WPF & Sivlerlight 多语言解决方案---本地化
多语言实现有很多方式, 最近一个WPF项目需要用到多国语言, 而其中以en-US为基本语言, 这样经过摸索终于找出一种解决方式.
1. WPF使用传统.net Resources.resx是可行的, 但总是觉得没有使用到WPF Resource 那么方便;
2.WPF resource 文件, 开始总是没法实现多语言方案,后来 在微软社区终于找到了对应用程序进行本地化 的这篇文章, 解决了我的问题.
3.下面描述一下我的步骤:
第一步:项目根目录下,新建资源文件Language.xaml, 如下:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation%22
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml%22
xmlns:system="clr-namespace:System;assembly=mscorlib">
<system:String x:Uid="MainOpen" x:Key="MainOpen">Open</system:String>
<system:String x:Uid="MainNew" x:Key="MainNew">New</system:String>
<system:String x:Uid="MainProperty" x:Key="MainProperty">Pproperty</system:String>
<system:String x:Uid="MainSave" x:Key="MainSave">Save</system:String>
<system:String x:Uid="MainPageNew" x:Key="MainPageNew">New Page</system:String>
<system:String x:Uid="MainPageProperty" x:Key="MainPageProperty">Page Property</system:String>
<system:String x:Uid="MainPageDel" x:Key="MainPageDel">删除页面</system:String>
</ResourceDictionary>
第二步:在App.xaml 中, 注意Source="/Language.xaml" 前面”/”,我开始这个地方搞了好长时间:
<Application.Resources>
<ResourceDictionary >
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Language.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
这样可以在应用程序中任何地方都可以使用这个资源了, 至于怎么在WPF和silverlight中使用资源文件, 不在此文范围内, 请大家参考wpf资源的教程.
测试使用字符串资源, 新建一个窗口WinTest.xmal
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation%22
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml%22
x:Class="Exio.NR.WPF.Designer.WinTest"
x:Name="Window"
Title="WinTest"
Width="640" Height="480"><StackPanel VirtualizingStackPanel.VirtualizationMode="Recycling" HorizontalAlignment="Left" VerticalAlignment="Top">
<Label Content="{DynamicResource MainNew}"/>
<Label Content="{DynamicResource MainOpen}"/>
<Label Content="{DynamicResource MainPageDel}"/>
<Label Content="{DynamicResource MainPageProperty}"/>
<Label Content="{DynamicResource MainSave}"/>
</StackPanel>
</Window>
第三步: 使用MSBuilder编译
文本打开项目文件 xxx.csproj, 在每个PropertyGroup下添加<UICulture>en-US</UICulture>, 这一步是网上抄袭来的, 在后面会有问题报错, 暂时我们不管.
运行 MSBuilder编译, 具体命令为什么是3行,请参考 对应用程序进行本地化 的这篇文章:
msbuild /t:updateuid projName.csproj
msbuild /t:checkuid projName.csproj
msbuild projName.csproj
第四步: 错误解决
ok,我们做完了编译工作, 可以运行了, 启动程序, 会报一系列找不到App.xaml的错误, 最终发现是找不到对应语言的资源文件, 因为我的系统是中文系统, 也就是我编译的资源是 en-US的, 但是我的系统需要的 zh-CN, 怎么办哪?
2种方案:
1).改项目文件 xxx.csproj, 在每个PropertyGroup下使用<UICulture>zh-CN</UICulture>, 再用MSBuilder编译, 运行没问题了;
2).可是我的所有资源都是英文的,改过来工程浩大, 使用第一种方案,又感觉另类; 还有一种方式, 在我们AssemblyInfo.cs文件中添加一行[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] , 这个是设置最终回退的资源, 则当系统是中文的时候,先去找zh-CN下的资源,如果 zh-CN\projName.resources.dll不可用的时候例如这个dll被删除了),则中文版 Windows 将使用 en-US\projName.resources.dll。 ok, 再用MSBuilder编译, 运行没问题了;
这样我们编译生成了en-US版本的资源文件.
第四步: 使用LocBaml 导出(Parse) 资源和 生成(Trans) 新语言资源
具体参考对应用程序进行本地化 , 但是我的项目里面,我主要用到的是字符串资源, 通过LocBaml 导出的东东太多, 一个难找, 第二主要还是容易修改出错, 怎么办哪?
我修改了LocaBaml, TranslationDictionariesWriter.Write 中 65行(write out each resource 的foreach), 我只导出字符串资源文件.
foreach (DictionaryEntry entry in dict)
{
BamlLocalizableResourceKey key = (BamlLocalizableResourceKey)entry.Key;
BamlLocalizableResource resource = (BamlLocalizableResource)entry.Value;
if (!key.ClassName.Equals("System.String")) continue;
// column 1: baml stream name
writer.WriteColumn(bamlStreamList[i].Name);// column 2: localizable resource key
writer.WriteColumn(LocBamlConst.ResourceKeyToString(key));……
注:这样做, 只适合我的解决方案, 因为我没有用到其它资源文件, 具体情况具体考虑,这个只是参考.
ok, 使用 LocBaml.exe /generate en-US/projName.resources.dll /trans:projName-cn.csv /out:E:\ /cul:zh-CN
拷贝到你的运行目录的zh-CN文件夹下试试看.
这种方式不好之处是无法切换语言, 但是他会根据你的操作系统来决定你的语言,让你不需要选择语言, 后面一篇文章将介绍怎么利用 WPF Resource来实现语言切换.