asp.net
摘要:本文將通過一個實際案例來詳細剖析如何?一個ASP.NET 2.0網站開發過程中的全球化與本地化問題。
一、簡介
全球化和本地化是每一位開發人員在建立全球化產品或應用程式時必須清楚的兩個重要的慨念。儘管有許多文章對這個題目作過較好的解釋,但是我一直沒有看到一篇全面而綜合地討論關於全球化/本地化的所有重要概念的文章。本文旨在通過一個具體案例來詳細分析使用ASP.NET2.0開發一個web應用程式時所涉及到的全球化問題。
二、背景理論
全球化是應用程式開發中某一階段的任務,其目的是使程式能夠跨多個文化地區可用而不必顧及語言和地區性差別。例如,你在開發一個小型庫存管理程式,而你生活在例如英格蘭這樣一個以英語為主要語言的地區。現在,如果你想把你的程式賣到另一個不同國家,比方說是德國,那麼你需要確保你的程式以德語顯示並實現輸入。
本地化是使用一種地區特定的文化和語言來建立內容、輸入和輸出資料的過程。文化將會影響日期顯示設定(如是mm/dd/yyyy還是dd/mm/yyyy),貨幣顯示格式等。現在,確保我們的程式能夠被本地化的過程稱為國際化或全球化。用更簡單的術語來說,全球化能夠被定義為一組活動,通過這一活動,可以確保我們的程式能夠運行在使用不同語言和文化的地區。
因此,全球化是與內在代碼的改變相關聯的以便支援這樣的改變,如使用資源檔等;而本地化是使用一種特定的文化和地區性資訊的過程,以便該程式能夠使用本地的語言和文化。這意味著要把字串翻譯成一個特定的本地的語言;為此,要把語言特定的字串放到資源檔中。一般地,應該從主構建和代碼開發階段就開始考慮全球化問題,而本地化通常在以後才實現。
三、 實現ASP.NET 2.0網站的全球化
讓我們從一個簡單的樣本開始。為瞭解釋本地化並使事情儘可能簡單,我使用ASP.NET和C#建立了一個稱為TestSite的新網站(詳見本文下載的源碼);我添加了一個MasterPage和一個預設頁面。這個預設頁面中含有一個TextBox和一個Calendar控制項;該TextBox控制項有一個描述貨幣的雙精確度型實數。在本例中,我們會看到隨著使用者選擇不同的語言貨幣格式發生相應的變化。當我運行該應用程式時,此預設頁面看起來如下所示:
我已經出版了這個測試web應用程式,你可以在下列URL處看到它的功能版本:http://63.134.215.124/testsite/default.aspx
四、 文化和本地化
首先,讓我先解釋一下文化和本地化。
一般地,語言也依賴於地理位置。例如,法語既是法國人的語言也是加拿大人的語言(除此之外,還有其它許多國家也說法語)。但是從語言角度來講,加拿大法語不同於法國法語。同樣,在美國英語和英國英語之間也存在一定的區別。因此,語言常常需要與說該語言的特定地區相聯絡,並且這是通過使用本地化(語言+地理位置)實現的。
例如,fr是法語語言的代碼,而fr-FR意味著法國使用的法語。因此,fr僅指定了這種語言,而fr-FR才實現了本地化。同樣,fr-CA定義另一個代表加拿大法語和文化的本地化。如果我們僅僅使用fr,那麼它僅代表是一種中立性質的文化(也即是,地區中立)。
那麼,我們如何定義或改變當前文化呢?
在.NET FCL(架構類庫)的CultureInfo類中存在兩個屬性,我們可以通過重載該類的構造器來對它們進行設定,然後使用它來改變當前執行線程的文化:
1.UICulture:取得/設定當前執行線程的使用者介面。這個屬性協助運行時刻從一個特定的資源檔(我們將在後面看到)中載入資源字串。這個屬效能夠使用中立文化,也可以是本地化。例如:
Thread.CurrentThread.CurrentUICulture = new CultureInfo("fr");
或:
Thread.CurrentThread.CurrentUICulture = new CultureInfo("fr-CA");
2.Culture:取得/設定地區特定的文化和貨幣、日期等的格式。這個屬性需要語言也需要位置(本地化)。
Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-A"); //正確,因為我們已經給出了本地化
Thread.CurrentThread.CurrentCulture = new CultureInfo("fr"); //錯誤,無法工作
有時,我們需要一種不屬於任何語言或本地化的文化,對於任何地區/語言都不變。為此,我們可以使用CultureInfo.InvariantCulture屬性。這一屬性在內部系統處理期間使用;此時,要求是文化獨立的,或者儲存不需要被直接顯示給終端使用者的資料。
UICulture和Culture屬性都能夠在Web.Config檔案的<GLOBALIZATION>屬性中進行定義。另外,它們還能夠在頁面級上被指定。但是,我們不想寫入程式碼這些值而是喜歡動態地設定它們。由上面可知,我們還能夠使用Thread.CurrentThread.CurrentCulture和Thread.CurrentThread.CurrentUICulture屬性以編碼方式得到/設定這些值。因此,我們將在本應用程式中使用這些屬性。
五、本地化切換
現在,回到我們的應用程式中來,我們需要一種方法實現本地化切換。為此,存在兩種方法:
1.使用瀏覽器設定:在IE中,使用者可以通過使用"Internet Options->General->Languages"來改變文化。為此,我們需要把Culture和UICulture都設定為auto並且把enableClientBasedCulture設定為true,如下所示:
< GLOBALIZATION culture="auto" uiculture="auto" enableClientBasedCulture=""true"" />
2.使用者指定的設定:我們能夠向使用者提供一個選項以便其在運行時刻指定和改變文化和語言。這是推薦的方法,因為有時瀏覽器本身可能沒有提供使用者特定的語言集(例如一個法語旅遊者可能在印度上網)。而且,有時經由瀏覽器修改語言設定將會被阻斷。
現在,我們使用第二種推薦的方法,我在MasterPage上部(在一個面板控制項內)建立了一個節;此處,我使用了一個具有這些語言選項的下拉式清單方塊以便讓使用者選擇一種特定的本地化表達。
在本樣本中,僅為了說明問題,我僅使用了四種語言選項:
Hindi,American English,British English和French。
為了實現我的應用程式的全球化,我的目標是:無論使用者何時選擇一種特定的本地化語言,下列都應該發生:
1.所有內容都應該是本地化的:這意味著,所有字串和文本應該以選擇的語言和本地化顯示。
2.每個控制項的標題(/內容)也應該以本地語言顯示文本。
3.日期和貨幣格式化應該根據選擇的本地化發生。
4.所有顯示給使用者的訊息應該是使用本地的語言。
為了達到以上目的,你首先要確保從代碼中取出此內容並把它放在單獨的資源檔中,在.NET中這是一些具有.resx副檔名的簡單的XML檔案。
由於這些內容將因語言不同而有所不同,所以,我們針對每一種文化(語言)各自建立了相應的資源檔。每一個這樣的檔案中都提供了Name和Value兩個域。下面是在兩個資源檔中的樣本入口;在此,假定我們必須輸入一個字串"Welcome":
1.添加一個新的資源檔並命名它為TestSiteResource.resx,並且使用VS編輯器開啟它。在Name域輸入"Banner",在Value域輸入"Test Website for Localization"。這個資源檔預設使用的是美式英語。
2.添加另一個資源檔並命名它為"TestSiteResources.fr-FR.resx"。這個檔案相應於法語字串。在Name域中添加"Banner",在Value域中添加"Examinez le site Web pour le comportement de localisation"。
如果你想添加加拿大法語資源,那麼,你需要建立另一個資源檔"TestSiteResources.fr-CA.resx"。這個名字的中間部分定義了本地化,並且它應該與通過UICulture屬性指定的相同。
3.這些檔案將被儲存在ASP.NET 2.0的App_GlobalResources檔案夾下。
【提示】如果你僅想在某些頁面上顯示本地化字串,那麼,通過把資源檔放到App_LocalDirectory檔案夾下,你可以在整個應用程式中限制本地化行為。這樣將使得本地化成為頁面特定的,而不是全應用程式範圍內的。這些命名應該如下所示(假定你僅想本地化一個名為MyPage.aspx的頁面):
MyPage.aspx.resx:這是MyPage.aspx的預設的資源檔。
MyPage.aspx.fr-FR.resx:當文化改變為French時,將使用它,但是僅僅應用程式中的MyPage.aspx被本地化。
所有上面的.resx檔案將被編譯到運行時刻程式集中。這些程式集被稱作"小程式集",並且為.resx檔案提供了強型別封裝器。因此,我們不需要擔心在ASP.NET 2.0中由我們自己來建立資來源程式集的問題。在你發行你的網站後,這些程式集被放在/bin檔案夾下的單獨的檔案夾中(名字為locale):
對於非ASP.NET應用程式,我們需要使用兩個工具:
1.資源檔產生器(resgen.exe);
2.程式集連結器(al.exe)。
在MSDN中存在大量有關如何使用這些工具的詳細資料。有興趣的讀者可以找來看看。
現在,既然我們已經針對不同文化和語言建立了資源檔,那麼接下來,當使用者動態地改變文化時,我們需要一種方法來在運行時刻載入它們。幸好實現這一點在ASP.NET 2.0中相當容易。請見下面的代碼:
String welcome = Resources.TestSiteResources.Welcome;
在這行代碼中,我們使用了Resources命名空間,它是由ASP.NET自動建立的,這時它把資源檔編譯成"小"程式集並且我們使用與我們建立的資源檔名相同的TestSiteResources類。然後,我們存取Welcome屬性,它將基於當前文化從資源檔中提供實際的文本。如果我們想得到標籤控制項lblWelcome的文本,那麼,我們可以使用ASP.NET 2.0中提供的兩個方法來進行相同的設定:
1.隱式本地化:在此,我們指定在控制項定義中的新的元標籤並且讓ASP.NET基於resourcekey屬性從資源檔中取得該值:
<asp:Label id=lblWelcome meta:resourcekey="lblWelcome" Text ="Welcome"
runat=" server "></asp:Label>
為了使這能夠工作,我們需要把頁面特定的資源檔放到/App_LocalDirectory檔案夾下。隱式本地化有助於縮小全域資源檔的大小並且有助於改進全域資源管理。當你有大部分頁面特定的內容時,你可以使用這種方法。
你不需要手工地做任何事情來設定這些隱式本地化屬性。只要在設計方式下開啟你的web頁面,然後轉到"Tools->Generate Local Resources"。這將為你的頁面自動地建立一個資源檔。在Visual Studio 2005資源檔編輯器中,你僅需要針對每一個控制項設定不同的域值(Control.Property)。
2.顯式本地化:當我們擁有全域資源檔時使用這一技術。在此,我們使用運算式來從資源檔中設定值,如下所示:
<asp:Label id=lblWelcome Text ="<%$ Resources:TestSiteResources, Welcome %>" runat=" server ">
</asp:Label>
我們能夠使用VS IDE實現這種設定。選擇標籤控制項,轉到其屬性視窗,選擇"Expressions->Text"。然後,從下拉框中選擇"Resources"並輸入類名(在這個樣本中是,TestSiteResources)和Resource鍵(Banner)。這是本地化一個頁面中的UI控制項的推薦方式。
3.以編程方式訪問強型別化資源類,如下所示:
lblWelcome.Text = Resources.TestSiteResources.Welcome;
這種方法可以工作,但是它需要針對頁面中的每一個控制項進行編碼。因此,你可以對所有的控制項使用第二種方法,而且使用這個方法來存取相應於其它內容的資源字串(如果需要的話)。還應注意,象Calendar控制項這樣的控制項都實現了內建的本地化功能。一旦當前線程的UICulture和Culture發生改變,它就會自動地顯示本地化內容,這一切都歸功於ASP.NET!