冠军 阅读(163) 评论(0)

 我们会看到很多支持多语言的网站,有些早期的网站在首页会有一个链接,让用户自己来选希望看到中文,还是英文,现在的网站则不需要了,这些网站可以根据用户使用的语言来显示不同语言的版本。比如,你在使用简体中文,打开网页,会看到一个简体中文的网页,你在使用英文,输入同一个地址,就会看到一个英文的页面。

服务器是如何知道用户希望看到何种语言版本的页面呢?

浏览器端

 对于网站来说,一个网站要服务海量的用户,使用服务器来记住用户的语言是很麻烦的,这个工作还是从浏览器开始,如果浏览器自己告诉服务器希望使用的语言,服务器不就简单了吗?

各种浏览器都可以设置希望使用的语言,在 IE 中,选择设置,弹出对话框之后,可以设置语言首选项。

点击语言,弹出语言首选项对话框。

在控制面板中进行设置。

对于 Chrome 来说,在高级设置中。

点击语言和输入设置。

当浏览器向服务器发出请求的时候,浏览器会在请求头中添加一个特殊的请求头 Accept-Language 来说明浏览器端设置的语言类型,如果你刚才注意的话,会发现我们可以设置多个语言,而且可以调整顺序,在 Accept-Language 头中,它们按着你设置的顺序依次出现。每种语言使用逗号 (,) 进行分隔。

各种浏览器的 Accept-Language 如下所示。

IE 的语言

Accept-Language en-US,en;q=0.8,zh-Hans-CN;q=0.5,zh-Hans;q=0.3

Chrome 的语言

Accept-Language:zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.4

FireFox 的语言

Accept-Language: en-us,zh-cn;q=0.8,en;q=0.5,zh;q=0.3

慢着,q 又是什么呢?在 HTTP 协议中有一个详细的说明,点击这里的链接可以查看详细说明: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html。简单来说,语言可以携带一个“q”值,来表示用户对该语言的喜好程度,这个值在 0 - 1 之间,默认为 1。

 服务器端

在我们服务器端代码中,可以直接获取到浏览器在请求中携带的语言设置,在 .NET 中,HttpRequest 表示浏览器发出的请求,属性 UserLanguages 就表示 Accept-Language 中传递的语言,已经根据优先级进行了排序,而且已经根据逗号 (,) 进行了拆分。这个属性是一个字符串数组。

代码中

string[] languages = Request.UserLanguages;

比如,我们希望取出第一个语言,就可以通过 Request.UserLanguages[0] 来获取到了。

获取的语言从程序的角度来说仅仅是一个表示语言的字符串,从面向对象的角度来说,我们需要一个对象来表示语言,这个类就是 CurtureInfo 类,它定义在命名空间 System.Globalization 中。可以通过 MSDN 来查看它的定义

通常,我们将表示语言的字符串通过构造函数传递给 CultureInfo。

CultureInfo info = new CultureInfo(culture);

 

中文问题

如果你刚才仔细查看的话,会发现 IE 发送的语言代码与 Chrome 是不一样的。你会发现表示简体中文实际上有四种写法:

  • zh
  • zh-cn
  • zh-Hans
  • zh-Hans-CN

 这些写法是从哪里来的呢,在 MSDN 中有详细的说明

CultureInfo    类将根据 RFC 4646 为每个区域性指定一个唯一的名称。  名称是语言关联的 ISO 639 小写双字母区域性代码和国家/地区关联的 ISO 3166 大写双字母子区域性代码的组合。

比如 zh 就表示中文,Han: 汉字 ,S: Simplified 简体字,T: Tranditional 繁体字,而 cn 表示中国地区代码。

区域性名称的格式为 两个小写字符的语言代码>-两个大写字符的国家地区码。 例如 “zh-CN” 代表“中文(简体中文)”,“en-US”代表“英语(美国)”。 在双字母语言代码不可用的情况中,将使用从 ISO 639-2 派生的三字母代码。

请注意,某些区域性名称还指定 ISO 15924 书写符号。 例如,中文有简体和繁体之分,这种名称可以使用 两字符的语言码-书写标记-两字符的国家地区码形式。 例如“zh-Hans-CN”代表“简体中文(中国)”。 对于 Windows Vista 之前的操作系统,包含书写符号的区域性名称使用languagecode2-country/regioncode2-scripttag 的模式,例如“uz-UZ-Cyrl”代表“乌兹别克语(乌兹别克斯坦,西里尔语)”。

非特定区域性只能由双字母小写语言代码指定。 例如,fr指定“法语”的非特定区域性,de指定“德语”的非特定区域性。

那么,zh 就表示非特定区域的中文,en 就表示非特定区域的英文。

但是,需要注意的是,CultureInfo 不支持 zh-Hans-CN 写法,如果你使用了,会收到这样一个异常。

zh-Hans-CN 是无效的区域性标识符。

你可以使用 zh,  zh-cn, zh-Hans, 但是,不能使用 zh-Hans-CN 来构建 CultureInfo 对象。