概念
應用程序具備多語言支持,是實現全球化(Globalization)和本地化(Localization)最重要的功能。
關於全球化和本地化的概念、設計原則、基本流程可參考微軟文檔 https://docs.microsoft.com/zh-cn/dotnet/framework/wpf/advanced/wpf-globalization-and-localization-overview
目前有多種方案可供選擇:
• 使用resx資源文件
• 使用xaml資源文件
• 使用markup擴展
本文介紹學習使用resx文件的一些經驗和心得。
管理模型
resx資源文件通常是嵌入應用的數據,隨應用程序一起發佈,如果修改資源文件中的數據,需要重新編譯。
.NET對多種語言使用“中心–衞星”模式管理多個區域的資源,處於“中心”位置的稱為默認資源,處於“衞星”位置的稱為特定區域資源。
例如,項目中有個資源文件Resources.resx,這個就是默認資源文件,Resources.en-US.resx、Resources.fr-FR.resx、Resources.zh-CN.resx等就是特定區域的資源文件。(可使用ResXManager擴展工具進行生成資源文件)
在VS中編譯生成應用程序時,編譯器會在可執行程序的目錄中生成對應特定區域的子目錄,子目錄中存放區域對應資源的dll文件。
.NET使用ResourcesManager對象管理這些資源文件, ResourceManager從Thread.CurrentUICulture屬性中獲得當前的區域,然後根據該屬性從特定區域中進行查找,如果找到了對應的區域,則使用該區域的資源內容,如果未在特定區域中找到內容,則使用默認的資源。
下面舉個簡單的例子説明。
代碼與數據
新建一個WPF(.NET Framework)桌面應用TestApp,
創建的項目中,VS已經預先建好了一些文件,打開Properties目錄下的Resources.resx文件,在其中添加一些字符串資源,並且將訪問修飾符改為Public。
然後在Properties目錄下新建一個文件名為Resources.en-US.resx的資源文件,在其中添加字符串資源。
修改Properties目錄下的Settings.settings文件,增加當前App語言的設置。
編輯MainWindow.xaml前端文件。首先添加名稱空間,並在Grid中添加兩個按鈕控件。
xmlns:prop="clr-namespace:TestApp.Properties"
...
<Button Cnotallow="{x:Static prop:Resources.btnChnText}" Horiznotallow="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="75" Click="Button_chn_Click"/>
<Button Cnotallow="{x:Static prop:Resources.btnEngText}" Horiznotallow="Left" Margin="100,10,0,0" VerticalAlignment="Top" Width="75" Click="Button_eng_Click"/>
編輯MainWindow.xaml.cs後台文件
1、首先添加引用
using System.Globalization;
2、然後在MainWindow中添加兩個內部成員變量
string _currentCulture = Properties.Settings.Default.Culture;
ResourceManager _rm = new ResourceManager("TestApp.Properties.Resources",
typeof(MainWindow).Assembly);
3、修改MainWindow的構造函數,在InitializeComponent之前修改當前的Culture。
Thread.CurrentThread.CurrentUICulture
= CultureInfo.CreateSpecificCulture(_currentCulture);
4、增加兩個按鈕的響應函數
private void Button_chn_Click(object sender, RoutedEventArgs e)
{
if (MessageBox.Show(_rm.GetString("strChnQuestion"), "",
MessageBoxButton.YesNo,
MessageBoxImage.Question)
== MessageBoxResult.Yes)
{
Properties.Settings.Default.Culture = "zh-CN";
Properties.Settings.Default.Save();
}
}
private void Button_eng_Click(object sender, RoutedEventArgs e)
if (MessageBox.Show(_rm.GetString("strEngQuestion"), "",
MessageBoxButton.YesNo,
MessageBoxImage.Question)
== MessageBoxResult.Yes)
{
Properties.Settings.Default.Culture = "en-US";
Properties.Settings.Default.Save();
}
}
運行效果
程序運行後缺省顯示中文,點擊按鈕顯示的也是中文的提示。
選擇某個語言後,重新啓動程序,所有的界面和提示都切換成了目標語言。
後續改進
這種方法的缺陷在於界面的文字採用靜態渲染,運行過程中不會因為語言的切換而改變現實。
如果不考慮程序的執行效率,可以利用Markup的擴展,將界面語言的切換改為動態方式,這樣可以在運行中進行語言的切換,而不必重新啓動程序。