促使程序贏得更多客戶的最好、最經濟的方法是使之支持多國語言,而不是將潛在的客戶群限制為全球近70億人口中的一小部分。本文介紹四種實現WPF應用程序支持多國語言的解決方案。
效果如下圖:
Language - en-US (英文)
Language - zh-CN (中文)
閱讀目錄
一、使用LocBaml工具
這是微軟MSDN給出的一種解決方案,請參見如何:對應用程序進行本地化。這種方式操作相對繁瑣,不能方便的實現在程序運行過程中動態切換語言,但是新增支持語言無需對項目重新編譯,這是這種實現方式的一個亮點。
1. 設置默認語言環境
項目文件LocalizationDemo.csproj添加<UICulture>en-US</UICulture>,程序集文件AssemblyInfo.cs中把[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]注釋去掉。
2. 在xaml文件中添加Uid
打開Visual Studio 命令提示(2010)如下圖,進入項目文件.csproj所在目錄,運行命令:msbuild /t:updateuid LocalizationDemo.csproj;若要驗證是否缺少或重復Uid,運行命令:msbuild /t:checkuid LocalizationDemo.csproj。
3. 通過Localization.Attributes,設置本地化的特性(屬性)
如:<DataGridTextColumn x:Uid="DataGridTextColumn_1" Header="No." Width="auto" Binding="{Binding No}" Localization.Attributes="$Content(Ignore) Width(Ignore) Header(None Readable Modifiable)"/>,這里Width(Ignore)設置Width屬性不實現本地化,Header(None Readable Modifiable)設置Header屬性可讀可寫需要實現本地化,更多本地化特性細節請參見本地化特性和注釋。
4. 編譯項目,生成語言資源文件
生成的LocalizationDemo.resources.dll會在\bin\Debug\en-US\目錄下。
5. 將語言資源文件輸出存儲為 .csv 文件,以作進一步分析
將 LocBaml.exe(LocBaml 工具是一種尚未投產使用的應用程序。它顯示為一種示例,該示例使用某些本地化 API 並演示如何編寫本地化工具。點擊下載LocBaml)復制到應用程序的 bin\debug 文件夾,即創建主應用程序集的位置。打開Visual Studio 命令提示(2010),進入bin\debug目錄,運行命令:LocBaml.exe /parse en-US/LocalizationDemo.resources.dll /out:en-US.csv
6. 翻譯可本地化內容
注意此步應當使用兼容unicode的文本編輯器進行編輯翻譯。或者中文系統下將 .csv 文件在 Microsoft Excel 中進行查看,對最后一列(值)進行翻譯更改,另存為zh-CN.csv。
此時會彈出如下消息提示框,選擇"是(Y)",
然后用記事本打開zh-CN.csv文件,選擇"另存為",如下圖(初始編碼為"ANSI")選擇"UTF-8"保存。
7. 使用 LocBaml 生成新增語言的.resources.dll資源文件
運行下面命令根據翻譯的zh-CN.csv生成中文資源文件LocalizationDemo.resources.dll,可以在E:\目錄下找到,將生成的LocalizationDemo.resources.dll復制到項目\bin\Debug\zh-CN\目錄下即可。
LocBaml.exe /generate en-US/LocalizationDemo.resources.dll /trans:zh-CN.csv /out:E:\ /cul:zh-CN
8. 測試新增語言資源文件
- 更改操作系統的地區設置(“開始” | 控制面板 |“區域和語言選項”)。
- 代碼中控制
1 //中文為: "zh-CN" 2 CultureInfo ci = new CultureInfo("en-US"); 3 Thread.CurrentThread.CurrentCulture = ci; 4 Thread.CurrentThread.CurrentUICulture = ci;
二、使用資源字典文件
這種方式的實現相對較為豐富,即可實現新增支持語言無需重新編譯,也可實現程序運行中切換語言(參見本文實現動態切換程序顯示語言),以下是常用實現方式。
1. 創建資源字典StringResource.xaml,包含需要支持多國語言的字符串
1 <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 2 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 3 xmlns:sys="clr-namespace:System;assembly=mscorlib"> 4 <sys:String x:Key="WinTitle">MainWindow</sys:String> 5 <sys:String x:Key="TblText">Support multi language demo.</sys:String> 6 <sys:String x:Key="BtnOK">OK</sys:String> 7 <sys:String x:Key="HdNo">No.</sys:String> 8 <sys:String x:Key="HdName">Name</sys:String> 9 <sys:String x:Key="HdGender">Gender</sys:String> 10 <sys:String x:Key="HdDept">Dept</sys:String> 11 <sys:String x:Key="HdEmail">Email</sys:String> 12 <sys:String x:Key="HdTel">Tel</sys:String> 13 <sys:String x:Key="MsgShowTime">Now time is:{0}</sys:String> 14 </ResourceDictionary>
2. 在app.xaml中使用MergedDictionary
1 <Application x:Class="LocalizationDemo.App" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 StartupUri="MainWindow.xaml" Exit="Application_Exit"> 5 <Application.Resources> 6 <ResourceDictionary> 7 <ResourceDictionary.MergedDictionaries> 8 <ResourceDictionary Source="Resources\StringResource.xaml" /> 9 <ResourceDictionary Source="Resources\StringResource.zh-CN.xaml" /> 10 </ResourceDictionary.MergedDictionaries> 11 </ResourceDictionary> 12 </Application.Resources> 13 </Application>
3. 在程序中使用資源字典中的字符串
- .xaml文件,Text="{StaticResource TblText}"
- .cs文件,string s = Application.Current.FindResource("MsgShowTime").ToString();
4. 復制StringResource.xaml命名為StringResource.zh-CN.xaml,key不變,value翻譯為中文
1 <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 2 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 3 xmlns:sys="clr-namespace:System;assembly=mscorlib"> 4 <sys:String x:Key="WinTitle">主窗體</sys:String> 5 <sys:String x:Key="TblText">支持多國語言示例。</sys:String> 6 <sys:String x:Key="BtnOK">確定</sys:String> 7 <sys:String x:Key="HdNo">員工號</sys:String> 8 <sys:String x:Key="HdName">姓名</sys:String> 9 <sys:String x:Key="HdGender">性別</sys:String> 10 <sys:String x:Key="HdDept">部門</sys:String> 11 <sys:String x:Key="HdEmail">郵箱</sys:String> 12 <sys:String x:Key="HdTel">電話</sys:String> 13 <sys:String x:Key="MsgShowTime">現在時間是:{0}</sys:String> 14 </ResourceDictionary>
5. 在程序啟動時根據當前區域加載對應的資源字典文件
1 List<ResourceDictionary> dictionaryList = new List<ResourceDictionary>(); 2 foreach (ResourceDictionary dictionary in Application.Current.Resources.MergedDictionaries) 3 { 4 dictionaryList.Add(dictionary); 5 } 6 string requestedCulture = string.Format(@"Resources\StringResource.{0}.xaml", Culture); 7 ResourceDictionary resourceDictionary = dictionaryList.FirstOrDefault(d => d.Source.OriginalString.Equals(requestedCulture)); 8 if (resourceDictionary == null) 9 { 10 requestedCulture = @"Resources\StringResource.xaml"; 11 resourceDictionary = dictionaryList.FirstOrDefault(d => d.Source.OriginalString.Equals(requestedCulture)); 12 } 13 if (resourceDictionary != null) 14 { 15 Application.Current.Resources.MergedDictionaries.Remove(resourceDictionary); 16 Application.Current.Resources.MergedDictionaries.Add(resourceDictionary); 17 }
6. 測試新增語言資源文件同"使用LocBaml工具"中step8
三、使用.resx資源文件
這種方式和Winform支持多國語言保持一致,相對較容易實現,新增支持語言需要重新編譯程序,所有的.resx文件必須放在同一個主程序集中。
1. 添加字符串資源
在資源文件Resources.resx中添加字符串資源,並將訪問修飾符設置為Public。
2. 在程序中使用資源文件
.xaml文件,引入名稱空間:xmlns:props="clr-namespace:LocalizationDemo.Properties";使用方式:Text="{x:Static props:Resources.TblText}"
.cs文件,使用方式:string s = Properties.Resources.MsgShowTime;
3. 新增語言資源文件
以新增簡體中文為例,復制資源文件Resources.resx,重命名為Resources.zh-CN.resx,將值翻譯為中文保存。
4. 設置程序運行語言環境
1 LocalizationDemo.Properties.Resources.Culture = new CultureInfo("zh-CN");
四、實現動態切換程序顯示語言
以上三種支持多國語言的解決方案都是在程序運行過程中不能變更語言的,要實現程序運行中動態切換語言就需要在UI設計使用DynamicResource,其中一種簡單的實現是通過DynamicResource引用資源字典文件鍵值。
使用DynamicResource
具體實現方法和本文使用資源字典文件中步驟基本一致,只需將UI相關的.xaml文件中引用資源字典文件鍵值的StaticicResource改為DynamicResource,如下:
1 <TextBlock Height="23" TextWrapping="Wrap" Name="txtTips" Text="{StaticicResource TblText}" /> 2 <!--StaticicResource改成DynamicResource,如下--> 3 <TextBlock Height="23" TextWrapping="Wrap" Name="txtTips" Text="{DynamicResource TblText}" />
非Visual Controls實現動態切換語言
需要注意的是,在WPF DataGrid中的DataGridColumn等控件不是Visual Controls,它們的Binding屬性可以進行綁定,除此之外必須是Static靜態的,也就是我們可以通過創建靜態的樣式資源,在這些樣式資源中包含動態內容,然后在像DataGridColumn這樣的控件中引用靜態的樣式資源就可以了,實現如下:
- 靜態樣式資源包含動態內容
1 <Window.Resources> 2 <Style x:Key="HeaderNoStyle" TargetType="{x:Type DataGridColumnHeader}"> 3 <Setter Property="Content" Value="{DynamicResource HdNo}" /> 4 </Window.Resources>
- DataGridColumn引用靜態的樣式資源
1 <DataGridTextColumn HeaderStyle="{StaticResource HeaderNoStyle}" Width="auto" Binding="{Binding No}"/>
附:實現MessageBox支持多語言
另外,和其他元素不同的是,MessageBox的確定(OK),是(Yes),否(NO)等按鈕是直接調用系統Win32 API,MessageBox按鈕當前顯示哪種語言文本是由Windows操作系統安裝的默認語言決定,而與其他無關。為了解決這一問題需要實現設置自定義系統MessageBox按鈕文本,MessageBoxManager能夠實現這一需求,更多內容請參見Localizing SystemMessageBox一文。另外一種解決辦法就是自定義替代MessageBox功能的Windows窗體。
如何使用MessageBoxManager
//設置OK按鈕顯示文本 MessageBoxManager.OK = "確定啊,親"; //注冊MessageBoxManager MessageBoxManager.Register(); //正常使用MessageBox MessageBox.Show("你懂的..."); //取消注冊MessageBoxManager MessageBoxManager.Unregister();
效果如下圖:
