多语言界面 Web 站点的几个 Tip

公司里做一个内部管理用的 Portal,主要实现考勤、工作日报、项目管理等功能。因为是日本公司,老板不太懂中文,但员工的日文水平也不是非常好,因此 Portal 定为多语言(简体中文、日文、英文)界面。

1. 使用资源存储所有的界面文本:

这一条应该是工作量最大、最繁琐、也是最基础的部分,页面中的涉及到的所有文本(包括标签上的文字、出错的提示信息等)都要写入资源文件;然后,页面 Load 时,把文本从资源中读出写到那些 Label 里。

我们可以使用 {0} {1} 这样的占位符代替一些需要插入变量的地方,加载资源时,使用 String.Format 方法填充这些占位。(当然占位符是可以有格式信息的,比如日期类型的,{0:g} 等等。)
如果使用占位符,请注意一点:如果资源中找不到该资源项,或者说找到的是空字符串,那么在 String.Format 时将有可能出错。所以请务必保证该资源项存在。

2。资源文件的命名

依照一定的规则,如根级非固定区域性资源文件名为:strings.resx,那么 zh-CHS 的资源文件名应为:strings.zh-CHS.resx;类推,zh-CN 的资源文件应为 strings.zh-CN.resx。

3。固定区域性与非固定区域性

固定区域性代码,如:zh-CN(中文-中华人民共和国),zh-HK(中文-香港,SAR),en-US(英语-美国),ja-JP(日语-日本)。非固定区域性,如:zh-CHS(简体中文), zh-CHT(繁体中文),en(英语),ja(日语)。系统查找资源时,如为 zh-CN 的区域查找资源,会首先查找 zh-CN 的资源是否存在;如果没有找到,会自动查找其“父级”的非固定区域性,即 zh-CHS 的资源;如果依然没有找到,则使用 InvariantCulture (根级非固定区域性资源)。

因为 zh-CN, zh-SG, zh-MO 这些固定区域都同用 zh-CHS 简体中文,大多数文本应该是一样的;如果使用 zh-CHS 制作简体中文资源,则其子级的 zh-CN, zh-SG, zh-MO 都将使用此简体中文资源;个别不一致的资源项,可以单列在各子区域性的资源文件中。

根据上述特点:(a.)优先制作 zh-CHS, en, ja 这样的非固定区域性的资源。(b)如果 zh-CN 和 zh-SG 或 zh-MO 在某些资源项目不同,可以单列。这样便于兼容更多的区域性。

4。不同的固定区域性有不同的日期时间数字显示格式:

简单来说,用得最多的是 DateTime 的显示格式,在不同区域性中应该为访问者提供符合其区域性的格式。比如:我们平常喜欢使用的 DateTime.ToString("yyyy-M-d") 方法,在不同区域性的输出结果都是一样的,不符合我们的目的,应该使用 DateTime.ToString("d")、DateTime.ToString("f") 这样的方式,在不同区域性中输出不同的格式。(如:"d"时:zh-CN: 2004-9-11;  ja-JP: 2004/09/11;  en-US: 9/11/2004)

需要注意的是,这些必须跟固定区域性相结合。非固定区域性无从谈起此格式,比如同使用英语的美国和英国,其格式也是有差异的。

5。在页面上放置你的语言选择 DropDownList:

将其 AutoPostBack 属性设置为 true;对应三种语言的 ListItem 的 Value 属性分别为:en-US, zh-CN, ja-JP。

在语言选择 DropDownList 的 SelectedItemChanged 事件中:我们需要改变当前会话的区域性。简单的方式是:通过 Page 类的两个只写属性(write-only):string Culture 和 string UICulture(这两个是只写的,不能读取,在“.NET 类库文档”中看不到它们)。Culture 需要赋以固定区域性的代码,UICulture 除了接受固定区域性的代码外,还接受非固定区域性的代码。一般的,我们可以赋值,比如:Culture="zh-CN", UICulture="zh-CHS"(当然这里也可以直接写 "zh-CN" 的)。

事实上我们发现,这样的做法是有问题的,界面并没有直接改变语言。为什么呢?因为 DropDownList 的这一事件发生在 Load 之后(参看我的另一篇文章),而我们的那些 Label 中的文本就是在 Load 这一步加载的。

我使用 cookie 来记录用户对于语言的偏好(其实我还记录其他一些偏好信息,比如分页的时候每页的记录条数,喜欢的模版等)。因此,我的方案是:在 SelectedItemChanged 事件中向访客浏览器发放带有该语言标记的 cookie (我称之为“语言票”),然后直接 Response.Redirect(Request.Url.ToString()),重新“载”入页面。

这个还不够,我需要在页面 Load 之前解析“语言票”、确定并指定区域性。为了简便起见,我们在系统所有 Web Form 的基类 PortalPageBase (它是从 System.Web.UI.Page 继承来的)中写这些代码,在 OnInit 里解析“语言票”,并分别为 Culture,UICulture 这两个只写属性赋值。

(还有一些注意事项,未完待续吧……) 下一篇

posted on 2004-09-10 20:54  破宝  阅读(205)  评论(0编辑  收藏  举报

导航