本地化是Silverlight应用或多或少要面临的问题,然而,Silverlight 2对本地化的支持还存在或多或少的问题。以至于,我们不能完全实现类似于在Asp .NET应用中的本地化策略和方案,因此本文的目标是探索Silverlight应用中的本地化实现方法,及其过程。当然,我们也会顺便期望下一个Silverlight版本对多语言支持应有的改善。废话少说,我们开始。
准备资源文件
*.resx
首先,我们需要创建不同的语言版本的资源文件,例如此处包括的en-US和zh-CN两种资源文件:
创建的资源文件被命名为Lables.resx,对应的语言文件分别为Labels.en-US和Lables.zh-CN以实现对应用和中文的支持,关于资源文件的命名规则,详情参考MSDN(http://msdn.microsoft.com/en-us/library/system.globalization.cultureinfo.aspx), 或者也可以通过CultureAndRegionInfoBuilder来访问语言和地区信息。
Note:Labels.resx必须设置为Public,以便于自动产生的后台代码能够在用户代码中被调用,我们随后将会看到。
将Labels.resx复制为Labels.en-US和Labels.zh-CN,并实现相应的value值。
*.csproj
为了将资源文件程序集打包到*.xap文件中,我们必须修改*.csproj文件的SupportedCultures属性为:
<SupportedCultures>zh-CN;en-US</SupportedCultures>
这样,当编译Silverlight应用时,资源文件的程序集将包含在*.xap包中,实现在运行时支持本地化语言,我们解压*.xap可以看到:
*.xap
App.xaml
有了资源文件支持,我们就可以开始在Silverlight应用中实现多语言了,首先要做的工作是为当前线程指定期望的语言文化:
private voidApplication_Startup(objectsender,StartupEventArgse)
{
//Add localization control
CultureInfoculture=newCultureInfo("zh-CN");
Thread.CurrentThread.CurrentCulture=culture;
Thread.CurrentThread.CurrentUICulture=culture;
this.RootVisual=newBase();
}
*.cs
这样,我们就可以在c#代码还有*.xaml代码中,访问资源文件:
In our code mode, resouce will be call like this,
private void UserControl_Loaded(object sender, RoutedEventArgs e) { tbCopyright.Text = Lables.Copyright; }*.xaml
在xaml模式下,资源文件是以StaticResource形式绑定到需要使用的地方,所以我们首先引入资源文件所在的命名空间:
xmlns:res="clr-namespace:Anytao.SLScenario.Localization.Resources"同时,在页面中添加ResLables
<UserControl.Resources> <res:Lables x:Name="ResLables"></res:Lables> </UserControl.Resources>
这样,我们就可以使用啦:
<Grid x:Name="LayoutRoot" Background="White"> <StackPanel Orientation="Vertical"> <TextBlock x:Name="tbName" Text="{Binding Name, Source={StaticResource ResLables}}" /> <TextBlock x:Name="tbAge" Text="{Binding Age, Source={StaticeResource ResLables}}" /> <Button x:Name="btnSayHello" Content="{Binding Say, Source={StaticResource ResLables}}" Click="btnSayHello_Click" /> <TextBlock x:Name="tbCopyright" FontSize="15" Foreground="Red" /> </StackPanel> </Grid>Note:一个严重的问题是,按照正常操作的顺序以F5执行,在InitializeComponent时将引发AG_E_PARSER_UNKNOWN_TYPE异常,而该异常是由StaticResource定义引起的,最后检查到的原因是自动生成的资源类中,其构造器被声明为internal而非public,从而导致外部对于资源类实例的初始化不可访问,所以采取的办法是手动修改internal为public,当时每当修改资源文件之后,我们都必须再次手动执行之一麻烦。
好了,现在我们可以搞一杯上好的碧螺春,来修改你自己的本地化Silverlight应用了:
配置默认的语言文化
动态的获取语言文化是本地化非常重要的方面,例如在ASP.NET应用中,默认的语言文化被实现在web.config配置中,App启动时将以配置信息初始化当前线程的语言文化,在Silverlight中我们该如何为Silverlight应用添加类似的配置呢?
如果你的Silverlight应用寄宿在*.html页面中,那么需要添加cultrue和uiculture参数,如下:
*.html
<object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%"> <param name="source" value="ClientBin/Anytao.SLScenario.Localization.xap"/> <param name="onerror" value="onSilverlightError" /> <param name="background" value="white" /> <param name="minRuntimeVersion" value="2.0.31005.0" /> <param name="autoUpgrade" value="true" /> <param name="culture" value="en-US" /> <param name="uiculture" value="en-US" /> <a href="http://go.microsoft.com/fwlink/?LinkID=124807" style="text-decoration: none;"> <img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style: none"/> </a> </object>
如果你的Silverlight寄宿在*.aspx页面,那么我们同样可以将配置信息添加到web.config
web.config
当然,我们需要通过InitParams来传递配置文件的信息:
string currentCulture = e.InitParams["c"]; //Add localization control CultureInfo culture = new CultureInfo(currentCulture); Thread.CurrentThread.CurrentCulture = culture; Thread.CurrentThread.CurrentUICulture = culture;
在web.config添加默认的语言文化信息:
<appSettings> <add key="currentCulture" value="zh-CN"/> </appSettings>*.aspx
还需要在寄宿页面的Page_Load事件中获取配置信息,并传递给InitParameters:
protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { string c = ConfigurationManager.AppSettings["currentCulture"]; this.anytaoSL.InitParameters = string.Format("c={0}", c); } }这样,我们就有效的整合了Silverlight应用和ASP .NET应用的本地化方案,通过配置信息的修改我们可以很容易的对你的系统进行多语言文化的切换,这简直好爽啊。当然,如果有更多的想法,我们还可以将culture作为URL的选项,来开关多语言的切换,在本文的方案之上,实现这一目标是很容易的,我们期望在后文中给出在URL中进行语言切换的简单的实现。
通过本文的论述,我们感受到Silverlight对本地化的支持还存在需要改善的地方,表现在:
- 将资源文件程序集打包到*.xap包是一个痛苦的方案,需要和值得改进。
- 生成资源文件的后台类时,构造器的访问修饰符值得商榷。