WPF: 本地化(Localization) 實現 WPF: 本地化(Localization) 實現
WPF: 本地化(Localization) 實現
本文將討論在WPF中一種較為方便的本地化方法。
由於在專案中要實現本地化,所以我在網上查詢相關的解決方案。通過一系列調研,發現實現本地化的方法主要有以下三種:
- 通過編譯專案以設定 x:Uid 並使用 LocBaml 工具實現;
- 通過 DynamicResource 實現;
- 通過 Resx 檔案實現
其中第一種是官方介紹的方法,考慮到實現步驟略為複雜,所以直接忽略;
第二種方式的實現,主要是在程式中新增 Resource Dictionary 型別的檔案,並在其中放入本地化資源字串;在 XAML 程式碼中,直接使用 {DynamicResource XXXX} 來實現;這種方法比較方便,不過它也有兩個缺點:
- 在 XAML 中,引用 DynamicResource 的屬性必須為依賴屬性,否則會出錯;
- 在 C# 程式碼中引用稍微有點麻煩,需要從 Resource Dictionary 中獲取並轉化為字串
其中第一點可以說是致命缺點,我曾在專案中添加了一個第三方控制元件,其 Header 屬性並不是依賴屬性,所以不能使用這種方式;不是依賴屬性,當然,也就更不能使用繫結(Binding)來設定了。
所以,之後嘗試了第三種方式——使用 resx 檔案,事實上,這是一種比較傳統的、且普遍的方式,說它傳統,是因為在 WinForm 中就可以這麼做;說它普遍,是因為在 ASP.net MVC 中也可以這麼做;並且,在 UWP 中的實現方式也與此有點類似。可以說,基本上基於 .NET 的各個平臺都是以這種或類似這種方式來實現本地化的。並且,事件證明,這種方式的確是非常合適的,也很好用,在 XAML 程式碼和 C# 程式碼中均可以非常方便的使用。
使用 ResX 檔案實現
它的操作步驟大概如下:
1. 建立一個 WPF 專案;
2. 在主視窗中新增幾個需要本地化其內容的控制元件,如 TextBlock、Button等;
3. 展示此專案的 Properties 資料夾,這裡已經有一個預設的 Resources.resx,在其中新增本地化字串;
4. 將其複製,並貼上到當前位置,將新檔案改名為 Resources.en-US.resx,並修改其中的本地化字串為對應的語言值;
說明:這裡我們添加了對英語語言的本地化,至於支援哪些語言的本地化,可以參考這篇文章 Supported languages,關於語言匹配可參考這篇文章 Manage language and region
5. 將上述兩個 resx 檔案的 Access Modifier 修改為 Public,預設值是 Internal;如下圖:
接下來就是如何使用了:
6. 在 Xaml 中新增名稱空間引用:
xmlns:loc="clr-namespace:WpfLocalizationTest.Properties"
7. 使用 {x:Static} 標記引用資源,如下:
<TextBlock Text="{x:Static loc:Resources.Main_Menu_Home}" />
8. 如果需要在程式碼中引用,也非常簡單:
var homePage = Properties.Resources.Main_Menu_Home;
經測試,這種方式也支援 IntelliSense(智慧提示),如下圖:
如果你沒看到智慧提示,可以先編譯專案。
此時,有兩種方式可以測試本地化效果,第一種方式是在控制面板中改變作業系統的語言,第二種方式是通過程式碼改變 CurrentUICulture;這裡我們使用後者,在 App.xaml.cs 中新增如下程式碼:
protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("en-US"); }
執行後就可以看到測試結果了。
在大型專案中使用
上面是在 Demo 中展示如何本地化應用,那麼在大型專案中是如何來應用這種方式呢?以下簡單介紹一下,可以供參考:
1. 在解決方案中建立一個類庫專案(或在已有專案中進行後續操作),此專案的用途主要是作資源用;
2. 在其中建立 Localization 資料夾,在這個資料夾下可以再建立針對各個模組的子資料夾,然後在此建立 resx 檔案、新增本地化字串並複製。檔案結構如下:
3. 要在主程式中使用,方式和我們在 Demo 中提到的是一樣的。首先在主程式專案中新增對新建立專案的引用,然後在 XAML 中新增名稱空間和相關程式碼:
xmlns:loc2="clr-namespace:App.Resources.Localization.MainModule;assembly=App.Resources"
<Button Margin="5" Padding="5" Content="{x:Static loc2:Resources.Main_New}" /> <Button Margin="5" Padding="5" Content="{x:Static loc2:Resources.Main_Open}" />
更方便的方式
如果軟體中有大量的文字需要本地化,那麼在 resx 檔案中的資源項將會非常多,這時,要在兩個甚至更多資原始檔中新增、刪除、對比、檢查專案時,將會非常困難。有沒有更方便的方法呢?這裡推薦一個 VS Extension: ResX Manager
它可以非常方便地管理當前解決方案中的 Resx 檔案以及其中的資源項,安裝後,在 VS 中工具選單中可以開啟,介面如下:
需要注意的是,如果要新增新資源項時,必須在左側僅選擇目標資原始檔。它的具體用法,不屬於本文討論的範圍,如果大家有需要了解,可以搜尋相關教程。總之,通過這個外掛,可以非常方便地建立、刪除、管理本地化文字。
總結
所以,通過本文所提出的 Resx 檔案本地化方案再加 ResXManager 擴充套件,你就可以方便地在你的 WPF專案中實現本地化了。如果您有更好的建議或意見,請留言交流。
本文將討論在WPF中一種較為方便的本地化方法。
由於在專案中要實現本地化,所以我在網上查詢相關的解決方案。通過一系列調研,發現實現本地化的方法主要有以下三種:
- 通過編譯專案以設定 x:Uid 並使用 LocBaml 工具實現;
- 通過 DynamicResource 實現;
- 通過 Resx 檔案實現
其中第一種是官方介紹的方法,考慮到實現步驟略為複雜,所以直接忽略;
第二種方式的實現,主要是在程式中新增 Resource Dictionary 型別的檔案,並在其中放入本地化資源字串;在 XAML 程式碼中,直接使用 {DynamicResource XXXX} 來實現;這種方法比較方便,不過它也有兩個缺點:
- 在 XAML 中,引用 DynamicResource 的屬性必須為依賴屬性,否則會出錯;
- 在 C# 程式碼中引用稍微有點麻煩,需要從 Resource Dictionary 中獲取並轉化為字串
其中第一點可以說是致命缺點,我曾在專案中添加了一個第三方控制元件,其 Header 屬性並不是依賴屬性,所以不能使用這種方式;不是依賴屬性,當然,也就更不能使用繫結(Binding)來設定了。
所以,之後嘗試了第三種方式——使用 resx 檔案,事實上,這是一種比較傳統的、且普遍的方式,說它傳統,是因為在 WinForm 中就可以這麼做;說它普遍,是因為在 ASP.net MVC 中也可以這麼做;並且,在 UWP 中的實現方式也與此有點類似。可以說,基本上基於 .NET 的各個平臺都是以這種或類似這種方式來實現本地化的。並且,事件證明,這種方式的確是非常合適的,也很好用,在 XAML 程式碼和 C# 程式碼中均可以非常方便的使用。
使用 ResX 檔案實現
它的操作步驟大概如下:
1. 建立一個 WPF 專案;
2. 在主視窗中新增幾個需要本地化其內容的控制元件,如 TextBlock、Button等;
3. 展示此專案的 Properties 資料夾,這裡已經有一個預設的 Resources.resx,在其中新增本地化字串;
4. 將其複製,並貼上到當前位置,將新檔案改名為 Resources.en-US.resx,並修改其中的本地化字串為對應的語言值;
說明:這裡我們添加了對英語語言的本地化,至於支援哪些語言的本地化,可以參考這篇文章 Supported languages,關於語言匹配可參考這篇文章 Manage language and region,儘管這兩篇文章是針對 UWP 的,不過原則上,對於 WPF 也是適用的;
5. 將上述兩個 resx 檔案的 Access Modifier 修改為 Public,預設值是 Internal;如下圖:
接下來就是如何使用了:
6. 在 Xaml 中新增名稱空間引用:
xmlns:loc="clr-namespace:WpfLocalizationTest.Properties"
7. 使用 {x:Static} 標記引用資源,如下:
<TextBlock Text="{x:Static loc:Resources.Main_Menu_Home}" />
8. 如果需要在程式碼中引用,也非常簡單:
var homePage = Properties.Resources.Main_Menu_Home;
經測試,這種方式也支援 IntelliSense(智慧提示),如下圖:
如果你沒看到智慧提示,可以先編譯專案。
此時,有兩種方式可以測試本地化效果,第一種方式是在控制面板中改變作業系統的語言,第二種方式是通過程式碼改變 CurrentUICulture;這裡我們使用後者,在 App.xaml.cs 中新增如下程式碼:
protected override void OnStartup(StartupEventArgs e) { base.OnStartup(e); Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("en-US"); }
執行後就可以看到測試結果了。
在大型專案中使用
上面是在 Demo 中展示如何本地化應用,那麼在大型專案中是如何來應用這種方式呢?以下簡單介紹一下,可以供參考:
1. 在解決方案中建立一個類庫專案(或在已有專案中進行後續操作),此專案的用途主要是作資源用;
2. 在其中建立 Localization 資料夾,在這個資料夾下可以再建立針對各個模組的子資料夾,然後在此建立 resx 檔案、新增本地化字串並複製。檔案結構如下:
3. 要在主程式中使用,方式和我們在 Demo 中提到的是一樣的。首先在主程式專案中新增對新建立專案的引用,然後在 XAML 中新增名稱空間和相關程式碼:
xmlns:loc2="clr-namespace:App.Resources.Localization.MainModule;assembly=App.Resources"
<Button Margin="5" Padding="5" Content="{x:Static loc2:Resources.Main_New}" /> <Button Margin="5" Padding="5" Content="{x:Static loc2:Resources.Main_Open}" />
更方便的方式
如果軟體中有大量的文字需要本地化,那麼在 resx 檔案中的資源項將會非常多,這時,要在兩個甚至更多資原始檔中新增、刪除、對比、檢查專案時,將會非常困難。有沒有更方便的方法呢?這裡推薦一個 VS Extension: ResX Manager
它可以非常方便地管理當前解決方案中的 Resx 檔案以及其中的資源項,安裝後,在 VS 中工具選單中可以開啟,介面如下:
需要注意的是,如果要新增新資源項時,必須在左側僅選擇目標資原始檔。它的具體用法,不屬於本文討論的範圍,如果大家有需要了解,可以搜尋相關教程。總之,通過這個外掛,可以非常方便地建立、刪除、管理本地化文字。
總結
所以,通過本文所提出的 Resx 檔案本地化方案再加 ResXManager 擴充套件,你就可以方便地在你的 WPF專案中實現本地化了。如果您有更好的建議或意見,請留言交流。