使用资源文件
创建资源
资源管理是 .NET 框架类库的一个功能,可用于从源代码中提取可本地化的元素,并将它们与字符串键一起存储为资源。运行时,可使用 ResourceManager 类的一个实例将键解析为原始资源或本地化版本。资源可存储为独立(“松散”)文件,或程序集的一部分。
ASP.NET 页可使用资源文件;另外,已编译的代码隐藏控件可以使用嵌入或链接到它们的程序集中的资源。
可使用 ResourceWriter 类以编程方式创建资源,或使用工具 Resgen.exe 创建资源。Resgen.exe 可使用简单的“键=值”格式作为输入,或使用 .resx 格式的 XML 文件。
; ; Lines beginning with a semicolon can be used for comments. ; [strings] greeting=Welcome ! more=Read more ... ...
使用页上的资源
下面的示例仅实现一个 .aspx 页,该页针对每个请求进行本地化。支持的语言是英语、德语和日语。确定语言的方法是检查 Global.asax 文件中 HTTP 标头的 Content-Language 字段。该字段的内容可通过 UserLanguages 集合访问:
<script language=JavaScript> function doClick(index, numTabs, id) { document.all("tab" + id, index).className = "tab"; for (var i=1; i < numTabs; i++) { document.all("tab" + id, (index + i) % numTabs).className = "backtab"; } document.all("code" + id, index).style.display = ""; for (var j=1; j < numTabs; j++) { document.all("code" + id, (index + j) % numTabs).style.display = "none"; } } </script>
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(Request.UserLanguages[0]); Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(Request.UserLanguages(0)) Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(Request.UserLanguages.GetValue(0)); | |||
C# | VB | JScript |
若要更改初始语言设置,可使用不同的本地化客户端,或更改浏览器上的语言设置。例如,对于 Internet Explorer 5.x,从菜单中选择“工具”->“Internet 选项”并单击底部的“语言”按钮。在接下来的对话框中,可以添加其他语言,并定义它们的优先级。为简单起见,示例总是选择第一项。
页第一次加载后,用户可在下拉列表控件 MyUICulture 中选择其他区域性。如果选定的区域性有效,此值将重写从 UserLanguages 获得的设置:
String SelectedCulture = MyUICulture.SelectedItem.Text; if(! SelectedCulture.StartsWith("Choose")) { // If another culture was selected, use that instead. Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(SelectedCulture); Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture; } Dim SelectedCulture As String = MyUICulture.SelectedItem.Text If Not(SelectedCulture.StartsWith("Choose")) Then ' If another culture was selected, use that instead. Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(Request.UserLanguages(0)) Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture End If var SelectedCulture:String = MyUICulture.SelectedItem.Text; if(! SelectedCulture.StartsWith("Choose")) { // If another culture was selected, use that instead. Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(Request.UserLanguages.GetValue(0)); Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture; } | |||
C# | VB | JScript |
以前的代码中需要使用 CreateSpecificCulture 方法,原因是您无法将线程的当前 CultureInfo 设置为非特定区域性。但是从 UserLanguages 设置中得到的字符串可以为非特定区域性。因此,CreateSpecificCulture 方法获取该字符串,并从中生成相应的 CultureInfo。
同样,在 Global.asax 文件中,将用应用程序范围初始化 ResourceManager 实例。这样,资源对每个应用程序仅加载一次。因为资源是只读的,因此不会发生锁争用。
public void Application_Start() { Application["RM"] = new ResourceManager("articles", Server.MapPath("resources") + Path.DirectorySeparatorChar, null); } Public Sub Application_Start() Application("RM") = New ResourceManager("articles", _ Server.MapPath("resources") + Path.DirectorySeparatorChar, _ Nothing) End Sub public function Application_Start() : void { Application["RM"] = new ResourceManager("articles", Server.MapPath("resources") + Path.DirectorySeparatorChar, null); } | |||
C# | VB | JScript |
于是就可以在页上轻松地使用资源管理器。问候字符串仅本地化为:
<%=rm.GetString("greeting")%>
|

global.asax |
[ 查看源代码]
|
使用附属程序集
查看前一节示例中的目录结构,可以发现示例的资源不是从 DLL 加载的,而是从 .resource 文件加载。尽管这确实是一种解决方案,但还可以将代码编译为附属程序集。根据定义,附属程序集是仅包含资源、不包含可执行代码的程序集。有关附属程序集的更多信息,请参阅如何做...创建资源。
.resources 文件由于不是 DLL 而不是影像复制的,因此 Web 站点在使用它们时可能会遇到锁定问题。认识到这一点,使用附属程序集的优点就变得十分明显了。另一种方法是使用应用程序资源的并行主程序集。主程序集包含备用的资源;附属程序集(每个区域设置都有一个)包含本地化资源。主程序集安装在 /bin 目录中,而附属程序集存储在普通的 xx-XX 子目录下(请参阅如何做...创建资源)。作为程序集,它们是影像复制的,而且不会被锁定。若要创建程序集识别的 .asp 应用程序:
- 创建资源 DLL 并将其复制到 /bin 目录中。例如:
resgen qq.txt qq.resources
al /embed:qq.resources,qq.resources /out:qq.dll“y”指示 Blob 是否应对其他程序集可见。由于 ResourceManager 位于 Mscorlib 中而且是一个不同于“qq”的程序集,因此 .resources 文件必须是公共可见的。“y”指示这是否应是公共的。
- 在页上包括以下语句。注意,此处的程序集名称位于在 Mscorlib 中定义的 System.Reflection 命名空间中(编译时总要引用它):
<% Assembly a = Assembly.Load("qq"); ResourceManager rm = new ResourceManager("qq", a); Response.Write(rm.GetString("key")); %>
<% Dim a As Assembly = Assembly.Load("qq") Dim rm As ResourceManager = New ResourceManager("qq", a) Response.Write(rm.GetString("key")) %>
<% var a:Assembly = Assembly.Load("qq"); var rm:ResourceManager = new ResourceManager("qq", a); Response.Write(rm.GetString("key")); %>
C# VB JScript - 将每个附属资源编译到各自的程序集中,并将其放入 /bin 目录中所需的正确目录结构中:
al /embed:qq.en-US.resources,qq.en-US.resources /out:qq.resources.dll /c:en-US
将代码替换为正在将 en-US 本地化到的区域性。记住,/c: 标记是区域性说明符。
LocalizedButton 控件存储 ResourceManager 实例,该实例由 LocalizedButton 的所有实例共享。每当呈现一个控件时,Text 属性的值便由本地化版本替换:
_rm = new ResourceManager("LocalizedStrings", Assembly.GetExecutingAssembly(), null, true ); ... override protected void Render(HtmlTextWriter writer) { Text = ResourceFactory.RManager.GetString(Text); base.Render(writer); } _rm = New ResourceManager("LocalizedStrings", _ Assembly.GetExecutingAssembly(), _ Nothing, _ True ) ... Overrides Protected Sub Render (writer As HtmlTextWriter) Text = ResourceFactory.RManager.GetString(Text) base.Render(writer) End Sub _rm = new ResourceManager("LocalizedStrings", Assembly.GetExecutingAssembly(), null, true ); ... override protected function Render(writer:HtmlTextWriter) : void { Text = ResourceFactory.RManager.GetString(Text); base.Render(writer); } | |||
C# | VB | JScript |
ResourceManager 实例负责将键解析为本地化资源。如果具有正确区域性的附属程序集不可用,并且找不到相关的区域性,则使用主程序集的非特定语言资源("en-us" -> "en" -> "非特定语言")。只需将新附属程序集的模块文件复制到适当的位置,即可提供另一种语言支持。
|

本地化控件 |
[ 查看源代码]
|
本节小结
- ASP.NET 页可使用资源类将资源中可本地化的内容分离出来,这部分内容在运行时被选定。
- 另一个好办法是使用附属程序集而不是中间的 .resources 文件加载资源,因为这样可避免锁定问题。
- 已编译控件可包含它们自己的资源,并将根据宿主页的 UICulture 来选择正确的本地化内容。