ASP.NET 2.0的全球化与本地化之全球化
在我的网站中,在创建资源文件并加入一些本地化数据后,我首先开始使用显式本地化来设置控件(例如,在我的网站中的标签)的文本,以便它们可以从资源文件中得到它们的值。既然存在四种语言;所以,除一个完全可依赖的资源文件之外(没有本地化命名),我创建了四个资源文件。
|
注意,这些资源文件都以本地化标记作为它们的中间名称,因此,我需要把UICulture设置为与该本地化相同的名字以便ASP.NET存取这些资源文件。
但是,问题是:我该怎样在PostBack事件中动态地改变文化呢?幸好,ASP.NET在Page类中提供了一种可重载的方法: InitializeCulture()。这个方法在页面生命周期(在生成任何控件之前)中执行得很早,并且在此,我们能够设置当前线程的UICulture和Culture。
由于这个方法位于Page类中,并且我不想针对每一个web页面都重复相同的代码,所以我创建了一个BasePage类,我的应用程序中的所有的aspx页面都派生自这个BasePage类。但是现在,我又面临另一个问题。下面,让我进行解释:
回到UI设计:我使用了一个MasterPage和一个Header用户控件(在一个ContentPlaceHolder内)。我把一个缺省的页面与该MasterPage相关联。整个站点必须动态地实现本地化。因此,在顶部,有一个下拉框,用户可以从中选择一种语言/文化。在BasePage的InitilializeCulture方法中,我必须取得用户从下拉框选择的项的值;但是,因为它还没有被初始化,所以,我还不能存取任何控件的值。答案是:使用表单集合(从响应对象内)。下面是实现代码:
///<SUMMARY> ///从通用的页面头部的下拉框列表中选择的语言名。 ///我们需要使用这个名字,因为我们还没有任何其它控件属性-现在控件本身还没有被初始化。 ///因此,我们使用"嵌套的"下拉框列表名,从中我们可以从Request.Form[]集合中得到该下拉框列表的值。 /// </SUMMARY> public const string LanguageDropDownID = "ctl00$cphHeader$Header1$ddlLanguage"; /// <SUMMARY> ///在一个回寄表单中的PostBack事件目标域的名字。你可以使用 ///它来确定是哪个控件触发了PostBack: /// Request.Form[PostBackEventTarget] . /// </SUMMARY> public const string PostBackEventTarget = "__EVENTTARGET"; |
请注意,在此,我是如何使用"parentControl:ChildControl"方法从表单集合中存取控件的。通过使用这一约定,你可以存取任何ASP.NET生成的嵌套控件。借助于表单集合中选择的值,我可以通过一个switch case语句来进行文化设置:
/// <SUMMARY> ///重载InitializeCulture方法来设置在当前线程中用户选择的选项 ///。注意,这个方法在Page生命周期的早期调用 ///,并且目前我们不存在任何控件 ///,因此必须使用Form集合. /// </SUMMARY> protected override void InitializeCulture() { ///<remarks><REMARKS> ///检查是否PostBack发生.不能使用在此方法中使用IsPostBack ///,因为这个属性还没有设置。 ///</remarks> if (Request[PostBackEventTarget] != null) { string controlID = Request[PostBackEventTarget]; if (controlID.Equals(LanguageDropDownID)) { string selectedValue = Request.Form[Request[PostBackEventTarget]].ToString(); switch (selectedValue) { case "0": SetCulture("hi-IN", "hi-IN"); break; case "1": SetCulture("en-US", "en-US"); break; case "2": SetCulture("en-GB", "en-GB"); break; case "3": SetCulture("fr-FR", "fr-FR"); break; default: break; } } } ///<remarks> ///从会话中取得文件,如果控制给导航到同一程序中的一个新页面。 ///</remarks> if (Session["MyUICulture"] != null && Session["MyCulture"] != null) { Thread.CurrentThread.CurrentUICulture = (CultureInfo)Session["MyUICulture"]; Thread.CurrentThread.CurrentCulture = (CultureInfo)Session["MyCulture"]; } base.InitializeCulture(); } /// <Summary> ///使用参数设置当前的UICulture和CurrentCulture /// </Summary> /// <PARAM name="name"></PARAM> /// <PARAM name="locale"></PARAM> protected void SetCulture(string name, string locale) { Thread.CurrentThread.CurrentUICulture = new CultureInfo(name); Thread.CurrentThread.CurrentCulture = new CultureInfo(locale); ///<remarks> ///由用户把当前线程的文化集保存在会话中 ///,以便它能够在当前应用程序中跨页面应用。 ///</remarks> Session["MyUICulture"] = Thread.CurrentThread.CurrentUICulture; Session["MyCulture"] = Thread.CurrentThread.CurrentCulture; } |
因此,用户在他/她选择的语言中会看到此内容。我们需要把该文件选择保存到一个会话或一个Cookie变量中,因为如果用户移动到同一应用程序中的其它一些页面,那么,当新的页面类一开始被实例化时,该线程的文化信息将会丢失(HTTP是无状态的!)。注意,在用户的会话到期时,如果你不想丢失当前线程的文化信息,那么你可以使用Cookies。
一旦我们从web应用程序中提取了所有的内容并且基于用户选择和使用Resources.TestWebSite.XXXPropertyName设置好了Culture和UICulture,那么,我们就已经为我们的全球化框架作好了准备。现在,剩下的唯一事情是把资源特定的数据添加到相应的资源文件中。针对每一种文件类型,我们需要有一个单独的(和适当命名的)资源文件。这个过程称为本地化。在我的web.config文件中,我使用了下列属性:
<globalization responseEncoding"=utf-8" requestEncoding="utf-8" fileEncoding="utf-8" /> |
注意,这里使用了编码属性-utf-8(8位Unicode转换格式),因为它是可变长度字符编码;并且,除了它是ASCII兼容的之外,还能够代表例如Greek,Arabic等语言。有关UTF-8编码的更多信息,请参考下面这个链接:
[url]http://en.wikipedia.org/wiki/UTF-8[/url]
另外,特别值得注意的是,尽管我们能够在发布服务器上拥有原始XML形式的资源文件(这样,用户可以方便地编辑它们而不必重新编译整个站点),但是,如果我们对资源文件作出任何修改的话,应用程序将重新开始运行。这有可能妨碍此发布的应用程序的性能。
二、设置语言方向相应的dir属性
许多时候,我们还需要设置本地化文本的方向(这是使用<html>或<body>标签的dir属性设置的)。这是必需的,因为有些语言从右到左(RTL)读取,例如Arabic,不同于象Hindi和English这样语言的标准的从左到右(LTR)的读取方式。这可以通过把.resx文件中的dir属性设置为适当的值来实现。
首先,你可以在所有资源文件中创建一个Direction(你可以使用任何名)域,并基于单个资源文件把它的属性设置为RTL或LTR。对于Arabic,这个域的值是RTL,而对于Hindi则是LTR。然后,把<body>标签的dir属性设置为如下:
<body runat="server" dir="<%$ Resources: TestSiteResources, Direction %>"> |
这样就可以设置正确的方向,因为该值来自于资源文件(基于当前线程文化)。
三、使用数据库实现本地化
我们已经看到了如何本地化控件的文本和UI描述。但是,存储在数据库中的内容会怎么呢?其实,这一部分内容也需要本地化,但是由于它存储在一个DB中,所以我们不能使用资源文件来实现相同目的。为此,我们需要创建新的表格。
假定我有一个存储用户评价的表格。该表格结构如下所示:
|
现在,我们想实现以本地化的文本来显示Comments和Name字段,但是,我们不可能把所有这些域的不同语言版本都存储在同一个表格中(既然存在不需要被本地化但却重复的其它域)。因此,我们需要重新组织该表格结构并且创建另一个表格来存储这两个域的本地化版本。首先,我们需要从这个表格中删除这两个域并创建一个如下所示的新表格:
|
在此,我们添加了一个新域:CultureID,它等价于LCID(或Locale标识符)。我们能够按如下所示添加文化特定的本地化数据:
|
现在,我们可以使用以CultureID(LCID)作为参数的SQL查询来取得本地化内容。我们还能够提供一个用户接口来把本地化数据输入到这样的表格以便能够以一种交互方式创建相应的内容。
四、总结
在本文中,我们讨论了在ASP.NET 2.0开发中有关实现全球化的一些重要方面,并且看到,这是非常容易实现的事情;但是,也存在许多值得注意的重要问题:
1.不要依赖于web浏览器的设置。你可以在应用程序中显示一个链接(可以在头部位置)以便用户能够通过点击它来选择他们的语言。
2.使用资源文件来把GUI中与描述相关的数据分离开来。资源fallback是ASP.NET使用的方法-当它不能找到相应于一种特定文化的资源文件时。它将首先试用中立资源文件,然后是缺省的资源文件或fallback资源文件(TestSiteResource.resx)。
3.使用数据库表格把数据存储到一个DB中。为此,你需要创建单独的表格来存储本地化内容。
4.如果你使用sn.exe来为你的主应用程序程序集创建一个强类型名,那么,你需要使用同一对密钥对(由sn.exe生成)中的私钥来签名你的小程序集;因为,强类型名字的程序集要求小程序集也应该是强类型名字。
转载于:https://blog.51cto.com/zhuxianzhong/59370
ASP.NET 2.0的全球化与本地化之全球化相关推荐
- 重新过一遍ASP.NET 2.0(C#)(5) - Localization(本地化,多语言)
介绍 声明性资源表达式可使您的应用程序使用多种语言,而不必手动编写代码来检索资源并在页中进行替换.您只需使用 ASP.NET 2.0 中新提供的表达式语法即可对资源替换进行定义.ASP.NET 2.0 ...
- ASP.NET 2.0 中的资源与本地化
转自MSDN 下载本文的代码:BasicInstincts2006_08.exe (878KB) 本页内容 控制页面级别的区域性设置 使用配置文件跟踪语言首选项 ASP.NET 2.0 中的资源文件 ...
- ASP.NET2.0中的全球化与本地化UICulture,Culture
ASP.NET2.0中的全球化与本地化UICulture,Culture 来源:转载 日期:2007-2-28 14:59:01 阅读:324 评论:0 一.简介 全球化和本地化是每一位开发者在创 ...
- ASP.NET全球化与本地化 c#多国语言的支持 (项目支持多国语言的开发)
ASP.NET 2.0及以上的开发平台,为全球化本地化应用程序提供了工具,而且实现起来非常简单.以下内容是使用c#,按照帮助一步步做的,将为初学者提供详细的实现步骤. 一 几个必要概念 (一) 支持全 ...
- Asp.Net Core 混合全球化与本地化支持
前言 最近的新型冠状病毒流行让很多人主动在家隔离,希望疫情能快点消退.武汉加油,中国必胜! Asp.Net Core 提供了内置的网站国际化(全球化与本地化)支持,微软还内置了基于 resx 资源字符 ...
- ASP.NET 2.0 本地化功能:本地化 Web 应用程序的新方法
适用于: Microsoft ASP.NET 2.0 Microsoft Visual Studio .NET Microsoft Visual Studio 2005 本地化 摘要:随着越来越多的公 ...
- 从Asp.net实现资源全球化和本地化
本文将从Asp.net实现资源全球化和本地化的基本概念入手,阐述在Asp.net1.1和Asp.net2.0中实现全球化和本地化的步骤.方法. 一.基本概念 1.为什么要实现资源的本地化? 我们的站点 ...
- 本地化在ASP.NET 2.0中的实现
这是来自在CodeGuru上的一篇文章,主要讲述了如何在ASP.NET 2.0中实现本地化的问题,而且文中对于一些常用术语以及资源文件在ASP.NET 2.0中的用法给出了很多说明,是初学者学习的一篇 ...
- asp.net 2.0 语言包 全球化
asp.net 2.0 语言包 全球化 新建一个测试站点添加 一个页面 test.aspx 在页面上拉出一个label控件命名为了 labTest 添加两个特殊的文件夹App_GlobalResour ...
最新文章
- 网络工程师应掌握的50个路由器知识要点
- 5G NR — Open vRAN 的组织单位
- Css2.0+Css3.0+jQuery手册 chm
- 免费的容器架构可视化工具 | 阿里云应用高可用服务 AHAS 发布重大新特性
- Flink watermark
- python空格算一个字符吗_举例说明python中空格是属于字符
- 桥牌笔记:一定要飞张?
- Oracle开发艺术
- win10无法装载iso文件_win10系统解决方案无法打开iso文件
- nmap扫描服务器端口不稳定,端口扫描命令nmap
- Unity塔防游戏学习(六)
- 激光雕刻机装上AI,混合材料T恤上都能雕出花,自动变换力度保证不割破
- Python实现小说下载器,可以打包exe
- IDEA中出现Connection refused: connect问题的解决方法
- 【CCF 201903-2】 二十四点(符号栈)
- 国产服务器(aarch64) Kettle 修改
- 作文总结思维导图怎么画?分享作文类型总结思维导图模板
- python---控制时间的函数time()
- 做工程设计类计算机配置,专业设计制图需要什么样的电脑?制图电脑配置要求 (全文)...
- 正方形里面两个扇形相交部分_边长为1的正方形内,两个扇形,一个半圆,求阴影面积....