zoukankan      html  css  js  c++  java
  • [转载]ASP.NET 2.0 本地化技术之研究

        众所周知ASP.NET 2.0里对本地化(Localization)做了很多工作,大大简化了开发过程。今天终于能抽出时间研究一下这个技术了,资料很多,但大多带着一股咬文嚼字的翻译味道,So......自己写一篇。

    1.使用工具自动生成本地化资源(LocalResources)
    2.原来Localizable AttributeProperty是这么回事呀
    3.手工添加本地化资源
    4.显示使用本地化资源
    5.全局资源的使用(GlobalResources)
    6.如何在后台编程时使用这两种资源
    7.编程切换语言设置
    8.使用图片资源
    9.代码下载


    1.使用工具自动生成本地化资源(LocalResources)

    首先当然是建立一个WEB工程啦,如图所示:


    双击Default.aspx,切换到[设计]视图,从工具箱里拖一个Button进来。点击菜单中的[工具]->[生成本地资源],如图所示:


    这时发现在解决方案方案视图里自动增加了一份本地资源,如下图所示:


    切换到属性视图,可以看到Text和ToolTip都被加上了一个红色符号,提示“属性是用表达形式隐式绑定的”,如下图所示:(注意:只有在视图状态下选中控件才能看到这两个属性哟


    为了增加对多语言的支持,我们现在右键Default.aspx.resx,点击复制,再选中App_LocalResources目录,点击粘贴,将“副本 Default.aspx.resx”重命名为Default.aspx.en-us.resx,如图所示:


    分别编辑Default.aspx.resx和Default.aspx.en-s.resx 的内容,如下图示:
    Default.aspx.resx


    Default.aspx.en-s.resx


    打开Default.aspx,在 Page 标签里添加Culture="auto" UICulture="auto",如下所示:
    <%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" meta:resourcekey="PageResource1" UICulture="auto" Culture="auto" %>

    只有这样,后面才能获取浏览器的首选语言设置。如果要加到 Web.config 中,如下所示:
        <system.web>
       
        <globalization uiCulture="auto" culture="auto" />
       
    </system.web>

    运行网站,效果如下图所示:


    点击IE菜单的[工具]->[Internet 选项],在弹出的对话框中点[常规]选项卡的[语言]按钮,弹出[语言首选项]对话框,如下图所示:


    点击[添加]按钮,选择英语(美国),并上移到第一位,如下图所示:


    一路[确定]点下来,刷新页面,可以看到Button的标题变成“Hello World”啦,如下图所示:


    综上所述,使用工具自动生成本地化资源,并隐式的绑定到控件上,来实现页面的本地化是非常简单的,但存在以下几项问题:

        1)必须为每个页生成多份资源文件;
        2)只有控件属性中被标识为Localizable(true)才可能被工具扫描到;
        3)由于是对页面包含的控件进行扫描,所以最好是在页面布局基本确定后再使用该工具,并且在编辑完    资源文件后不要再使用该工具,如果不幸你这样做了。。。会发现默认的资源文件被清空了

    2.原来Localizable AttributeProperty是这么回事呀

    在我前天写的随笔开发和使用自定义服务器控件中,一直对属性为什么要使用Localizable(true)不清楚。
            [
            Bindable(
    true),
            Category(
    "Appearance"),
            DefaultValue(
    "Hello"),
            Description(
    "The welcome message text."),
            Localizable(
    true)
            ]
            
    public virtual string Text
            {
                
    get
                {
                    
    string s = (string)ViewState["Text"];
                    
    return (s == null? "Hello" : s;
                }
                
    set
                {
                    ViewState[
    "Text"= value;
                }
            }

    查了许多关于WEB控件开发的资料,其中都对这个AttributeProperty做了忽略,原来只有当控件的属性声明为Localizable(true)时,VS的生成本地资源工具才会扫描到。

    3.手工添加本地化资源

    第一点中提到过生成本地资源工具只能扫描到页面已经包含的控件,那么如果后面由于开发需要又增加了一个新的控件要怎么办呢?虽然大部人都能自己想到,但还是写一下吧。

    从工具箱再拖一个Label控件到页面上,切换到源视图,修改代码如下:
    <asp:Label ID="Label1" runat="server" meta:resourcekey="Label1Resource1" Text="Label"></asp:Label>

    再修改两份本地资源文件,为Label1添加Label1Resource1键值的相关资源,如下图所示:
    Default.aspx.resx


    Default.aspx.en-s.resx


    再运行程序,切换语言设置,可以看到Label1的效果和Button1是一样的,如图所示:
    中文(中国)


    英语(美国)


    4.显示使用本地化资源

    OK,前面提到的都是隐式使用本地化资源,那么如何显示的使用本地化资源呢?相对于隐式来讲,显示更加灵活,功能也更强大。

    只需要将刚才的Label1的代码,
    <asp:Label ID="Label1" runat="server" meta:resourcekey="Label1Resource1" Text="Label"></asp:Label>

    修改为,即可。
    <asp:Label ID="Label1" runat="server" 
        Text
    ="<%$ Resources:Label1Resource1.Text %>" 
        ToolTip
    ="<%$ Resources:Label1Resource1.ToolTip %>" >
    </asp:Label>

    这时切换到[设计]视图,选中Label1控件,查看属性视图,会发现Text和ToolTip被加上的是蓝色的符号,提示“属性绑定了表达式”。跟上面提到的红色符号比较,少了“隐式”二字,这也就是所谓的显式和隐定的来源吧,如下图所示:


    5.全局资源的使用(GlobalResources)

    前面提到过,本地资源需要为每个页面分别生成多个资源文件,虽然这样看起来分门别类的挺清楚,但在实际应用过程中,我们有许多资源是可以共享的,总不能不停的重复写来写去吧。其实这种情况我们可以用全局资源(GlobalResources)来解决。

    在资源方案视图中选中网站,右键,点击[添加ASP.NET 文件夹]->[App_GlobalResources],如图所示:


    再选中App_GlobalResources文件夹,右键,点击[添加新项],在弹出的对话框中选中“资源文件”,命名为“LocalizedText.resx”,点击[添加],如图所示:


    双击LocalizedText.resx进行编辑,添加一条新的字符串资源,如图所示:


    复制LocalizedText.resx,粘贴到App_GlobalResources目录,重命名为LocalizedText.en-us.resx,双击进行编辑,添加一条新的字符串资源,如图所示:


    打开Default.aspx,切换到[设计]视图,从工具箱拖一个TextBox控件到页面上。切换到[源]视图,修改代码:
    <asp:TextBox ID="TextBox1" runat="server" Text="<%$ Resources:LocalizedText, Msg1 %>"></asp:TextBox>

    运行程序,切换语言设置,可以看到全局资源的使用效果了,如图所示:
    中文(中国)


    英语(美国)


    注意:全局资源不能使用隐式声明。

    6.如何在后台编程时使用这两种资源

    前面提到的都是在网页中使用这两种资源,那么如何在后台使用这两种资源呢?

    打开Default.aspx,切换到[设计]视图,从工具箱拖一个Localize控件(Literal 控件与 Label 控件类似,但 Literal 控件不允许对所显示的文本应用样式。可以通过设置 Text 属性,以编程方式控制在控件中显示的文本。)到页面上。双击Button1,添加以下实现
        protected void Button1_Click(object sender, EventArgs e)
        {
            Localize1.Text 
    = (String)GetLocalResourceObject("Label1Resource1.Text"+ " " +
                (String)GetGlobalResourceObject(
    "LocalizedText""Msg1");
        }

    记得添上这个引用
    using System.Globalization;

    运行程序,切换语言设置,可以看到和前面使用表达式调用资源的效果是一样的,如图所示:
    中文(中国)


    英语(美国)


    7.动态切换语言设置

    以上的介绍都是通过IE浏览器获取语言设置,其实我们可以自己设置使用哪种语言。

    1)通过在每个页面里的Page节指定
    <%@ Page Culture="en-us" UICulture="en-us" %>

    如上所设,该页将使用en-us的语言设置。

    注意:这只是个概要式写法,实际的页面中的Page一般都包含更多的属性。

    2)通过在Web.Config里的globalization节指定
    <system.web>
        
    <globalization Culture="en-us" UICulture="en-us" />
    </system.web>

    3)当然还有一种就是通过编程动态切换语言设置啦,这也是实际项目中经常用到的方式

    打开Default.aspx,切换到[源]视图,添加如下代码
            <href="?currentculture=zh-cn">中文(中国)</a>
            
    &nbsp;
            
    <href="?currentculture=en-us">English(USA)</a> 

    打开Default.aspx.cs,添加如下代码
        String s;

        
    protected override void InitializeCulture()
        {
            s 
    = Request.QueryString["currentculture"];
            
    if (!String.IsNullOrEmpty(s))
            {
                
    //UICulture - 决定了采用哪一种本地化资源,也就是使用哪种语言
                
    //Culture - 决定各种数据类型是如何组织,如数字与日期
                Thread.CurrentThread.CurrentUICulture = new CultureInfo(s);
                Thread.CurrentThread.CurrentCulture 
    = CultureInfo.CreateSpecificCulture(s);
            }
        }

    记得添上这个引用
    using System.Threading;

    运行程序,分别点击新增加的两个链接,效果如图所示:
    中文(中国)


    Enlish(USA)



    8.使用图片资源

    分别编辑LocalizedText.resx和LocalizedText.en-su.resx,添加图片资源,如图所示:
    LocalizedText.resx


    LocalizedText.en-su.resx


    注意:当图形文件添加到图形资源里时,系统会自动去除扩展名并把“-”替换成“_”,如上图,我的文件名为“en-us-flag.png”添加到资源里变成了“en_us_flag”。

    打开Default.aspx,切换到[设计]视图,从工具箱拖一个Image控件到页面上。打开Default.aspx.cs,添加如下代码
        protected void Page_Load(object sender, EventArgs e)
        {
            Image1.ImageUrl 
    = "~/Image.aspx?currentculture=" + s;
        }

    选中网站右键,创建一个新的WEB窗体,命名为Image.aspx,编辑该页面,在Page节增加如下代码
    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Image.aspx.cs" Inherits="Image" Culture="auto" UICulture="auto"%>

    注意:默认创建的WEB窗体的Page节,不包括Culture和UICulture这两个属性,一定要手工添上,切记!

    打开Image.aspx.cs,添加如下代码
        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);
            }
        }

        
    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();
        }

    当然,别忘了添上这两个引用
    using System.Threading;
    using System.Globalization;

    运行程序,分别点击两个链接,效果如图所示:
    中文(中国)


    English(USA)


    9.代码下载

    下载地址:https://files.cnblogs.com/reonlyrun/WebLocalizationTaste.rar
     
     
    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.代码下载

    下载地址:https://files.cnblogs.com/reonlyrun/WebLocalizationTaste2.rar
  • 相关阅读:
    RABC权限管理
    七牛云上传
    支付宝沙箱支付(Django端)超适合小白哦~
    ModelSerialzier + ModelViewSet基础使用
    微博三方登录
    Celery梳理
    ios 动画
    ios 贝塞尔动画
    ios 贝塞尔
    ios Masonry 开发细节
  • 原文地址:https://www.cnblogs.com/fx2008/p/2286165.html
Copyright © 2011-2022 走看看