我們會看到很多支持多語言的網站,有些早期的網站在首頁會有一個鏈接,讓用戶自己來選希望看到中文,還是英文,現在的網站則不需要了,這些網站可以根據用戶使用的語言來顯示不同語言的版本。比如,你在使用簡體中文,打開網頁,會看到一個簡體中文的網頁,你在使用英文,輸入同一個地址,就會看到一個英文的頁面。
服務器是如何知道用戶希望看到何種語言版本的頁面呢?
瀏覽器端
對於網站來說,一個網站要服務海量的用戶,使用服務器來記住用戶的語言是很麻煩的,這個工作還是從瀏覽器開始,如果瀏覽器自己告訴服務器希望使用的語言,服務器不就簡單了嗎?
各種瀏覽器都可以設置希望使用的語言,在 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 對象。