内容载入中...
三.在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 响应流。
。