大家是不是发现,在商店中看到的高大上的应用都有着多语言支持,可以根据操作系统的语言自动适配;或者可以通过用户的选择,显示对应的语言界面,确实很高大上呢。不过这个可不是什么难事,通过简单的几个步骤,让你的应用也高大上起来,支持多语言。这样在你以后的简历里,也可以写上:面向国际市场开发过多语言应用。听上去相当有底气!
0. 准备工作
在建立多语言支持前,首先要看一下 Manifest 文件中的默认语言选项,将它设置为你希望的默认显示语言。
接下来建立存放语言字符串的文件夹。如果是Universal App,就如下图所示,在 Shared 文件夹下建立 Strings 子文件夹,并在其中根据自己 App 希望支持的语言,再建立子文件夹,子文件夹的名称要和语言的编码一致。关于具体语言的编码,可以查询 Language Codes 页面:
http://msdn.microsoft.com/en-us/library/ms533052%28v=vs.85%29.aspx
如果不是 Universal App,那么 Strings 文件夹应该放在项目的根目录下。
建立好文件夹以后,在每个文件夹中添加 "Resources File (.resw)"。微软推荐使用默认文件名,以便在项目中进行调用。如果有特殊命名需求,请参考 How to load string resources (XAML) 页面:
http://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh965323.aspx
这些做完以后,多语言支持的框架就算是搭起来了,剩下的就是往里填写内容了。
1. 填写字符串
以 en-US 举例,我们打开 en-US 的 Resources.resw 文件,会发现其中分为三列,分别是 Name,Value 和 Comment。顾名思义,分别是字符串引用的名称,字符串的内容和字符串的备注或评论。那么我们就开始根据自己的需求填写字符串。其中 Name 和 Value 较为重要,必须填写,Comment 主要是增强可读性,不是必填项。
如果是需要对界面,也就是 XAML 语言定义的部分进行多语言支持,那么 Name 的部分就要像 XAML 语言定义一样,针对控件的每个单元进行定义。例如:
需要对文本框的内容,也就是 Text 进行多语言支持,那么 Name 部分就必须是 NameofTextbox.Text 的格式。比如下图中,我们要对“精华栏标题”进行多语言支持,那么我们首先为精华栏标题命名为 BestTitle,并且针对 BestTitle.Text 这一 Name 填写内容 Best。那么这一工作就做完了。
对于Button控件来说,其文本部分叫做Label(为什么就不能统一叫Text呢?好奇怪啊),所以要给AppButton_Zoom这个button填写一个AppButton_Zoom.Label项。
2. 界面引用字符串
有了这个命名,我们如何在界面中进行调用呢?
很简单,通过 Uid 实现。
找到 XAML 中对应的部分,添加 x:Uid="BestTitle" 这一属性,这样系统就会自动在多语言支持中找到对应的内容,并将 Text 的内容对应赋予该 TextBlock 的 Text 属性。这样,我们就无需在 XAML 文件中将现实的内容硬编码进去,只需要修改对应的资源文件就可以,是不是很方便呢。
<Button Style="{StaticResource Win8TopAppBarButton}" Tag="CNBlogs.Pages.BestPostsPage" Click="NavButton_Click" Padding="30"> <Button.Content> <TextBlock> <Run Text="" FontFamily="Segoe UI Symbol"/> <Run x:Uid="BestTitle" Text=""/> </TextBlock> </Button.Content> </Button>
运行一下看看效果,如果系统语言默认是英文的话,那么显示的内容就已经如我们所愿,变成英文的了。如果不是英文也没有关系,我们可以通过切换系统语言,或者在程序中设置应用语言来实现这一点,设置语言的方法,会在后文讲述。
对应的,我们也要添加上中文的内容,这样才能保证两种语言的对应性。
眼尖的读者一定发现了,不光 Text,连 FontSize 也可以定义么?对的,对于 Width,字体等简单属性,我们都可以根据不同语言的特性,对控件进行根据语言分类的设定,这样才可以使界面更加符合不同语言的特性及使用习惯。
3. 后台代码引用字符串
虽然前台设计主要由 XAML 实现,但是还是会有部分漏网的字符,是在后台的 C# 代码中实现的。对于这些部分的显示,如何调用资源文件中的内容呢?答案也是非常简单的。
首先,在资源文件中定义要调用的字符串。值得注意的是,这里不能像定义 XAML 中使用的字符串一样,使用类似 NameofTextbox.Text 的格式,而是要使用类似于变量命名的命名规则,不能再用”.”等分隔符隔开。否则系统调用会失败。
填写完成以后,我们打开后台 C# 代码,首先添加这一句:
Windows.ApplicationModel.Resources.ResourceLoader loader = new Windows.ApplicationModel.Resources.ResourceLoader();
这样就定义了一个 loader,由他负责从资源文件中找寻对应的语句。
当我们需要字符串的时候,就将字符串的部分替换为 loader.GetString("STRING_NAME")即可,其中 STRING_NAME对应的就是在资源文件中定义的 Name。例如,我们需要调用 "CommentTextblockText_Status1" 和 "CommentTextblockText_Status2" 字符串,那么我们就使用语句:
CommentButton.Content = isCommentTemperarorilyShown ? loader.GetString("CommentTextblockText_Status2") : loader.GetString("CommentTextblockText_Status1");
就可以了。
4. 设置程序语言
如果在 Windows Store App 中希望无视系统语言,强制设置程序语言,也是可以的。我们只需要在页面中添加一句:
Windows.Globalization.ApplicationLanguages.PrimaryLanguageOverride = "zh-CN";
就可以了。不过需要注意,这一句代码执行完了以后,只会对之后打开的页面生效,之前加载的页面的语言并不会发生变化。若希望全局生效,最好的办法是重新启动一下应用程序。
一个更好的办法是建立一个如图的下拉菜单:
这样可以方便用户自己选择界面语言。
遗憾的是,在 Windows Phone 中并没有这么好的全局设定方案,界面语言只能跟随系统显示语言。如果想要重设界面语言,就只能使用另外的黑科技了。
5. 其他
在中文和英文资源文件之间来回切换是个很痛苦的事情,尤其是界面字符串数目比较多的时候。笔者推荐一个插件,可以比较方便的进行语言之间的比较和翻译。
在 Visual Studio 中选择 TOOLS – Extensions and Updates,搜索 ResXManager 这一插件,安装重启以后,在 TOOLS 菜单中就可以打开它,界面如下图所示:
这样的对照界面比原来单一语言界面方便多了,如果有某种语言条目的空缺,他还会标红提醒,实在是多语言及本地化支持的利器。
小结
本地化及多语言支持的技术并无难点,困难之处往往在于多语言特点的兼顾,翻译的准确性及维护上。本文只是万里长征的第一步,后面的路还要开发者们一个字符串一个字符串去铺成……
分享代码,改变世界!
Windows Phone Store App link:
http://www.windowsphone.com/zh-cn/store/app/博客园-uap/500f08f0-5be8-4723-aff9-a397beee52fc
Windows Store App link:
http://apps.microsoft.com/windows/zh-cn/app/c76b99a0-9abd-4a4e-86f0-b29bfcc51059
GitHub open source link:
https://github.com/MS-UAP/cnblogs-UAP
MSDN Sample Code:
https://code.msdn.microsoft.com/CNBlogs-Client-Universal-477943ab