关闭

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

标签: 语言websql serversession数据库存储
686人阅读 评论(0) 收藏 举报
分类:
转自:http://blog.joycode.com/percyboy/archive/2004/09/10/33142.aspx

公司里做一个内部管理用的 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 这两个只写属性赋值。

6。关于文本排序:

不同语言对相同字符的排序可能是不同的,西方语言中,比如:瑞典语和德语都有字母“Ä ”,但瑞典语这个字母是在 Z 之后;德语是在 A 之后。西方语言的这种情况,我们接触的不多。

这次做的是简体中文、英语、日语三语言。比如中文和日文中都有汉字,但简体中文是按汉语拼音排序的,“学”(xue) 在 “生”(sheng) 之后;日语是按假名排序的,“学”(がく) 在 “生”(せい) 之前。

文本的排序,在 .NET 程序内部是跟区域代码关联的,具体到 ASP.NET 站点,我们在上一篇中为 Page.Culture 赋值 "zh-CN" 之后,如果比较“学”和“生”的话,就会按照已经指定的语言来比较、排序。

但这是在程序内部,可实际情况往往是:比如分页显示上万条数据时,我们是在数据库中排好顺序,只取出一页(20条或者40条或者 pageSize 条)的数据,返回给程序处理;如果我们在程序里只是对这 20条或者 40条数据排序的话,这只是将对已取出的这 20或40条记录排序,当然不是我们想要的效果。

也就是说这个排序规则需要在数据库端指定,在 Oracle 数据库的 PL/SQL 语言中,我们找到了

ALTER SESSION SET NLS_SORT = SCHINESE_PINYIN_M;

把这句话写在查询数据的存储过程/函数的最开始,则此存储过程/函数中的排序操作(ORDER BY ...)都将按汉语拼音排序;日语是

ALTER SESSION SET NLS_SORT = JAPANESE;

其他语言,我们可以使用默认的

ALTER SESSION SET NLS_SORT = BINARY;

传递一个代表不同区域的数字,在存储过程开始分别写上上面这句 SQL 即可达到预期的目的。

此处为错误!存储过程中不可以使用 ALTER SESSION ...,只能使用 NLS_SORT 函数!特修正:

SELECT ..... FROM .... WHERE ..... ORDER BY NLS_SORT(排序字段名, 'NLS_SORT=SCHINESE_PINYIN_M') DESC;

很遗憾,我在 SQL Server 的 T-SQL 语言中没有找到类似的操作(哪位知道的可以告诉我),据我目前所知:SQL Server 只支持的“静态”的排序规则,你可以给一个字符类型(char, varchar, text, nvarchar, ntext)的字段指定排序规则,但指定之后在存储过程中间不能改变这个规则,即一个字段只能按一种规则排序,不能动态改变。看来 SQL Server 暂时无法满足我们这个需求。

其他数据库的情况,尚不知晓,知道的朋友请留在下面,大家共同分享。

7。显示与程序内部处理的格式问题

比如,我们通过 Query String (查询字符串)传递一个日期参数到另一个页面,这时我们就应当使用和区域性无关的固定格式,如 DateTime.ToString("yyyyMMdd"),这样无论在何种区域性中我们都得到 20040911 的字符串,便于我们在另一侧“接收”。

也就是,内部处理需要通过文本传递时,使用和区域性无关的固定格式;而显示时使用和区域性相关的格式。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:397552次
    • 积分:5720
    • 等级:
    • 排名:第4495名
    • 原创:143篇
    • 转载:195篇
    • 译文:0篇
    • 评论:47条