在Visual Studio .NET裏面,本地化資源,比如字符串、圖片之類的,都是跟culture(語言文化)有關,這些東西都是存儲在單獨的文件中並且根據相應的culture設定進行加載,如果要了解怎樣加載你自己的本地化資源,那就需要了解資源文件的組織結構關係:
1. .Net在加載資源文件的時候,是按照自下而上的方式。Framework裏面,父類對應english,是唯一的一種沒有自身資源文件的,其實也並不是沒有,而是存在main assembly裏面。
2. 在父類之下,可以有多種多樣的culture的資源,我們說的culture是指語言文化並不是指windows控制面板中的區域,比如,法國(French簡寫爲“fr”)就是一個culture。english簡寫成“en”也是一個culture。
3. 在這些culture之下,又有一些特定區域的culture,這些特定區域的culture,它有兩點屬性,不僅包含語言文化,還加上區域特色,就好比中國有中國的文化,而福建還有它自身的區域性文化。
在一個程序試圖加載一個資源的時候,好比一個字符串,並且還沒有找到,它就會沿着上面所說的層次結構一層一層的往上爬,直到找到爲止。
在進行本地話的過程中,最好的方法是建立相對通用的資源文件,也就是上文中第2條中的而不是第3條中,就好比我們在漢化的過程中,一般漢化成普通話,而不是漢化成福建話,或者是臺灣話。也就是越通用越好,假設你有一個French Belgian ("fr-BE")的資源文件,而且它的直接上級就立馬到了最高級english,那麼當你的區域設置改變成French Canadian,系統降會尋找對應的"fr-CA"資源,而此時已經無法找到,就會選用處於main assambly中的資源,也就是英文。下圖顯示的就是你不想看到的場景。
如果你願意,你可以爲"fr" culture放置儘可能多的資源文件,這樣French Canadian的用戶雖然無法看見"fr-BE"的資源文件,但是它至少可以獲得French的資源文件,以下圖片就是推薦的方式。
以上我們說的資源文件,還有另一種比較高雅的叫法,叫Satellite Assemblies,翻譯成中文可以叫做衛星程序集。需要注意的是這些資源程序集的強名必須跟主程序集的相一致,如果它們不匹配的話,也就無法加載了。
2.2. 本地化WinForm
VS提供了較豐富的本地化方法,通過VS開發環境實現本地化有兩種方法:
第一種是用系統工具爲各種UI元素生成資源文件,然後把這些資源文件編譯到衛星程序集中去;
第二種方法是添加一個資源文件模版然後使用內置的XML Designer進行編輯;第二種方法的好處是還可以本地化messagebox中出現的文本。
下面我們用一個工程簡單演示一下這兩種本地化步驟:
2.2.1. 用VS生成資源文件
1. 創建一個工程,我的工程名叫:WindowsApplication2;
2. 設置窗體的Localizable爲true(確定是否將爲此對象生成可本地化的代碼)
此時Language屬性已經被設置成了“(Default)”;
3. 往窗體上拉一個Text控件,還是老規矩,設置它的值爲“Hello World”;
4. 設置窗體的Language屬性爲“German (Germany)”;
5. 重新設置Text控件的值爲“Hallo Welt”;
6. 設置窗體的Language屬性爲“French (France)”;控件值會自動改爲Hello World
7. 再設置Text控件的值爲“Bonjour le Monde”;
8. 保存並編譯工程文件。
這時VS爲我們生成的文件如上圖所示。
9. 按F5執行程序。
生成的文件如上圖所示,兩個子目錄下分別包含資源程序集。如“de-DE”目錄下包含的“漢化示例.resources.dll”。
10. 你已經擁有了一個擁有德文和法文的應用程序了,不過具體顯示什麼就取決於你操作系統的區域配置了。當然你也可以在程序中指定要顯示的語言。下面將通過代碼的方式詳細說明。
在Program.cs程序入口Main中加入如下代碼
這是需要的命名空間:
// C#
using System.Globalization;
using System.Threading;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace 漢化示例
{
static class Program
{
/// <summary>
/// 應用程序的主入口點。
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
System.Threading.Thread.CurrentThread.CurrentUICulture=new System.Globalization.CultureInfo("fr-FR");
Application.Run(new Form1());
}
}
}
只加了下面這句
System.Threading.Thread.CurrentThread.CurrentUICulture=new System.Globalization.CultureInfo("fr-FR");
經過以上處理,我們現在看到的就是法語了。不過這種硬編碼的方式並不推薦,這種方式不能通過用戶喜好設定或者是程序設定來更改界面。
2.2.2. 添加資源模版並編輯(右鍵工程添加新建項)
添加Resource File類型文件,這裏命名爲:WinFormStrings,然後編輯文件如下:
法文和德文的添加方法類似,不過需要變動一下文件名
大致修改的情況如下所示:
resource file name |
name |
Value |
Comment |
WinFormStrings.de.resx |
strMessage |
Hallo Welt |
|
WinFormStrings.fr-FR.resx |
strMessage |
Bonjour le Monde |
|
資源文件是添加好了,下面講述如何訪問這些資源文件:
1. 添加命名空間:using System.Resources;
2. 爲主窗口添加一個button,不過此時需要注意的是把窗體的Localizable屬性設置爲False,否則將無法添加。(我這裏懶得用新項目,還是前文提到的那個項目)
3. 爲這個button的Click事件編寫代碼如下,需要注意的是ResourceManager的參數。且默認的ResourceManager是大小寫敏感的,雖然也可以設置忽略大小寫,不會有造成性能上的損失。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace 漢化示例
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
System.Resources.ResourceManager localResxManager = new System.Resources.ResourceManager("漢化示例.WinFormStrings",typeof(Form1).Assembly);
MessageBox.Show(localResxManager.GetString("strMessage"));
}
}
}
4. 編譯並執行即可顯示效果。
這時如果要更改顯示語言的話,還是使用
Thread.CurrentThread.CurrentUICulture = new CultureInfo("fr-FR");
這種方式進行更改。
private void button2_Click(object sender, EventArgs e)
{
System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("fr-FR");
}
3. 本地化DevExprss
通常有兩種做法,其一是使用Localizer,需要編寫一點代碼,且這種方法的靈活性不夠,只能本地化爲一種語言。
另一種方法是使用前文說到的衛星程序集的方式,這種方式無需編寫任何代碼,只需本地化資源文件之後,編譯成資源程序集,並把這些程序集放在程序的啓動目錄下即可,並且可以放置多種語言的配件。
DevExpress公司已經爲我們準備好了很多東西,官方網站上已經提供了較多語言的資源文件的下載,最新版本的Dev控件,截至2007-3-25該控件的本版是7.1.1,中文的資源文件已經包含如下幾個:
剩下的工作就是按各自的需要自己漢化了。
3.1. 使用Localizer(Archie覺得此方法不錯)
下面我們以一個簡單的例子描述XtraGrid中的比較符的本地化。代碼如下所示:
private void Form1_Load(object sender, System.EventArgs e) {
GridLocalizer.Active = new MyGridLocalizer();
}
public class MyGridLocalizer : GridLocalizer {
public override string GetLocalizedString(GridStringId id) {
string ret = "";
switch(id) {
// ...
case GridStringId.CustomFilterDialogConditionEQU : return "=";
case GridStringId.CustomFilterDialogConditionNEQ : return "<>";
case GridStringId.CustomFilterDialogConditionGT : return ">";
case GridStringId.CustomFilterDialogConditionGTE : return ">=";
case GridStringId.CustomFilterDialogConditionLT : return "<";
case GridStringId.CustomFilterDialogConditionLTE : return "<=";
// ...
default:
ret = "";
break;
}
return ret;
}
}
運行程序,我們可以看到如下的效果:
private void Form1_Load(object sender, EventArgs e)
{
DevExpress.XtraGrid.Localization.GridLocalizer.Active = new MyGridLocalizer();
}
public class MyGridLocalizer : GridLocalizer
{
public override string GetLocalizedString(GridStringId id)
{
string ret = "";
switch (id)
{
// ...
case GridStringId.GridGroupPanelText:
return "拖動到此列";
default:
ret = "";
break;
}
return ret;
}
}
3.2. 創建衛星程序集
爲了本地化窗體資源,.Net Framework已經爲我們提供了相應的工具——WinRes.exe。要了解它的具體使用方法,你查看相應的MSDN相關文檔。
我們先以一個Library來描述它的本地化步驟,就用XtraEditors吧,如果你有Dev的源代碼,你會發現Dev已經把各種資源放在了一個叫做LocalizationRes.resx的資源文件裏面。
1. 把LocalizationRes.resx文件拷貝一份到你自己的某個目錄下,重命名爲你需要的culture,比如要本地化爲德文的話,就更名爲"LocalizationRes.de.resx",當然我們需要的是中文,於是把它更名爲LocalizationRes.zh-CHS.resx。窗體或用戶控件也都用一個resx文件,同樣可以使用這種方式漢化。
2. 現在我們可以藉助VS開發環境對這個文件進行漢化了,如下圖所示:
3. 現在我們需要藉助Resgen.exe把這個文件轉化爲一個resources文件。
resgen LocalizationRes.zh-CHS.resx LocalizationRes.zh-CHS.resources。
4. 把這個資源文件打包到衛星配件中去,仍然使用VS提供的一個小工具——Al.exe。下面的命令行就是把LocalizationRes.zh-CHS.resources文件打包成衛星配件了。
al /out:DevExpress.XtraEditors.Resources.Dll /v:0.0.0.0 /culture: zh-CHS /embed:LocalizationRes.zh-CHS.resources,DevExpress.XtraEditors.LocalizationRes.zh-CHS.resources /keyfile:strongkey.snk。
上面各種參數一目瞭然吧,就不贅述了。需要注意的是keyfile對應的strongkey必須跟DevExpress相應組件指定的strongkey一致。通過al命令也可以把多個resources文件打包成一個單一的配件。如下面這條命令把多種資源打包成配件。
%al% /out:../zh-CHS/DevExpress.XtraPrinting.%VER_DLL%.Resources.dll /v:%VER_PSYS% /culture:zh-CHS /embed:ComponentEditorForm.zh-CHS.resources,DevExpress.XtraPrinting.ComponentEditorForm.zh-CHS.resources
/embed:LocalizationRes.zh-CHS.resources,LocalizationRes.zh-CHS.resources /embed:HeaderFooterForm.zh-CHS.resources,DevExpress.XtraPrinting.Native.WinControls.HeaderFooterForm.zh-CHS.resources /embed:WatermarkEditorForm.zh-CHS.resources,DevExpress.XtraPrinting.Native.WinControls.WatermarkEditorForm.zh-CHS.resources
/keyfile:%KEYFILE%
通過這裏大家可以看出,已經把幾個窗體的資源也打進來了,不過需要注意的是/embed裏的第二個參數要加上窗體或控件所在的命名空間。
現在衛星配件已經製作出來了,現在需要把它配置到一個地方以便Framework能夠找到它。通常有兩種方法,一種是直接把它放到GAC中,方便省事;另一種是把它們放到具體的程序目錄下。
要放到GAC裏面,簡單的方法就是直接把衛星配件拖放到“Windows/assembly”目錄下,如果非要顯得自己專業一點的話,也可以使用Microsoft提供的工具gacutil,使用如下命令:
gacutil /i:LocalizerRes.zh-CHS.resources.dll
如果不放到GAC中,那就放在你的程序的所在目錄下,放置的時候也有一點學問,下面的這個圖顯示的是邏輯目錄結構:
其實很簡單,看另一個圖可能直觀點:
以下的代碼用於設置所選用的資源:
static void Main()
{
System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("de");
Application.Run(new Form1());
}
還是這麼簡單,事實上只要把資源配件放到目錄下即可,無需進行硬編碼即可完成本地化工作,那是因爲我們一般默認的CurrentUICulture就是zh-CHS。
目前爲止我們就完成了需要做的大部分工作了,剩下的就是大家想到什麼然後給我提提意見或建議,我再進行改進,初次執筆,感覺舉筆維艱,寫的挺生硬的,將就着看吧,呵呵,,