ASP.NET 2.0 本地化技術之研究(二)

ASP.NET 2.0 本地化技術之研究的回覆中提到了以下兩點:

1.這只是單個頁面的切換,如何做整個站點的切換呢?( hjh
2.關於如何將資源直接顯示……既然控件能夠將嵌入dll的資源直接顯示,不知道網站能否也將嵌入資源直接調用WebResource顯示呢?(Cat Chen

由於不是一兩句可以說清,所以再開一篇仔細講一下。


內容列表:

1.整站本地化資源的切換
2.使用ProFile保存用戶選擇的語言
3.關於WebResource的使用
4.代碼下載

1.整站本地化資源的切換

在上一篇裏我們講到,可以通過重載頁面的InitializeCulture函數,在其中切換當前線程的CurrentUICulture和CurrentCulture來實現本頁的資源切換。那麼整站呢?總不能在每個頁面裏都寫上這幾句吧。。。

首先,我想到的是使用MasterPage,如果在MasterPage里加上資源切換的代碼,那麼所有使用該母板的頁面都具備這種能力了吧,呵呵(想得不錯)。但如意算盤打破了,MasterPage是使用@Master來聲明的,根本和Page是兩個繼承路線,所以MasterPage裏沒有InitializeCulture這個虛函數!

沒辦法,想到了另一個解決方案,創建一個從System.Web.UI.Page繼承下來的基類,在其中實現資源切換,而站內所有頁面的實現類都從該類繼承。OK,就這麼辦!

打開上一篇完成的網站,選中網站,右鍵在彈出菜單中點擊[添加ASP.NET文件夾]-[App_Code]。
選中該文件夾,右鍵點擊[添加新項],在彈出式窗口中選擇“類”,命名爲LocalizedPage.cs,點擊[添加]完成,如圖所示:


編輯LocalizedPage.cs,代碼如下:
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>
/// 所有需要本地化資源切換的頁面基類
/// </summary>
public class LocalizedPage : System.Web.UI.Page 
{
    
protected override void InitializeCulture()
    {
        String s 
= Request.QueryString["currentculture"];
        
if (!String.IsNullOrEmpty(s))
        {
            
//UICulture - 決定了採用哪一種本地化資源,也就是使用哪種語言
            
//Culture - 決定各種數據類型是如何組織,如數字與日期
            Thread.CurrentThread.CurrentUICulture = new CultureInfo(s);
            Thread.CurrentThread.CurrentCulture 
= CultureInfo.CreateSpecificCulture(s);
        }
    }
}

編輯Image.aspx.cs,去除其重載的InitialzeCulture()函數,將其基類改爲LocalizedPage,代碼如下:
using System;
using System.Data;
using System.Configuration;
using System.Collections;
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;

public partial class Image : LocalizedPage
{
    
protected void Page_Load(object sender, EventArgs e)
    {
        System.Drawing.Bitmap img 
= (System.Drawing.Bitmap)GetGlobalResourceObject(
            
"LocalizedText",
            CultureInfo.CurrentCulture.Name.ToLower().Replace(
"-""_"+ "_flag");

        System.IO.MemoryStream ms 
= new System.IO.MemoryStream();
        img.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);

        Response.ClearContent();
        Response.ContentType 
= "image/jpeg";
        Response.BinaryWrite(ms.ToArray());

        img.Dispose();
        ms.Dispose();
        ms.Flush();
    }
}

運行網站,可以看到由Image頁面負責輸出的圖片,可以按選中的語言正常切換。

再編輯Default.aspx.cs,調整代碼如下:
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.Globalization;
using System.Threading;


public partial class _Default : LocalizedPage 
{
    
protected void Page_Load(object sender, EventArgs e)
    {
        String s 
= Request.QueryString["currentculture"];
        Image1.ImageUrl 
= "~/Image.aspx?currentculture=" + s;
    }

    
protected void Button1_Click(object sender, EventArgs e)
    {
        Localize1.Text 
= (String)GetLocalResourceObject("Label1Resource1.Text"+ " " +
            (String)GetGlobalResourceObject(
"LocalizedText""Msg1");
    }
}

運行程序,一切正常。

總結:利用這種方式,新建頁面時只需修改其繼承的基類爲LocalizedPage即可。對於已經建好的站點,同理,也可以很方便的加入資源切換的支持。

2.使用ProFile保存用戶選擇的語言

前面我們是通過URL傳參的方式將用戶選擇的語言傳遞到各個頁面,感覺不爽。那麼使用Session呢?聽上去不錯,但是你沒聽過ProFile嗎?這可是ASP.NET 2.0的新特性之一呀!與Session一樣ProFile是針對一個特定用戶的,但ProFile更好用,因爲它有以下特點:
  1)可存儲,默認是保存在SQL Server Express中,但通過實現Provider可以將它存儲到任何地方
  2)支持匿名使用,在用戶認證後還可以遷移到認證用戶中(具體實現方法據說是非常的“巧妙”)
  3)支持生成和管理報告
不錯吧,那麼我們就用ProFile來保存用戶選擇的語言信息吧。

注意:由於ProFile默認是由SQL Server Express來存儲的,所以要保證你的VS2005已經安裝該模塊。

編輯Web.Config,在system.web節點下增加以下配置
<configuration>
    
<system.web>
        
<anonymousIdentification enabled="true"/>
        
<profile>
            
<properties>
                
<add name="LanguagePreference" type="string" 
                    defaultValue
="Auto" allowAnonymous="true" />
            
</properties>
        
</profile>
    
</system.web>
</configuration>

同時加入的anonymousIdentification節,是爲了讓系統自動爲匿名用戶生成唯一標識。另外的allowAnonymous="true"表明LanguagePreference屬性可以被匿名用戶訪問。

編輯Default.aspx,切換到[設計]視圖,刪除原來用於切換語言的兩個鏈接“中文(中國)”和“English(USA)”。從工具箱中拖一個DropDownList控件到頁面上,設置其AutoPostBack屬性爲True(切記!),然後編輯它的Items屬性,如圖所示:


中文(中國)的Value爲zh-cn,英文(美國)的Value爲en-us。

編輯Default.aspx.cs,爲DropDownList編寫SelectedIndexChanged事件的實現,代碼如下:
    protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
    {
        Profile.LanguagePreference 
= DropDownList1.SelectedValue;
        Response.Redirect(Request.Url.AbsolutePath);
    }

修改Page_Load的實現,代碼如下:
    protected void Page_Load(object sender, EventArgs e)
    {
        String s 
= Profile.LanguagePreference;
        Image1.ImageUrl 
= "~/Image.aspx";
    }

然後再編輯LocalizedPage.cs,代碼如下:
    protected override void InitializeCulture()
    {
        String s 
= (String)Context.Profile.GetPropertyValue("LanguagePreference");
        
if (!String.IsNullOrEmpty(s) && (s != "Auto")) 
        {
            
//UICulture - 決定了採用哪一種本地化資源,也就是使用哪種語言
            
//Culture - 決定各種數據類型是如何組織,如數字與日期
            Thread.CurrentThread.CurrentUICulture = new CultureInfo(s);
            Thread.CurrentThread.CurrentCulture 
= CultureInfo.CreateSpecificCulture(s);
        }
    }

注意:我們在Default.aspx.cs之所以可以直接使用Profile來訪問用戶個人信息,是因爲ASP.NET在頁面運行時自動爲我們生成了一個繼承自System.Web.Profile.ProfileBase的ProfileCommon類。而在App_Code目錄的代碼開始執行時,ProfileCommon還沒有生成,更別提Profile了。所幸的是,我們可以通過上面代碼的方式訪問到用戶個人信息(真的研究了好長時間。。。

運行程序,切換語言,運行效果如圖所示:
中文(中國)


英文(美國)


注意喲,退出程序後,再次運行,所有頁面將按你上次設置的語言顯示,Profile真的很不錯。

3.關於WebResource的使用


ASP.NET是在運行時將全局資源和本地資源進行編譯,象.aspx文件一樣,所以我們只需要將.resx文件xcopy到正在運行的WEB服務器上,即可爲新語言提供本地化的支持。但如果我們開發了一個WEB控件,其中使用到了一些資源(如圖片),那就要求我們必須將DLL和資源文件一起部署到WEB服務器上,比較麻煩。

ASP.NET開發團隊考慮到了這一點,現在我們可以在網站裏使用資源DLL,這樣在發佈DLL時資源也同時被分配了。該技術是通過在控件代碼裏調用GetWebResourceUrl方法,這個方法指向一個名爲WebResource.axd的內置HTTP處理程序的URL。通過加載一個名爲AssemblyResourceLoader的HttpHandler類,ASP.NET運行時響應WebResource.axd的請求,返回指定資源的URL。

該技術有以下缺點:
  1)只能在面向 ASP.NET 2.0 網站的 DLL 項目內使用該技術,而無法網站內直接使用該技術
  2)該技術實際上並不支持任何形式的本地化(說到這,感覺把這傢伙寫到本隨筆裏不太合適。。。管它呢,先寫完再說!

選中網解決方案,右鍵在彈出式菜單裏點擊[添加]->[新建項目],在彈出窗口選中Visual C#項目下的類庫,並設好保存路徑,如圖所示:


點擊確定,刪除Class1.cs。選中ClassLibrary1項目,右鍵在彈出菜單裏點擊[添加]->[新建項],在彈出窗口選擇“WEB 自定義控件”,如圖所示:


點擊[添加],現在解決方案裏已經包含兩個項目了,如圖所示:


右鍵ClassLibrary1項目,選擇[添加]->[現有項],隨便找一張圖片(我使的是園子的logo,嘿嘿),如圖所示:


點擊[添加],右鍵剛添加的圖片點擊[屬性],將“生成操作”設爲“嵌入的資源”,如圖所示:


編輯WebCustomControl1.cs,代碼如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

[assembly: WebResource(
"ClassLibrary1.logo.gif""image/gif")]

namespace ClassLibrary1
{
    [ToolboxData(
"<{0}:WebCustomControl1 runat=server></{0}:WebCustomControl1>")]
    
public class WebCustomControl1 : WebControl
    {
        
protected override void RenderContents(HtmlTextWriter output)
        {
            output.WriteBeginTag(
"image");
            String url 
= Page.ClientScript.GetWebResourceUrl(GetType(), "ClassLibrary1.logo.gif");
            output.WriteAttribute(
"src", url);
            output.WriteEndTag(
"image");
        }
    }
}

編輯網站的Default.aspx文件,切換到[設計]視圖,將工具箱的ClassLibrary1面板裏的WebCustomControl1控件拖到頁面上,運行程序,效果如圖所示:



4.代碼下載

下載地址:http://www.cnblogs.com/Files/reonlyrun/WebLocalizationTaste2.rar 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章