Silverlight 2中多语言支持实现(上)

引言

最近项目要在Silverlight 2应用程序中实现本地化,原以为这个过程非常简单,却没想到实现的时候一波三折,好在结果还算不错。需求是这样的,用户第一次访问的时候,默认为英文,当用户选择一种显示语言后,记录在本地,下次用户访问时直接显示已经选择的语言。现在我把整个实现的过程记录下来,希望对大家有所帮助。

本文为Silverlight 2中多语言支持实现第一部分。

准备工作

我们发现在Silverlight 2中提供了ResourceManager类,这意味着可以通过资源文件来实现,首先在Silverlight项目中建立一个文件夹,命名为Resources,添加一个资源文件Strings.resx,并添加几个值,如下图所示:

TerryLee_0007

该文件将作为默认资源文件,设置Access Modifier为Public,它将会生成Strings.Designer.cs文件,如下图所示:

TerryLee_0008 

现在再创建几个其它语言的资源文件,如中文、法语、挪威语等,注意资源文件的命名方式,都是以Strings+语言文化构成,有关每一种语言文件的代码,大家可以查阅MSDN。

TerryLee_0009

其它这些文件的Access Modifier的设置为No Code generation。有了前面这些准备工作,接下来进行实现。

实现

有了上面这些资源,我们很容易想到利用Silverlight中的静态资源来绑定到UI控件上面,首先定义资源文件:

TerryLee_0011

绑定到UI控件上,如我们放置三个按钮:

TerryLee_0012

最后我们只剩下一步工作,就是指定当前线程的语言文化和UI语言文化,这一点我们可以在Application_Startup事件中来实现,我们设置为zh-CN,如下代码所示:

TerryLee_0010

至此工作完成,可是当我们编译时却发现有这样的错误:

Type 'Strings' is not usable as an object element because it is not public or does not define a public parameterless constructor or a type converter

很明显Strings类型的构造函数访问性不是public,打开Strings.Design.cs文件可以看到,它的构造函数是internal的,这一点好办,手工修改为public(也许该问题将会在RTM中解决)。但是要注意,每次当修改完Resource文件后,它会再次变为internal类型。

TerryLee_0013

问题出现

现在编译成功,可是当运行时却并没有出现我们想要的结果。我们首先会想到,资源文件编译后是否下载到了本地,也就是是否打包到了xap文件中,这一点很好证实,我们可以解压xap文件来看看,果然不出所料,如下图所示:

TerryLee_0014

在xap文件中,除了Silverlight项目程序集之外,并没有任何与资源文件有关的东西。有一种“暴力”的办法可以解决这个问题,那就是我们拷贝Silverlight项目bin\Debug文件夹下的资源文件,手工进行打包xap文件,并且需要在xap文件的AppManifest.xaml文件夹中手工加入AssemblyPart,如下代码所示:

TerryLee_0015

事实证明,这样确实可以得到多语言的支持,问题在于每次编译后,xap文件都会重新生成一次。总是这样手工打包也不是长久之计,所以必须想办法彻底解决问题,也许到了Silverlight 2.0 RTM,这个问题已经不存在了。

问题解决

我们打开Silverlight项目文件(.csproj),可以看到有SupportedCultures这样一项,如果在这里进行了设置,再编译Silverlight项目时将会自动打包资源文件,如下图所示,我们添加一项zh-CN:

TerryLee_0016

现在再解压xap文件看看效果,可以看到,现在zh-CH资源文件已经打包在了xap文件中:

TerryLee_0017

运行程序,可以看到已经显示为中文了:

TerryLee_0018 

到这里,终于可以松一口气了,下面接着实现其它功能。

添加本地存储

现在我们要实现本地存储功能,这个不是什么难事,可以通过Silverlight 2中的隔离存储来实现。在用户选择一种语言后保存到本地:

TerryLee_0019

然后在应用程序启动时,读取该配置:

TerryLee_0020

好了,现在我们来看一下效果:

英文

TerryLee_0021

中文:

TerryLee_0018 

总结

至此,简单的多语言支持算是实现了,其实还有其它的问题没有解决,我将在下一篇分析。最后再啰唆一句:Silverlight 2 Beta 2对于多语言支持的支持实在是...

作者:TerryLee
出处:http://terrylee.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
Tag标签: Silverlight
posted @ 2008-06-19 01:05 TerryLee 阅读(5610) 评论(43)  编辑 收藏 所属分类: [03]  银光点亮世界

  回复  引用  查看    
#1楼2008-06-19 01:07 | Eeyore      
哈,这么晚还发贴,我来顶你Terry~
  回复  引用  查看    
#2楼[楼主]2008-06-19 01:12 | TerryLee      
@Eeyore
这么晚还来回帖,感动啊,呵呵。。。

  回复  引用  查看    
#3楼2008-06-19 02:23 | 萧寒      
顶一下再睡
  回复  引用    
#4楼2008-06-19 08:14 | Arvin[未注册用户]
老零晨发文,别累坏
  回复  引用  查看    
#5楼2008-06-19 08:15 | aspnetx      
Terry最近发帖都好晚啊,呵呵.要注意休息哦.
  回复  引用  查看    
#6楼2008-06-19 08:23 | jisen      
新单位不错啊!
  回复  引用    
#7楼2008-06-19 08:48 | ZhaoJun[未注册用户]
楼主的学习能力实在是很强啊!
  回复  引用  查看    
#8楼2008-06-19 09:12 | Windie Chai(笑煞天)      
又学习了!!!谢谢楼主。
  回复  引用  查看    
#9楼2008-06-19 09:21 | Anytao      
早上来,再顶不迟
  回复  引用    
#10楼2008-06-19 09:22 | Jeffrey Chen[未注册用户]
顶,学习了!!!!
  回复  引用  查看    
#11楼2008-06-19 09:23 | 代震军      
不错不错,呵呵:)
  回复  引用  查看    
#12楼[楼主]2008-06-19 09:44 | TerryLee      
@萧寒
谢谢:)

  回复  引用  查看    
#13楼[楼主]2008-06-19 09:45 | TerryLee      
@Arvin
好,谢谢,我会注意的:)

  回复  引用  查看    
#14楼[楼主]2008-06-19 09:45 | TerryLee      
@aspnetx
嗯,多谢:)

  回复  引用  查看    
#15楼[楼主]2008-06-19 09:46 | TerryLee      
@jisen
新单位是挺好,呵呵

  回复  引用  查看    
#16楼[楼主]2008-06-19 09:46 | TerryLee      
@ZhaoJun
过奖了,这是实际项目中遇到的问题,折腾的我够呛,所以分享出来,希望对大家有所帮助。

  回复  引用  查看    
#17楼[楼主]2008-06-19 09:47 | TerryLee      
@Windie Chai(笑煞天)
客气了,呵呵

  回复  引用  查看    
#18楼[楼主]2008-06-19 09:48 | TerryLee      
@Anytao
Anytao比我来得早啊,现在睡的晚,早晨都起不来了。。。

  回复  引用  查看    
#19楼[楼主]2008-06-19 09:48 | TerryLee      
@Jeffrey Chen
谢谢支持:)

  回复  引用  查看    
#20楼[楼主]2008-06-19 09:49 | TerryLee      
@代震军
不过还有一个致命的缺陷本文没有提到,将会在第二部分中说明。。。

  回复  引用  查看    
#21楼2008-06-19 10:08 | 王德水      
大侠的文章总是图文并茂,简单易懂,谢谢
  回复  引用  查看    
#22楼2008-06-19 10:35 | Jason.Wei      
都顶啊..
我也ding下...

  回复  引用  查看    
#23楼2008-06-19 11:13 | Jason.Wei      
TerryLee.有两个问题:
1.
<UserControl.Resources>
<local:Strings x:Name="LocStrings"></local:Strings>
</UserControl.Resources>
是放在Grid标记内?还是独立出来?
如是独立出来.为何提示:
类型"Strings"不能用作对象函数,因为它不是公共的.或者它不是公共构造函数..
2.如果是放在Grid标记内:却为何出现:
错误 1 未在类型“UserControl”中找到可附加的属性“Resources”。 E:\Web\silverlight\Projects\JasonWei.languages\JasonWei.languages\Page.xaml 7 10 JasonWei.languages

  回复  引用  查看    
#24楼[楼主]2008-06-19 11:23 | TerryLee      
@王德水
谢谢支持:)

  回复  引用  查看    
#25楼[楼主]2008-06-19 11:25 | TerryLee      
@Jason.Wei
是放在UserControl下面的,如果想放在Grid里面,就应该是Grid.Resources而不是UserControl.Resources

“类型"Strings"不能用作对象函数,因为它不是公共的.或者它不是公共构造函数.. ”
这个错误我在文章中已经解释过了。“很明显Strings类型的构造函数访问性不是public,打开Strings.Design.cs文件可以看到,它的构造函数是internal的,这一点好办,手工修改为public(也许该问题将会在RTM中解决)。但是要注意,每次当修改完Resource文件后,它会再次变为internal类型。”

  回复  引用  查看    
#26楼2008-06-19 11:34 | Jason.Wei      
@TerryLee
ok.已解决.谢谢.
至于Strings的问题,是我没有注意.sorry.再让你解答下

  回复  引用  查看    
#27楼2008-06-19 11:55 | Jason.Wei      
@TerryLee
是放在UserControl下面的,如果想放在Grid里面,就应该是Grid.Resources而不是UserControl.Resources
---------------------------
Grid标记并没有提供.Resources吧?
还有,Application_Startup事件我没有找到......

  回复  引用  查看    
#28楼[楼主]2008-06-19 12:13 | TerryLee      
@Jason.Wei
Grid怎么可能没有提供Resources呢?

Application_Startup事件在App.xaml文件中。

  回复  引用    
#29楼2008-06-19 16:20 | Helloword[未注册用户]
呵呵,回去试一下。
  回复  引用  查看    
#30楼[楼主]2008-06-19 16:57 | TerryLee      
@Helloword
还是有一个问题没有得到解决,在第二部分我会分析一下,呵呵

  回复  引用  查看    
#31楼2008-07-01 15:01 | pazzini      
支持一下,呵呵
  回复  引用  查看    
#32楼[楼主]2008-07-01 22:14 | TerryLee      
@pazzini
:)

  回复  引用  查看    
#33楼2008-07-29 11:45 | 不若相忘于江湖      
李兄。我照着你的第一个实例做的, 请看下我的代码。为何在页面上总会报JS

的错误。 项目可以编译通过。

<UserControl x:Class="Wcf.Page"
xmlns="http://schemas.microsoft.com/client/2007"" target="_new">http://schemas.microsoft.com/client/2007"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"" target="_new">http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Locals="clr-namespace:Wcf.Resources"
Width="600" Height="300" >
<UserControl.Resources>
<Locals:Strings x:Name="LocStrings"></Locals:Strings>
</UserControl.Resources>

<Canvas>

<Button Content="dd"/>

<Button Content="{Bind Save,Source={StaticResource LocStrings}}"/> //这样总提示不能包含这样的Content属性
<Button Content="{Bind Cancel,Source={StaticResource LocStrings}}"/>
<Button Content="{Bind Cancel,Source={StaticResource LocStrings}}"/>
</Canvas>
</UserControl>

  回复  引用  查看    
#34楼2008-07-29 11:46 | 不若相忘于江湖      
难道我的是BETA 2 的原因?
  回复  引用  查看    
#35楼[楼主]2008-07-30 00:55 | TerryLee      
@不若相忘于江湖
Bind Save,Source={StaticResource LocStrings}

应该是Binding。。。

  回复  引用  查看    
#36楼2008-11-03 16:41 | chenming      
Language--这个类是哪里的?
  回复  引用  查看    
#37楼[楼主]2008-11-05 09:37 | TerryLee      
@chenming
自定义的-_-

  回复  引用  查看    
#38楼2008-11-10 13:23 | baggiojing      
转帖了,thanks
  回复  引用  查看    
#39楼[楼主]2008-11-12 11:17 | TerryLee      
@baggiojing
保留原文出处即可:)

  回复  引用    
#40楼2009-01-08 17:45 | Chuanbo Zhang[未注册用户]
生成的Resource 文件code behind是internal 的问题,有更新么?
  回复  引用  查看    
#41楼[楼主]2009-01-12 11:29 | TerryLee      
@Chuanbo Zhang
RTW版中应该解决了吧,我没有测试。

  回复  引用    
#42楼2009-03-27 11:04 | kurokawa[未注册用户]
李兄你好!最近小弟在做项目时也需要用到多语言支持,看了你这篇文章受益良多。但是我按照你的方法写好资源文件之后,把资源文件引进page.xaml里面时就出现问题了。错误提示以下:

System.Windows.Markup.XamlParseException: AG_E_PARSER_UNKNOWN_TYPE [Line: 12 Position: 37]
位于 System.Windows.Application.LoadComponent(Object component, Uri resourceLocator)
位于 AceWorkFlowPractise.WorkflowMod.Page.InitializeComponent()

page.xaml的开头部分代码如下:
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:theming="clr-namespace:Microsoft.Windows.Controls.Theming;assembly=Microsoft.Windows.Controls.Theming"
xmlns:myControl="clr-namespace:AceWorkFlowPractise.WorkflowMod"
xmlns:local="clr-namespace:AceWorkFlowPractise.WorkflowMod.Resources"
x:Class="AceWorkFlowPractise.WorkflowMod.Page"
Width="1000" Height="550" Loaded="UserControl_Loaded"
theming:ImplicitStyleManager.ApplyMode="Auto" theming:ImplicitStyleManager.ResourceDictionaryUri="Themes/Microsoft.Windows.Controls.Theming.ExpressionLight.xaml"
>
<UserControl.Resources>
<local:StaticStrings x:Name="locRes"></local:StaticStrings>
</UserControl.Resources>

从报错的信息来看,好像是初始化时转换xaml标签时出错,而且按照错误位置来看应该是UserControl.Resources标签出问题,请教究竟是什么问题呢,我的silverlight是2.0正式版。

  回复  引用    
#43楼2009-03-27 11:42 | kurokawa[未注册用户]
不好意思,上面的问题已经解决了,又是internal构造函数的问题。但是为什么我没有Type 'Strings' is not usable as an object element because it is not public or does not define a public parameterless constructor or a type converter的提示呢?奇怪。



发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 1225088





相关文章:

相关链接: