原来用webForm开发的旧系统,因使用需要,由简体中文改支持多语言,改完后,登录时可以切换语言版本,如下图:
改造方案需要满足:改造工作量小,改造速度快,扩展性好;
方案一:编写资源文件
文件内容以Key-Value方式,每个语言一个文件,无法兼顾后端存储过程;
方案二:写数据库
表结构以Key-语言1,语言2..语言N的方式,扩展性好,前端和后端都能使用;
以上两种方案都不能满足以上三个要求;
虽然我的方案综合了以上两种方案,并创造性的增加了其他方法;
一、满足非服务端组件的改造要求
在我的项目中,前端有用到jQuery框架(具体名称就不说了),这个框架有实现国际化,一个语种一个js文件,选择不同语种时,用js引入部分加入动态的session即可自动切换;
二、满足服务端组件的快速翻译
WebForm页面中的各中有GridView、Label、Radio、Select、Text等服务端组件,需要翻译的属性有Text和ToolTip;按常规的做法是把Text和ToolTip的内容用一个函数(<%=getLangStr(“中文内容”) %>)替换之,我的方案服务端组件全部自动翻译,具体就是在page_load中调用ControlTrans函数,以下是函数实现:
/// <summary>
/// 语言翻译
/// </summary>
/// <param name="ctls"></param>
public static void ControlTrans(Control page)
{
foreach (Control item in page.Controls)
{
//以下判断的顺序不能更改,先子类后基类
if (item is GridView)
{
GridViewTrans((GridView)item);
continue;
}
if (item is ImageButton)
{
ImageButtonTrans((ImageButton)item);
continue;
}
if (item is ListControl)
{
ListTrans((ListControl)item);
continue;
}
//判断是否包含子控件,
if (item.HasControls())
{
ControlTrans(item);
continue;
}
if (item is WebControl)
{
WebControlTrans((WebControl)item);
continue;
}
}
}
/// <summary>
/// 翻译组件文本内容
/// </summary>
/// <param name="obj"></param>
private static void WebControlTrans(WebControl obj) {
if (obj.Attributes[DefTrans] != null)
{
return;
}
obj.Attributes.Add(DefTrans,"1");
if (obj.ToolTip.Trim() != "") {
obj.ToolTip = ShowData.getLangStr(obj.ToolTip.Trim());
}
List<PropertyInfo> infos=obj.GetType().GetProperties().Where(a => a.Name == "Text" || a.Name== "ErrorMessage").ToList();
for (int i = 0; i < infos.Count; i++)
{
string text = infos[i].GetValue(obj, null).ToString().Trim();
if (!string.IsNullOrEmpty(text))
{
infos[i].SetValue(obj, ShowData.getLangStr(text), null);
}
}
}
/// <summary>
/// GridView翻译
/// </summary>
/// <param name="grid"></param>
private static void GridViewTrans(GridView grid) {
if (grid.Attributes[DefTrans] != null) {
return;
}
grid.Attributes[DefTrans] = "1";
foreach (DataControlField item in grid.Columns)
{
if (item.HeaderText.Trim() != "" && item.Visible && !(item is TemplateField))
{
item.HeaderText = getLangStr(item.HeaderText.Trim());
}
}
}
/// <summary>
/// DropDownList翻译
/// </summary>
/// <param name="list"></param>
private static void ListTrans(ListControl list)
{
if (list.Attributes[DefTrans] != null)
{
return;
}
list.Attributes.Add(DefTrans,"1");
foreach (ListItem item in list.Items)
{
if (item.Text.Trim() != "")
{
item.Text = getLangStr(item.Text.Trim());
}
}
}
一个aspx页面加cs文件的修改一般不会超过10分钟改完,60个页面,对自已狠一点一天就改完了,达到了快速的目地;
三、数据结构设计的优化
常规的方法是将key的内容为一个或多个单词,但我做了优化,我的Key就是简体中文的内容,
系统在翻译时,是以原来WebForm的中文做为关键值来搜索需要翻译的语言,这样做可以省去创建key值的时间,实现创建Key值自动化;只要打开一下页面,WebForm中要翻译的内容全部写入数据表。
注意乱码问题,aspx创建时应为utf8编码,字段类型应为nvarchar
四、合理利用静态变量,提升性能
按常规的方法,每翻译一次就查一次肯定性能上会有问题,特别是多人操作的系统;
我的方案是首次调用getLangStr函数时,系统会一次性加载全部翻译记录(用到了线程安全集合类ConcurrentBag),后续的调用都从集合中查询。这个类是一个静态变量,实现全局性,避免被反复初始化,提升了翻译的性能。
五、合理利用百度翻译
百度提供了翻译接口(http://api.fanyi.baidu.com/api/trans/product/index),可以支持28种语言的互译,自然我们要利用好这个资源,自已写了一个批量翻译的工具(如下图),一键翻译,后台数据表中的中文转其他语言就搞定了;
当然,百度翻译的结果是需要较对的,机器就是机器,翻译出来并不是完美的,但比从头到尾翻译要快多了;因此,在系统中增加一个较对的界面是必不可少的,如下图:
通过以上方案的实践,符合改造的三个要求,改造工作可以减少60%;
以上方案分享出来只是希望对准备改造的朋友多一种思路和方法,也希望大家提出更多的建议;