利用.net2.0的資源文件實現多語言開發!

我個人覺得這個是比較重要的,所以想寫清楚點,自己也一直在研究用xml實現!
但是還沒投入實踐,技術有限,我也纔剛進入社會的學生而已!!
等做出來再寫篇blog和大家分享
不過本人也是菜鳥,所以有什麼地方寫錯了,希望大家能多多指教!
首先我在最後面貼了一篇很好的文章,希望大家先去看看那個再來實際操作我的例子!這樣肯定ok,不然我估計大家看我例子到後面會傻掉,呵呵!~
首先我會講自己如何實現的一步步講給大家聽


首先我做的項目裏前臺和後臺都需要實現多語言!後臺因爲是用的母版,所以有點不一樣!我先跟大家講一下我前臺是怎麼實現的:

1.首先在配置文件裏中添加一個名爲LanguagePreference的基於字符串的配置文件屬性來支持匿名識別用戶區域性的功能。
  請注意anonymousIdentification元素的enabled屬性必須爲“true”,否則匿名識別功能就不可用。
  <!--此節是爲了讓系統自動爲匿名用戶生成唯一標識,另外的allowanonymous屬性表示languagepreference屬性可以被匿名用戶訪問-->
  <anonymousIdentification enabled="true"></anonymousIdentification>
  <profile>
   <properties>
    <add name="languagePreference" type="string" defaultValue="Auto" allowAnonymous="true"></add>
   </properties>
  </profile>

 

2.在主頁面加上一個dropdownlist,記得打開他的autopostback屬性
  <asp:DropDownList ID="drdlstLanguageList" runat="server" AutoPostBack="True" OnSelectedIndexChanged="drdlstLanguageList_SelectedIndexChanged" Width="65px">
                                    <asp:ListItem Value="Auto" Text="請選擇語言"></asp:ListItem>
                                    <asp:ListItem Value="en-us" Text="英語"></asp:ListItem>
                                    <asp:ListItem Value="zh-cn" Text="簡體中文"></asp:ListItem>
                                </asp:DropDownList>


3.//通過下拉菜單選擇頁面顯示語言
    protected void drdlstLanguageList_SelectedIndexChanged(object sender, EventArgs e)
    {
        Profile.languagePreference = drdlstLanguageList.SelectedValue;
 //這裏會強制發生一次從瀏覽器到 Web 服務器的新往返程,從而在使用所需的語言首選項設置了配置文件屬性後,重新啓動頁面的生命週期。
        Response.Redirect(Request.Url.AbsolutePath);
    }

4.編寫一個PageBase類,也就一個cs文件,只不過它繼承自System.Web.UI.Page,並作爲站點中所有頁面類的基類。
這麼做的目的其實很簡單,就是爲了將各個頁面中一些共同的處理過程提煉出來放到基類中,以減少代碼重複,提高可維護性。
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

using System.Threading;
using System.Globalization;

/// <summary>
/// PageBases 的摘要說明
/// </summary>
public class PageBases:System.Web.UI.Page
{
 public PageBases()
 {
  //
  // TODO: 在此處添加構造函數邏輯
  //
 }

    protected override void InitializeCulture()
    {
        base.InitializeCulture();

        string language = (String)Context.Profile.GetPropertyValue("languagePreference");
 
     if (!String.IsNullOrEmpty(language) && (language != "Auto"))
            {
                Thread.CurrentThread.CurrentUICulture = new CultureInfo(language);
                Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(language);
            }
 
    }
}

 

5.這樣我們的多語言其實就差不多實現了,還差的就是利用資源文件開始大量的翻譯!
我們隨意選擇一個頁面,轉到他的設計頁面,然後工具/生成本地資源
這樣就會多出一個文件夾App_LocalResources,裏面還會多出一個和選擇頁面的名字項目的resx文件
例如剛選擇的哪個頁面是aa.aspx  那麼生成的資源文件就是aa.aspx.resx
那麼我們現在複製他,複製一個先,等大家明白了自己再加!
然後將他該成aa.aspx.en-us.resx,如果你需要其他語言就再複製文件,記得象aa.aspx.en-us.resx一樣要做更改!
這裏需要注意更改的部分必須象en-us一樣是區域性標識!
最後就是進行翻譯工作!

但是最後你會發現html裏的字無法實現多語言,而且母版裏的sitemap文件無法實現多語言!
(1)解決html文字顯示
     首先將打開相應的資源文件,添加鍵值;然後在需要頁面顯示的地方拖出一個Localize控件,將資源文件添加的內容綁定上去!
     如果內容是放在本地資源文件裏就這樣綁定<a href=Default.aspx><asp:Localize ID="LocalizeText" runat=server Text="<%$ resources:鍵的名稱 %>"></asp:Localize>
     如果內容是放在全局資源文件裏就這樣綁定<a href=Default.aspx><asp:Localize ID="LocalizeText" runat=server Text="<%$ resources:DisplayResource,鍵的名稱 %>"></asp:Localize>
  這裏大家一定不清楚,例如什麼是全局文件夾等等,所以我在開始就讓大家先看下我貼的一篇文章!表達能力太差,忘大家見諒,呵呵~!

 好/。。我們再來解決第二個問題!
(2)vsitemap文件如何實現多語言!
     有兩種方法,一是本地化web.sitemap,二是在不同的文化/語言中使用不同的sitemapprovider!不過第二種我也沒做過,因爲看到一文章上寫那種很麻煩而且沒成功!我也就沒去試
     什麼時候有時間試試再修改這篇文章!
     直接本地化web.sitemap有可分爲隱式表達式(implicit expression)和顯式(explicit)表達式。
     在web.sitemap中首先要增加enablelocalization,並把它設成true。
     其次,要爲需要翻譯的sitemapnode增加resourcekey,作爲資源文件中的標識。
   比如
    <sitemap enablelocalization="true"
       xmlns="http://schemas.microsoft.com/aspnet/sitemap-file-1.0" >
    <sitemapnode url="~/default.aspx" title="title"
        description="desc" resourcekey="yes">

    然後要增加相應的資源文件 web.sitemap.resx 和本地化的的資源文件(比如 web.sitemap.zh-cn.resx ),
    而且必須放在 app_globalresources 文件夾中(beta 1 中是 resources 文件夾)。
    資源文件中要增加的內容的名稱/標識(name)要和 web.sitemap 對應,按照上面的例子就是 yes.title 和 yes.desc

    如果要使用顯式表達式,先要在 app_globalresources 文件夾中增加公用的資源文件,比如appresource.resx。然後相應的 weib.sitemap 要作如下修改。

    <sitemap enablelocalization="true"
        xmlns="http://schemas.microsoft.com/aspnet/sitemap-file-1.0" >
    <sitemapnode url="~/default.aspx" title="$resources: appresource, yestitle"
        description="$resources: appresource, yesdesc">

 在資源文件中對應的名稱/標識就應該是 yestitle 和 yesdesc。
.............................................................................................................................................
好了,這樣就實現了!哎。發現自己文筆實在不怎麼的。。。希望不會誤導大家!下面是我說的很好的一篇文章,希望大家多多研究,肯定不會誤導你們,呵呵!
.............................................................................................................................................
這是一篇很好的blog,我覺得有必要粘過來讓大家深入瞭解以下資源化

首先我講一下我是怎麼實現的,首先申明,目前我還是用.net的資源文件實現的!
解析Asp.net中資源本地化的實現
 
        本文將從Asp.net實現資源全球化和本地化的基本概念入手,闡述在Asp.net1.1和Asp.net2.0中實現全球化和本地化的步驟、方法。

一.基本概念

1.爲什麼要實現資源的本地化?

        我們的站點可能爲全球各個國家和地區的人所瀏覽,每個國家和地區的人都有自身的語言文化特點。就拿咱們偉大的祖國爲例,中國大陸用簡體中文,港澳臺則使用繁體中文。另外各個國家對於貨幣、數字、日曆等信息的表達格式各有不同,我們國家多使用年月日的格式,而美國則是月日年。諸如此類的區別林林總總,我也就不多舉例了。爲了給我們的網站瀏覽者更好的用戶體驗,我們應該提供一個全球化的解決方案,只要用戶選擇了他的語言和區域,站點就按照他的語言文化習慣來展現頁面信息,這個過程可以叫做本地化。

2.區域性、固定區域性、非特定區域性、特定區域性

        區域性名稱遵循 RFC 1766 標準,格式爲“<languagecode2>-<country/regioncode2>”,其中 <languagecode2> 是從 ISO 639-1 派生的由兩個小寫字母構成的代碼,<country/regioncode2> 是從 ISO 3166 派生的由兩個大寫字母構成的代碼。例如,美國英語爲“en-US”。在雙字母語言代碼不可用的情況中,將使用從 ISO 639-2 派生的三字母代碼;例如,三字母代碼“div”用於使用 Dhivehi 語言的區域。某些區域性名稱帶有指定書寫符號的後綴;例如“-Cyrl”指定西里爾語書寫符號,“-Latn”指定拉丁語書寫符號。舉例:

區域性名稱
 區域性標識符
 語言-國家/地區
 
zh-CN
 0x0804
 中文-中國
 
zh-TW
 0x0404
 中文-臺灣
 
zh-CHS
 0x0004
 簡體中文
 
zh-CHT
 0x7C04
 繁體中文
 
en
 0x0009
 英語
 
en-US
 0x0409
 英語-美國
 
en-GB
 0x0809
 英語-英國
 
uz-UZ-Cyrl
 0x0843
 烏茲別克語(西里爾語)- 烏茲別克斯坦
 
uz-UZ-Latn
 0x0443
 烏茲別克語(拉丁)- 烏茲別克斯坦
 

         固定區域性不區分區域性。可以使用空字符串 ("") 按名稱或者按區域性標識符 0x007F 來指定固定區域性。固定區域性由CultureInfo類的InvariantCulture屬性來代表固定區域性的實例。固定區域性僅與英語語言關聯,不與任何國家/地區關聯。它幾乎可用在要求區域性的“全局化”命名空間中的所有方法中。如果你的程序進行字符串比較或大小寫更改操作,則應該使用 InvariantCulture 確保無論系統如何設置的區域性,行爲都將按照InvariantCulture所代表的英語語言的固定區域性來完成。但是,固定區域性必須僅由需要不依賴區域性的結果的進程(如系統服務)使用;否則,它得到的結果可能在語言上不正確,或者在文化上不合適。舉例:CultureInfo Invc = New CultureInfo("");
CultureInfo Invc = CultureInfo.InvariantCulture;這兩行代碼的作用相同,目的是獲得固定區域性實例。

        比如你現在要對一個DateTime的實例dateTime執行dateTime.ToString()方法。這個方法實際是使用你當前線程的CurrentCulture作爲默認的區域性,根據這個區域性將日期實例轉化爲相應的字符串形式。那麼如果我們此時不需要它按照線程或系統的區域性進行ToString操作,那麼我們應該用這個方法dateTime.ToString(“G”, CultureInfo.InvariantCulture)或者dateTime.ToString(“G”, DateTimeFormatInfo.InvariantInfo)。

        非特定區域性是與某種語言關聯但不與國家/地區關聯的區域性。特定區域性是與某種語言和某個國家/地區關聯的區域性。例如,“en”是非特定區域性,而“en-US”是特定區域性。注意,“zh-CHS”(簡體中文)和“zh-CHT”(繁體中文)均爲非特定區域性。

        區域性有層次結構,即特定區域性的父級是非特定區域性,而非特定區域性的父級是 InvariantCulture。CultureInfo類的Parent屬性將返回與特定區域性關聯的非特定區域性。如果特定區域性的資源在系統中不存在,或因其它原因不可用,則使用非特定區域性的資源;如果非特定區域性的資源也不可用,那麼使用主程序集中嵌入的資源。

3.實現本地化常用的類型、屬性和方法

        CultureInfo類表示有關特定區域性的信息,包括區域性的名稱、書寫體系和使用的日曆,以及有關對常用操作(如格式化日期和排序字符串)提供信息的區域性特定對象的訪問。CultureInfo類的實例化一般有兩個途徑,如下所示:
CultureInfo culture = CultureInfo. CreateSpecificCulture (name);
CultureInfo culture = new CultureInfo(name);

        二者的區別是,使用第一種方法,只能創建固定區域性或特定區域性的CultureInfo實例。如果name爲空字符串,則建立固定區域性的實例,如果name爲非特定區域性,那麼建立name 關聯的默認特定區域性的 CultureInfo實例。第二種方法,則是建立一個name所指定的區域性的CultureInfo實例,它可以是固定的,非特定的或特定區域性的。

        Thread類的CurrentCulture屬性用來獲取或設置當前線程的區域性。它必須被設置爲特定區域性。Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");如果Thread.CurrentThread.CurrentCulture = new CultureInfo("en ");就會報錯!

        Thread類的CurrentUICulture屬性用來獲取或設置資源管理器使用的當前區域性以便在運行時查找區域性特定的資源。這裏的資源管理器可以關聯爲ResourceManger類。
Thread.CurrentThread.CurrentUICulture = new CultureInfo("en");
Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");

        ResourceManger類可以查找區域性特定的資源,當本地化資源不存在時提供代用資源,並支持資源序列化。常用的ResourceManager的構造函數是public ResourceManager(string,Assembly)。其含義是初始化 ResourceManager類的新實例,它使用指定的根名稱從給定的Assembly中查找資源文件。所謂根名稱是例如名爲“MyResource.en-US.resources”的資源文件的根名稱爲“MyResource”。在根名稱的表達中可以加上命名空間,如“MyWebSite.Resource.UserFolder. MyResource”。而Assembly可以是需要調用資源文件的頁面所在的Assembly,如typeof(MyPage).Assembly。ResourceManager類的GetString方法用來獲得資源文件中的指定鍵的值。舉例:當已設置了線程的CurrentUICulture屬性之後按如下方法。
ResourceManager rm = new ResourceManager("items", Assembly.GetExecutingAssembly());
String str = rm.GetString("welcome");

如果想按照指定的區域性來獲得資源則按照如下寫法:
ResourceManager rm = new ResourceManager("items", Assembly.GetExecutingAssembly());
CultureInfo ci = Thread.CurrentThread.CurrentCulture;
String str = rm.GetString("welcome",ci);


二.在Asp.net1.1中實現資源本地化

        首先應在網站項目WebTest中建立一個Resource文件夾,在這個文件夾中存放整個項目公用的資源文件。比如我們建立了以下三個資源文件:MyResource.en.resx,MyResource.en-US.resx,MyResource.zh-CN.res。每個資源文件中都有兩個鍵值對,鍵值爲State和Address。在需要使用資源文件的頁面MyPage.aspx中調用資源文件,如下所示:
Thread.CurrentThread.CurrentCulture= CultureInfo.CreateSpecificCulture("zh-CN");
Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture;
ResourceManager rm = new ResourceManager("WebTest.Resource.MyResource", typeof (MyPage).Assembly);
Label1.Text = rm.GetString("State");
Label2.Text = rm.GetString("Address");

好了,這個時候Label1和Label2就按照MyResource.zh-CN.resx文件中的規定顯示“州”和“地址”。以上是一個最基本最簡單的本地化方法,這裏隱含着一些問題,我們來逐一解決並優化該方法。

1. 如何獲得用戶的默認區域性

        通過用戶瀏覽器“屬性”->“語言”選項裏的設置,取最上面那條作爲用戶的默認語言。
CultureInfo cultureInfo = CultureInfo.CreateSpecificCulture(Request.UserLanguages[0]);
Thread.CurrentThread.CurrentCulture = cultureInfo;
Thread.CurrentThread.CurrentUICulture = cultureInfo;

        一般情況下,設定CurrentCulture和CurrentUICulture具有相同的區域性,當然也可以不相同,比如你規定CurrentCulture爲en-US,而CurrentUICulture爲zh-CN。那麼這樣造成的效果是,頁面中貨幣、日期等信息都按照美國英語的格式顯示,而需要從資源文件中取值的內容,資源管理器會從MyResource.zh-CN.resx文件裏獲得。

        如果你的站點頁面上並沒有提供讓用戶選擇語言的功能,那麼也就是默認按照用戶瀏覽器設置的區域性進行顯示,因此你就可以把上述代碼放在Global.asax.cs文件的Application_BeginRequest方法中。這樣每次用戶對頁面發出請求時,我們的程序都會首先進行區域性設置。

2. 記住用戶的區域性設置

        通過會話可以記住瀏覽者的區域性設置或選擇。但是這個操作不能在Global.asax.cs文件中Application_BeginRequest方法中進行,因爲那時會話還處於不可用狀態。如果你的站點並沒有提供讓用戶選擇語言的功能,那麼你也沒什麼必要記住用戶的區域性設置,只要按照上面介紹的在Global.asax.cs文件中Application_BeginRequest方法裏設置一下就可以了,不影響性能。這主要可以避免用戶在中途突然改變了瀏覽器中語言的設置,而網站仍按照會話中存儲的區域性爲用戶顯示頁面內容的衝突。

        如果你提過了讓用戶選擇語言的功能,那顯然要在頁面程序中使用會話來記錄用戶的區域性選擇。因爲從客戶端到服務器段的每次請求,服務器段都會開啓一個新的線程進行處理和響應。如果你的程序沒有記住客戶的選擇,那麼只能按照默認的區域性進行響應。

3. 資源管理器如何查找指定區域性的相應資源文件?

        在執行取值操作時,也就是執行ResourceManager類的GetString方法時,資源管理器會按照當前線程的CurrentUICulture屬性去尋找相對應的資源文件。有如下幾種情況:
(1). 比如當前CurrentUICulture對應的區域性是en-US,那麼首先找MyResource.en-US.resx是否存在,如存在則從中取值;如不存在,則看MyResource.en.resx是否存在。
(2). 比如當前CurrentUICulture對應的區域性是en,因爲en是非特定區域性的,那麼首先找其默認關聯的特定區域性en-US的資源文件MyResource.en-US.resx是否存在,如存在則從中取值;如不存在,則看MyResource.en.resx是否存在。
(3). 比如當前CurrentUICulture對應的區域性是en-GB,那麼首先找資源文件MyResource.en-GB.resx,如不存在,則看MyResource.en.resx是否存在,如存在則從中取值;如也不存在,則看en關聯的默認特定區域性en-US的資源文件MyResource.en-US.resx是否存在,如果此時MyResource.en-US.resx不存在,但是MyResource.en-CA.resx存在,則程序依然會拋出找不到合適資源文件的異常。

        因此我們可以總結一下,當前線程CurrentUICulture對應的是特定區域性時,資源管理器優先查找此特定區域性對應的資源文件,如果沒找到,則去找其非特定區域性的資源文件,如果還沒找到,再去找其非特定區域性關聯的默認區域性的資源文件。當前線程CurrentUICulture對應的是非特定區域性時,資源管理器優先查找此非特定區域性對應的默認特定區域性的資源文件是否存在,如果不存在,則去看此非特定區域性對應的資源文件是否存在,如果也不存在則拋出異常。

4.如何處理未提供本地化支持的區域性?

        如果站點沒有提供相應的資源文件支持用戶默認的區域性,那麼必須將其當前線程的CurrentUICulture轉化爲你站點默認的區域性,比如en-US或zh-CN。轉化的時機有兩個:
一是當你在獲得Request.UserLanguages[0]時,用其與配置文件中預先設定的被支持的區域性進行比較,如果確認其爲不被支持的,那麼立刻設置CurrentUICulture爲默認區域性。
二是在使用ResourceManager的GetString方法進行取值的時候,使用try catch結構,捕獲MissingManifestResourceException異常,在異常處理中,首先將CurrentUICulture設爲默認區域性,之後再重新使用GetString取值。

5. 通過Web.config設定站點默認的culture和uiCulture

        <globalization requestEncoding="utf-8" responseEncoding="utf-8" uiCulture="zh-CN" culture="en-US"/>
如上所示:規定站點的默認culture爲en-US(此處必須爲特定區域性),uiCulture爲zh-CN。

        當然你也可以在每個頁面的Page標籤中進行逐頁設定:<@Page Culture=“zh-CN” UICulture=“en”>。這裏就不管web.config是如何設置的,頁面會按照Page標籤的設定進行顯示。

三.在Asp.net2.0 中實現資源本地化

        Asp.net2.0中爲資源本地化提供了更加多樣的實現方法。我這裏着重談其與Asp.net1.1中的不同之處。

1.通過Web.config設定站點默認的culture和uiCulture

        在Asp.net1.1中使用web.config文件進行站點區域性設定的方法已經講過了,而在Asp.net2.0中其更加靈活。通常,您會想要站點中的所有頁面都符合相同的區域性設置。只需按如下所示在web.config中,爲globalization元素的UICulture 和 Culture(區域性)屬性分配一個站點範圍的“auto”值, 注意這個“auto”值在Asp.net1.1中是不被接受的。<globalization uiCulture="auto" culture="auto" /> auto的意義在於ASP.NET 通過檢查瀏覽器發送的 HTTP 標題獲取到的用戶首選區域性設置,並使用這個區域性設置站點的默認區域性,即當前線程的CurrentUICulture和CurrentCulture屬性。

        除了自動設置以外,您還可以爲 Asp.net 指定一個站點的默認區域性: <globalization uiCulture="auto:zh-CN" culture="auto:zh-CN" /> 注意:只有當ASP.NET無法找到 HTTP 標題來確定用戶的首選區域性,比如瀏覽器的“屬性”->“語言”中沒有任何區域性設置完全是空的時候,auto後面設定的默認區域性纔會生效。

        在web.config中進行了globalization配置之後,你的應用程序不需要寫任何代碼,線程的CurrentUICulture和CurrentCulture就會按照在globalization元素中設置的uiCulture和culture屬性值獲得區域性設置。如果沒有進行globalization配置,則線程的CurrentUICulture和CurrentCulture就會默認爲en-US。

2.使用Web.config文件跟蹤用戶的區域性選擇

        在Asp.net1.1中,那些提供了區域性選擇的站點,一般使用會話來記錄用戶的選擇,以便在用戶每次對站點發出請求時,都按照用戶選擇的區域性對顯示內容進行本地化。在Asp.net2.0中提供了另一個方法,那就是使用web.config文件來跟蹤用戶的區域性選擇。

        您可以在web.config文件中添加一個名爲 LanguagePreference 的基於字符串的配置文件屬性來支持匿名識別用戶區域性的功能。請注意anonymousIdentification元素的enabled屬性必須爲“true”,否則匿名識別功能就不可用。
<anonymousIdentification enabled="true"/>
<profile>
    <properties>
        <add name="LanguagePreference" type="string"  defaultValue="auto" allowAnonymous="true" />
    </properties>
</profile>

下面我將闡述在Asp.net2.0中如何針對LanguagePreference屬性編程。首先,可以寫一個PageBase類,它繼承自System.Web.UI.Page,並作爲站點中所有頁面類的基類。這麼做的目的其實很簡單,就是爲了將各個頁面中一些共同的處理過程提煉出來放到基類中,以減少代碼重複,提高可維護性。然後在PageBase類中寫如下代碼:protected override void InitializeCulture()
{
        base.InitializeCulture();
        string LanguagePreference = ((ProfileCommon)this.Context.Profile).LanguagePreference;
        //該用戶首次訪問本站,Profile.LanguagePreference爲空時,識別用戶瀏覽器的語言設置
        if(string.IsNullOrEmpty(LanguagePreference))
        {
             if (this.Context.Request.UserLanguages != null)
             {
                  LanguagePreference = this.Context.Request.UserLanguages[0];
                  ((ProfileCommon)Context.Profile).LanguagePreference = LanguagePreference;
              }
          }
          else
          {
               Thread.CurrentThread.CurrentUICulture = new CultureInfo(LanguagePreference);                               
               Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(LanguagePreference);
           }
}

        System.Web.UI.Page類的InitializeCulture方法是在Asp.net2.0中新加的,它爲當前線程設置Culture和UICulture。頁面生命週期已被設計爲InitializeCulture方法先於頁面的Init和Load運行。在上述代碼中,首先使用((ProfileCommon)this.Context.Profile).LanguagePreference;獲得當前LanguagePreference配置文件屬性的值,判斷其是否爲空,也就是是否已經爲用戶保存了區域性設置。如果爲空,則從Http頭中獲取用戶的首選區域性設置,並通過((ProfileCommon)Context.Profile).LanguagePreference = LanguagePreference;保存用戶的首選區域性設置。如果不爲空,說明已經保存了用戶的區域性設置,那麼使用這個區域性設置當前線程的CurrentUICulture和CurrentCulture屬性。
         如果Web.config中定義了<globalization uiCulture="auto" culture="auto" />,那麼可以將上述代碼簡化爲:protected override void InitializeCulture()
{
        base.InitializeCulture();
        string LanguagePreference = ((ProfileCommon)this.Context.Profile).LanguagePreference;    

        if(!string.IsNullOrEmpty(LanguagePreference))
        {
              Thread.CurrentThread.CurrentUICulture = new CultureInfo(LanguagePreference);
              Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(LanguagePreference);
        }
        else
        {
               ((ProfileCommon)Context.Profile).LanguagePreference = Thread.CurrentThread.CurrentCulture.Name;
         }
}

        如果在站點中提供了讓用戶選擇區域性的功能,比如在站點的母版頁中放了一個選擇語言的列表,那麼可以通過以下語句來記住用戶對區域性的選擇:
 protected void lstLanguage_SelectedIndexChanged(object sender,EventArgs e)
{
        if (lstLanguage.SelectedValue != "Auto") //默認選項是Auto
    {
 Profile.LanguagePreference = lstLanguage.SelectedValue;
     }
    else
    {
       Profile.LanguagePreference = null;
     }
    Response.Redirect(Request.Url.AbsolutePath);
 }
        注意Response.Redirect(Request.Url.AbsolutePath);這行代碼,因爲事件處理代碼是在Page_Load之後執行的,要是想讓頁面迅速發生變化必須執行重定向操作。

3.     在Asp.net2.0中使用資源文件

        在站點中建立全局資源文件的時候,VS.Net2005會自動建立一個App_GlobalResources文件夾專門來存放全局資源文件。所謂全局資源文件,也就是給站點中多個頁面文件或母版頁使用的資源文件。假設我們創建名爲MyResource.resx和MyResource.zh-cn.resx的文件。在程序中我們可以使用以下代碼來獲得資源文件中的值:this.lblCountry.Text = Resources.MyResource.Country;
其中Country是資源文件中的鍵。顯然,這比Asp.net1.1中從資源文件獲取值要容易很多。

        這裏有兩個問題需要注意:第一,在創建一組具有相同根名稱的資源文件時,沒有區域性標示的文件必須建立,比如MyResource.resx是必須有的,其它如MyResource.en-gb.resx和MyResource.zh-cn.resx的建立是根據需要的。如果不建立MyResource.resx只建立了MyResource.zh-cn.resx等,則上述代碼中的Resources命名空間下就不會出現MyResource,因此上述代碼編譯無法通過。MyResource.resx中應該存放站點默認語言的內容,以備在找不到與當前線程CurrentUICulture匹配的本地化資源文件或在本地化資源文件中找不到相應鍵值時使用。Asp.net是以MyResource.resx文件中的鍵爲準,假如在MyResource.resx中不存在Country鍵,而在MyResource.zh-cn.resx中存在Country鍵,那麼上述代碼在編譯時也會報錯。第二,Asp.net在找不到相應區域的本地化資源時,不會報告任何異常,會自動從MyResource.resx文件中獲取值,但並不改變當前線程的CurrentUICulture。
       
        在站點中建立局部資源文件的時候,VS.Net2005會自動建立一個App_LocalResources文件夾專門來存放局部資源文件。所謂局部資源文件,也就是給站點中單一頁面文件使用的資源文件。它的命名方式一般是Default.aspx.resx和Default.aspx.zh-cn.resx。現在我在Default資源文件中添加三個鍵Language、lblNavigation.Text和lblNavigation.ForeColor。其中我爲Default.aspx.resx的lblNavigation.ForeColor設置blue,爲Default.aspx.zh-cn.resx的lblNavigation.ForeColor設置red。在頁面文件中Default.aspx中從局部資源文件裏獲得內容的方法如下有兩種:
(1). <asp:Label ID="lblLanguage" runat="server" Text="<%$ Resources:Language %>"></asp:Label>
(2). <asp:Label ID="lblNavigaion" runat="server" meta:resourcekey="lblNavigation"></asp:Label>
 使用第一種方法時要注意使用符號$。使用第二種方法更加靈活,它可以一次性地爲控件的很多屬性設定值。

        在這裏仍然有問題需要注意:頁面默認的局部資源文件必須被建立,比如Default.aspx.resx是必須的,而Default.aspx.zh-cn.resx則根據需要。如果你不建立默認的局部資源文件,而在頁面中卻要使用局部資源文件時,當使用第一種方法進行綁定時,出編譯錯誤;當使用第二種方法進行綁定時,不會出編譯錯誤,但是這些屬性的設置全都沒起作用,如同沒寫一樣。

4.顯示本地化圖像

        顯示本地化圖像也是Asp.net2.0的新功能。在Asp.net2.0中資源文件已經不僅限於string類型的鍵值對組合,它可以保存多種類型的文件。利用這一功能可以實現圖像的本地化。其實所謂本地化圖像,無非就是將給不同區域性準備的圖像放到不同的本地化資源文件中去。比如將LitwareSlogan.jpg放到MyResource.resx中,把LitwareSlogan.cn.jpg放到MyResource.zh-cn.resx中。


        當不同本地化版本的全局資源文件中含有本地化版本的圖像文件時,您可以自定義一個名爲 MyLocalImage.ashx 的處理程序文件,基於用戶的語言首選項來有條件地進行加載,代碼如下所示。
 

頁面中的調用方法:

<asp:Image ID="Image1" runat="server" ImageUrl="~/ MyLocalImage.ashx" />

MyLocalImage.ashx 的處理程序的寫法:

public class MyLocalImage : IHttpHandler
{
       public void ProcessRequest (HttpContext context)
       {
            context.Response.ContentType = "image/png";
            string LanaguageReference = ((ProfileCommon)context.Profile).LanguagePreference;
            if (!string.IsNullOrEmpty(LanaguageReference))
            {
                    Thread.CurrentThread.CurrentUICulture = new CultureInfo(LanaguageReference);
            }
            Bitmap bm = Resources.Litware.LitwareSlogan;
            MemoryStream image = new MemoryStream();
            bm.Save(image,ImageFormat.Png);
            context.Response.BinaryWrite(image.GetBuffer());
         }
}

        MyLocalImage.ashx 中定義的自定義處理程序類可使用您以前在自定義 InitializeCulture 方法中看到的類似邏輯,在從全局資源文件中檢索圖像文件以前,初始化當前線程的 CurrentUICulture 設置。您可能疑問爲何在頁面的基類中已經設置了當前線程的CurrentUICulture,而在這裏還要重新設置,那是因爲這裏的線程與基類中處理的線程不是同一線程。在該自定義處理程序正確初始化了 CurrentUICulture 設置之後,它即可通過 MyResource.resx 的強類型化資源類來訪問圖像文件。然後,便只需將圖像文件的數位編寫到 HTTP 響應流。
posted
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章