it步行者

天地间有我在行走。
  首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

开发.net多语言程序

Posted on 2005-07-03 11:56  itwalker  阅读(4079)  评论(5编辑  收藏  举报

/******************************************************************************************
 *【Author】:itwalker
 *【Email】:itwalker@hotmail.com
 *【Date】:2005年7月3日
 *【Notice】:
 *1、本文为原创技术文章,首发博客园(www.cnblogs.com),转载和引用请注明作者及出处。
 *2、本文必须全文转载和引用,任何组织和个人未授权不能修改任何内容,并且未授权不可用于商业。
 *3、本声明为文章一部分,转载和引用必须包括在原文中。
 ******************************************************************************************/

最近开发工作涉及到.net程序的多语言支持,完成之后,发现这项工作其实分两部分,第一部分是关键,实现多语言的几个对象和方法,第二部分是体力活,把程序中所有涉及到有文字表述的地方——title、label、text、message依次在资源文件中对应输入准备实现的语种语言。而实际上,即使是件体力活,你还是会发现,实现程序的多语言支持,是一件比较有趣的工作。

从.net的多语言模型来看,多语言的关键是资源文件和.net提供的资源管理类ResourceManager(当然,实现多语言不会只用到这一个类,还需要其他几个类),不同的语种对应一个资源文件,资源文件是多语言的载体,ResourceManager类是实现多语言的调度。没有多语言支持的程序,所有程序中的文字信息在编译的时候生成在程序集中,提供多语言支持的程序,最终将生成一个主程序集和对应的多语言附属程序集,用反编工具查看附属程序集,全部是资源文件中的内容。MSDN的资料也讲:资源文件从Visual Studio XML 格式 (.resX) 编译为中间二进制格式 (.resources),然后将该二进制文件嵌入附属程序集中(ms-help://MS.MSDNQTR.2003FEB.2052/vbcon/html/vbconInternationalizingApplications.htm)。原来如此。

因为是总结性的备忘文章,下面记录的是实际中参照MSDN的相关文章遇到问题的地方。

一、web应用的多语言:
ms-help://MS.MSDNQTR.2003FEB.2052/vbcon/html/vbwlkWalkthroughLocalizingWebForms.htm

web界面实现多语言所有的详细过程都在MSDN这篇文章中。不过,有两点不太符合实际工作,文章面向的是一个只有一个页面的样例工程,而我需要处理的是二、三十个web页面,按照文章所述方法一个页面一个页面去设置多语言区域,工作量过大,如果是成百上千个页面就崩溃了。我需要有一个地方来统一设置多语言的区域信息,然后具体页面只需关心在什么地方替换成对应语言即可。另外,样例的多语言支持,是根据客户端浏览器的语言区域信息来决定显示语言,而我们要实现的是根据webv.config的设置来决定显示语言。比如,即使是中文浏览器,但如果指定的是英文版,显示的就应该是英文。

对于第一个问题,很自然的,想到Global.asax.cs中的Application_BeginRequest事件方法。于是,在Application_BeginRequest事件方法中加入这样的代码:

protected void Application_BeginRequest(Object sender, EventArgs e)
{
    Thread.CurrentThread.CurrentCulture
=new CultureInfo(ConfigurationSettings.AppSettings["DefaultCultrue"]);

    Thread.CurrentThread.CurrentUICulture
=Thread.CurrentThread.CurrentCulture;
}

DefaultCultrue,就是在web.config文件中配置版本的项。
然后是在页面中的操作,这里遇到些周折。

LocRM= new ResourceManager("LocProject.strings"typeof(WebForm1).Assembly);

从上面的样例代码中参数typeof(WebForm1).Assembly来看,似乎没有什么问题,在每个页面Page_Load 中拷贝上这句,修改成对应页面名称即可,但是能不能用一个通用的对象来代替这个Assembly对象而不用指定页面呢?经过几次周折,最后发现可以这样实现:

System.Type oType=this.GetType().BaseType;
LocRM
=new ResourceManager("LocProject.strings",oType.Assembly);

第一部分就这样搞定,其余的就是第二部分的体力活了,不表。

二、windows应用的多语言
ms-help://MS.MSDNQTR.2003FEB.2052/cssample/html/vcsamMultilingualFormSample.htm

这里的样例和文章基本上只是起了一个参考作用,因为跟我最终要实现的有所不同。

windows应用的多语言支持稍有不同,体现在两方面,一个是没有可保存设置的配置文件(当然自己加上也不是什么问题),另一个就是用实例化通用Assembly对象也有不同。

对第一个问题,经过测试,发现应用程序能自动识别当前操作系统语言版本调用相应语言,如果使用配置文件需要用户自己设定,这个不同于web应用,管理员设置一次即可,意义不大,于是决定不作处理,让应用程序自动识别操作系统语言版本调用相应语言,需要解决的就是第二问题了。

其实,第二个问题的发现和解决都在第一个问题中,使用web页面上的方法来取用当前窗体类型出错,单步跟踪调试,发现用“this.GetType().BaseType”取到的类型名称是“System.Windows.Forms.Form”,显然不对,用监视查看了一下代码“this.GetType()”获得的对象,居然FullName一项中正是需要的内容,修改了一下代码:

System.Type oType=this.GetType();

继续体力活,结束之后用虚拟机启动英文版的windows,运行修改之后的windows应用,结果跟预期相符。

三、Office COM外接程序的多语言
这个虽然MSDN上没有相关文章,不过,道理是一样的,跟上面windows应用的多语言不同的地方就是,上面windows应用的多语言需要在每个窗体中实现,而office COM有窗体的地方实现一样,没有窗体而有message的地方,就针对类进行处理,在类的构造函数中实例化ResourceManager对象。

另外,区域性名称遵循 RFC 1766 标准,详细的名称、地区对应表在CultrueInfo类中可以找到。要注意的是,资源文件的命名和web.config中的配置要使用特定区域名称而不能使用非特定区域名称,比如,英文,应该指明使用美国英语“en-us”还是英国英语“en-GB”,而不能仅仅使用“en”。

最后,上述三类.net程序的多语言支持工作完成用了一个工作周时间,体力活的时间四天半,第一部分只用了半天……古人说,得鸟者,罗之一目,一目之罗,不可得鸟。应该是了。