四、多语言的实现
上一章讲的是如何实现与数据的连接,本章来讲一下多语言是如何实现的。
现在很多公司都已经开展了国际化的运作,所以多语言的支持已经成为必须要考虑的一个因素,现在能真正实现多语言的系统大多都比较昂贵。
本系统的多语言支持直接得益于asp.net本身,它们本身都是使用UTF-8格式来存储,不是传统的本地编码。在asp.net页面中,每个控件都可以为多个国家字符集指定不同的字符串,但是这种方式不太灵活,特别是很多内容都是从数据库中拼凑出来的时候。为此我采用了另外一种方式,类似于资源文件,只是直接把内容写入了web.config中,这样以明文的形式来存储,并且web.config文件更改后,网站可以实现自动更新,不需要重新起动IIS。
在web.config中,存储多语言的部分如下例:
<add key="STRING_EN_内容管理" value="Content" />
<add key="STRING_EN_系统管理" value="System" />
<add key="STRING_EN_权限管理" value="Privilege" />
<add key="STRING_RU_内容管理" value="содержание" />
<add key="STRING_RU_系统管理" value="Система" />
<add key="STRING_RU_权限管理" value="привилегированность" />
可以看出,是直接对<appSettings>进行的扩展使用,没有建立新的段,key分成三部分:
u STRING
u EN / RU
u 需要翻译的中文
STRING用来标识,在后面的程序中会用到,而EN表示需要翻译成何种语言,如果您需要其它语种,只要在这里指定即可,如上例就是指定了英文和俄文两个语言,加上默认的中文,共有三种语言支持。最后只要把翻译的结果写在value这个属性里即可。
在配置了这个文件后,看起来以后每写一个asp.net页面都需要写很多的程序去翻译里面的字符,其实不是这样的,我还定义了一个基类,继承自Page,命名为local,在这个页面的Page_Load函数中,自动搜索页面中所包括的各种控件,比如文本框,标签,按钮,甚至图片框等,然后根据当前指定的语言(可由Session中寻找,也可以由Post中查看),选择相对应的翻译,就实现了多语言。
上面也提到了图片框,在多语言环境中,很多图片里都固化了本地的文字,所以对图片也需要替换。我在网站的images目录中,根据不同的语言增加了相应的子目录,如images/EN images/RU 等等,在翻译的时候,会把图片的路径由 images/a.gif 拼接成 images/EN/a.gif这种样式,就实现了图片的自动替换,当然前提是您已经准备了充足的图片用于替换。
取得页面中的所有控件可以用下面的函数:
foreach(Control control in parent.Controls)
{
}
在数据库中,有一个专门的表ZR_LANG来存储当前系统所支持的语言,在登录界面(包括前端和后端)都会从这里判断,多语言选择需要支持哪些语言。
如果页面的标题写在asp.net的页面里,那么是不能利用上面的方式来翻译的,所以我专门做了一个Label,来存放标题的内容,然后在页面中按如下方式来引用标题:
<HTML> <HEAD> <title><%=lblTitle.Text%></title> ….
这样在运行后,就可以实现正确的标题的翻译了。
关于Grid表格,对于Caption的翻译,并不难做,但是需要根据不同的语言,对Grid中的实际内容进行翻译,这是比较难做的,我在这里用了一个小技巧来实现:把Grid中需要翻译内容的列的前面加一个空格,在实际工作中,遇到有空格的列,就表明其中的内容需要翻译,然后就一条条的翻译过来即可。为什么加一个空格呢,首先,它不会对显示有什么影响,另外,这样也可以区别对待,不需要翻译的列,就不需要使用此方式来占用过多的时间了。以下两个函数处理此事,请参考:
public static void LocalGrid(ref System.Web.UI.WebControls.DataGrid grid)
{
System.Web.UI.Page page = new System.Web.UI.Page();
if (page.Session["__LANGUAGE__"] != null)
{
if (page.Session["__LANGUAGE__"].ToString() == "TW" || page.Session["__LANGUAGE__"].ToString() == "EN")
{
string lang = page.Session["__LANGUAGE__"].ToString();
foreach( System.Web.UI.WebControls.DataGridColumn column in grid.Columns )
{
string text = column.HeaderText;
if (System.Configuration.ConfigurationSettings.AppSettings["STRING_" + lang + "_" + text] != null)
{
text = System.Configuration.ConfigurationSettings.AppSettings["STRING_" + lang + "_" + text];
}
else
{
if (lang == "TW")
{
text = Big5.GetBig5Code(text);
}
}
column.HeaderText = text;
}
}
}
}
/// <summary>
/// 本地化一个GRID里的内容
/// </summary>
/// <param name="grid">表格</param>
public static void LocalGridContent(ref System.Web.UI.WebControls.DataGrid grid)
{
System.Web.UI.Page page = new System.Web.UI.Page();
if (page.Session["__LANGUAGE__"] != null)
{
ArrayList cols = new ArrayList();
int i = 0;
foreach( System.Web.UI.WebControls.DataGridColumn column in grid.Columns )
{
string text = column.HeaderText;
if (text.Substring(0,1) == " ")
{
column.HeaderText = Tran(column.HeaderText);
cols.Add(i);
}
i++;
}
if (cols.Count > 0)
{
int cnt = grid.Items.Count;
for (int j = 0; j < cnt; j++)
{
foreach(object col in cols)
{
int colNumber = (int)col;
string content = grid.Items[j].Cells[colNumber].Text ;
content = Tran(content);
grid.Items[j].Cells[colNumber].Text = content;
}
}
}
}
}
到此,已经基本讲了多语言的一些实现方式,在后面一节会来重点讲一下本系统的控件结构。