前天將我的 Windows 8 安裝了簡體中文的 Language pack (語言套件),設定上去後連到我的部落格網站立刻出現嚴重的例外錯誤,因此注意到從 Windows Vista / .NET 3.0+ 開始針對繁體中文與簡體中文的 Language Tag 已經都改用 IETF 的標準表示字串,原本我們常用 zh-CHT 代表繁體中文,爾後都會改用 zh-Hant 來表示,若是簡體中文則是 zh-Hans。然而重點是 ASP.NET 2.0 並不支援讀取繁體中文的 zh-Hant 與簡體中文的 zh-Hans,只要嘗試讀取就會立刻引發例外狀況,這是各位開發人員應該注意的地方。
首先,我必須聲明這樣的改變完全是為了因應 IETF 標準的變化所致,zh-Hant / zh-Hans 這樣的 Language Tag 是從 2006 年才被定義出來(RFC 4646),在這之前我們要表示不含地區特性的中文,都會採用 zh-CHT 或 zh-CHS,然而之後才被定義成 zh-Hant / zh-Hans。
我們從 IE9 的「語言喜好設定」的畫面來看,如下圖示,通常台灣這邊的預設語言都會是 中文 (繁體,台灣) [zh-TW],當你新增語言的時候有個選項叫做 中文 (繁體) [zh-Hant],兩者的差異就在於 zh-TW 是含有地區特性的 Language Tag,而 zh-Hant 為通用於「中文繁體」的語系,並沒有區分台灣、香港或澳門之間的文化差異。
若用 Fiddler 來看從瀏覽器送出的 Accept-Language 標頭,可以發現他送出的 Language Tag 是 zh-TW
而 ASP.NET 的多國語系功能支援,就是依賴這個 HTTP Header (Accept-Language) 的值來判斷瀏覽器的語系,藉此送出不同語系資源的內容。由於我的部落格有內建多國語系功能,前天將我的 Windows 8 Consumer Preview 安裝了簡體中文的語言套件(Language pack),設定上去後連到我的部落格網站立刻出現嚴重的例外錯誤:
我查了一下 事件檢視器 (Event Log),得到以下錯誤訊息:
- Exception type: NotSupportedException
- Exception message: Culture 'zh-Hant' is a neutral culture. It cannot be used in formatting and parsing and therefore cannot be set as the thread's current culture.
- Stack trace:
at System.Globalization.CultureInfo.CheckNeutral(CultureInfo culture)
at System.Threading.Thread.set_CurrentCulture(CultureInfo value)
at System.Web.HttpApplication.ThreadContext.SetRequestLevelCulture(HttpContext context)
at System.Web.HttpApplication.ThreadContext.Enter(Boolean setImpersonationContext)
at System.Web.HttpApplication.OnThreadEnterPrivate(Boolean setImpersonationContext)
at System.Web.HttpApplication.PipelineStepManager.ResumeSteps(Exception error)
at System.Web.HttpApplication.BeginProcessRequestNotification(HttpContext context, AsyncCallback cb)
at System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context)
看到這個錯誤很直覺的會想到應該是多國語系的地方出了問題,因此我就在我的 Windows 8 主機安裝 Fiddler 來分析我從 Windows 8 的 IE10 到底送出了什麼 Accept-Language 內容過去,如下圖示:
備註:你也可以用 IE10 內建的開發者工具進行 HTTP 封包分析。
果不其然,IE10 送出的 Language Tag 並不是常見的 zh-TW 而是 zh-Hant,這個例外並不是網站本身程式所造成的,而是 ASP.NET 在 自動判斷 文化特行的時候發生了錯誤。下圖我列出了我網站 web.config 所列出的 <globalization> 設定值,造成錯誤的地方正是如圖箭頭處所指出的 culture="auto" 設定。
解決辦法也很簡單,就是是不要自動判斷 culture 的文化特性,將該屬性移除即可。
請注意:設定 uiCulture="auto" 一樣可以讓全域資源檔或區域資源檔正常運作,所以大部分情況下是不會有問題的,這裡的 culture 主要是針對數字、貨幣、時間、日期等地區特性進行判斷。
而我剛剛也針對 ASP.NET 2.0 , 3.5 , 3.5 SP1 , 4.0 進行測試,發現要 ASP.NET 4.0 之後才不會出現例外狀況,所以如果你的 ASP.NET 應用程式需要針對數字、貨幣、時間、日期等地區特性進行自動判斷,恐怕需要在 Global.asax 裡多寫程式額外判斷才行,相關範例可參考我的另一篇文章【如何讓 ASP.NET 依據瀏覽器指定的語系自動選用資源檔】。
這問題也許只會出現在 Windows 8 Consumer Preview 這個版本裡,因為目前這一版的 IE10 並無法選取內含地區特性的語系,所以你並無法選擇 zh-TW 或 zh-CN 這些語系,這點實在讓我非常困擾。
在 IE9 以前的語言喜好設定都可以很自由的個別設定,跟作業系統不會有直接的關聯,但是在 Windows 8 裡的 IE10 卻跟作業系統綁的緊緊的,以下是在 IE10 設定不同語系的步驟圖示:
1. 開啟「網際網路選項」並點選「語言」按鈕,目前這步驟跟之前的 IE 版本都一樣:
2. 在設定語言喜好設定的介面,跟前一版已經不一樣了,現在這一版變成要開啟作業系統裡的語言設定
3. 這時你會開啟控制台裡的語言設定,你必須在這裡挑選語言,而且無法預覽或選擇含地區特性的語系,我也找不到任何可以選擇 zh-TW 這個 Language Tag 的選項,希望在未來的 Windows 8 版本能夠解決這個問題。
註:文化特性這部份真的有夠錯綜複雜的 @_@
相關連結