20.3 为不同的语言选择资源文件
前文阐述了如何创建及其使用全局资源文件与本地资源文件。在这里存在一个问题:前面讲到,要实现应用程序支持多语言功能,就需要为每种语言(如英语和法语)或每种语言和区域性(如英语[英国]、英语[美国])分别创建一个资源文件。那么该如何根据语言的需要在程序中来选择这些不同的资源文件呢?
其实,针对上面的问题,ASP.NET提供了Culture与UICulture两个属性来解决。其中,Culture属性的值确定与区域性相关的函数的结果,如日期、数字和货币格式等;而UICulture属性的值确定为页面加载哪些资源。
当页面运行时,ASP.NET会选择与页面的当前UICulture设置最匹配的资源文件版本。如果没有匹配项,ASP.NET将使用资源回退获取资源。例如,如果正在运行Default.aspx页并且当前的UICulture属性设置为es(西班牙语),则ASP.NET会使用本地资源文件Default.aspx.es.resx的已编译版本。
最后还需要说明的是,Culture和UICulture属性是使用标识语言的Internet标准字符串(例如,en代表英语,es代表西班牙语,de代表德语)和标识区域性的Internet标准字符串(例如,US代表美国,GB代表英国,MX代表墨西哥,DE代表德国)设置的。例如,en-US代表英语/美国,en-GB代表英语/英国,es-MX代表西班牙语/墨西哥,等等。其实,相对于Microsoft.NET Framework的其他版本,Microsoft.NET Framework 4最少支持354个区域性,详细的信息可以参考MSDN。
20.3.1 以声明方式设置区域性和UI区域性
在ASP.NET中,可以通过如下三种方式来以声明的方式设置ASP.NET网页的区域性和UI区域性:
1)如果需要设置所有页的区域性和UI区域性,那么可以向Web.config文件添加一个globalization节,然后设置它的uiCulture和culture特性。如下面的示例代码所示:
<configuration>
<system.web>
<globalization uiCulture="en-US"culture="en-US"/>
</system.web>
</configuration>
2)如果需要设置单个页的区域性和UI区域性,那么可以设置@Page指令的Culture和UICulture特性。如下面的示例代码所示:
<%@Page Language="C#"AutoEventWireup="true"
CodeBehind="TestY.aspx.cs"Inherits="_20_1.TestY"
Culture="en-US"UICulture="en-US"%>
3)如果要使ASP.NET将区域性和UI区域性设置为当前浏览器设置中指定的第一种语言,那么可以将UICulture和Culture设置为auto,也可以将该值设置为auto:culture_info_name,其中culture_info_name是区域性名称。
其实,用户完全可以在浏览器中设置区域性和UI区域性。其设置方法为:在Microsoft Internet Explorer的“工具”菜单上,依次单击“Internet选项”|“常规”选项卡|“语言”,然后设置它们的语言首选项,如图20-5所示。
图 20-5 设置区域性和UI区域性
如果Web.config文件中globalization元素的enableClientBasedCulture特性设置为true,则ASP.NET可以根据由浏览器发送的值自动设置网页的区域性和UI区域性。
当然,这种完全依赖于浏览器设置来确定网页的UI区域性并不是最佳做法,并且用户使用的浏览器通常并未设置为它们的首选项。因此,一般的做法是为用户提供显式选择页面的语言或语言和区域性的方法。在第20.3.2节中,将给出一个类似的小例子。
20.3.2 以编程方式设置区域性和UI区域性
除了可以以声明的方式来设置ASP.NET网页的区域性和UI区域性之外,还可以以编程的方式来设置ASP.NET网页的区域性和UI区域性。
其方法也很简单,只需要重写该页的InitializeCulture方法,并在该方法中确定其区域性和UI区域性。其中,InitializeCulture方法为页的当前线程设置Culture和UICulture特性,在页生命周期的很早的时期调用,此时还没有为页创建控件,也没有为页设置属性。因此,若要读取从控件传递给页的值,必须使用Form集合直接从请求获取这些值。
在InitializeCulture方法中,可以通过下列两种方式来设置区域性和UI区域性:
1)将页的Culture和UICulture属性设置为语言和区域性字符串(如en-US)。这两个属性是页的内部属性,只能在页中使用。示例如下面的代码所示:
protected override void InitializeCulture()
{
Page.UICulture="en-US";
Page.Culture="en-US";
}
2)将当前线程的CurrentUICulture和CurrentCulture属性分别设置为UI区域性和区域性。CurrentUICulture属性采用一个语言和区域性信息字符串。若要设置CurrentCulture属性,请创建CultureInfo类的一个实例并调用其CreateSpecificCulture方法。这一点将在下面进行介绍。
20.3.3 显式地选择页面的显示语言
上面阐述了如何通过声明与编程的方式来设置ASP.NET网页的区域性和UI区域性。为了加深理解与编程技巧,本小节将通过一个实际的示例来展示如何让用户显式地选择页面的显示语言。
首先,需要创建两个全局资源文件,如图20-6与图20-7所示。其中,MyResources.resx资源文件表示应用程序默认的资源文件;而MyResources.en-us.resx资源文件则表示一个专用于美国英语的资源文件。
图 20-6 MyResources.resx
图 20-7 MyResources.en-us.resx
下面来创建一个测试页面TestY.aspx。在该页面中,将Culture和UICulture特性设置为“auto”,从而使ASP.NET将区域性和UI区域性设置为当前浏览器设置中指定的第一种语言。详细代码如代码清单20-1所示。
代码清单20-1 TestY.aspx
<%@Page Language="C#"AutoEventWireup="true"
CodeBehind="TestY.aspx.cs"Inherits="_20_1.TestY"
Culture="auto"UICulture="auto"%>
<!DOCTYPE html PUBLIC"-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1"runat="server">
<asp:DropDownList ID="ddl_Language"
runat="server"Width="160px"
OnSelectedIndexChanged="ddl_Language_SelectedIndexChanged"
AutoPostBack="true">
<asp:ListItem Value="">默认</asp:ListItem>
<asp:ListItem Value="en-US">美国英文</asp:ListItem>
</asp:DropDownList>
<br/>
<br/>
<div>
<asp:Label ID="lb_User"runat="server"
Text="<%$Resources:MyResources, lb_User%>">
</asp:Label>:
<asp:TextBox ID="TextBox1"runat="server">
</asp:TextBox>
<br/>
<asp:Label ID="lb_Password"runat="server"
Text="<%$Resources:MyResources, lb_Password%>">
</asp:Label>:
<asp:TextBox ID="TextBox2"runat="server">
</asp:TextBox>
<br/>
<asp:Button ID="bt_Login"runat="server"
Text="<%$Resources:MyResources, bt_Login%>"/>
</div>
</form>
</body>
</html>
在上面已经阐述过,InitializeCulture方法在页生命周期的很早的时期就调用,此时还没有为页创建控件,也没有为页设置属性。因此,若要读取从控件传递给页的值,必须使用Form集合直接从请求获取这些值。因此,需要在代码中使用“Request.Form["ddl_Language"]”来读取ddl_Language控件所选择的值,然后将此值赋给页面的UICulture与Culture属性。如下面的代码所示:
using System;
using System.Collections.Generic;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace_20_1
{
public partial class TestY:System.Web.UI.Page
{
protected override void InitializeCulture()
{
if(Request.Form["ddl_Language"]!=null)
{
String selectedLanguage=
Request.Form["ddl_Language"];
UICulture=selectedLanguage;
Culture=selectedLanguage;
}
base.InitializeCulture();
}
protected void Page_Load(object sender, EventArgs e)
{
}
protected void ddl_Language_SelectedIndexChanged(
object sender, EventArgs e)
{
}
}
}
运行上面的示例代码,运行结果如图20-8所示,现在就可以在TestY.aspx页面中显式地选择是显示中文页面还是显示美式英文页面。
图 20-8 示例运行结果