在PictureStudio中,我需要实现多国语言的界面切换,而且切换各种语言版本的时候希望程序是动态的加载语言,不希望切换语言后重新启动程序。
实现这样的功能可以有很愚蠢的方法,比如说你可以在程序中为界面上的所有国家的文字信息,在代码中进行赋值,你可以想像这样的做法是可以的,但绝对是愚蠢的,代码不应该写得这么丑陋。如果需要实现10个不同语言的版本,那你的代码中每一个涉及到界面文字的控件都要有至少10行代码,而且维护的时候,需要到代码中去修改不同语言显示,这显然是很糟糕的。
把语言文字作为资源,而不是放在代码中。在.NET开发中,VS2005为每一个窗口都自动创建一个与窗口同名的资源文件,后缀名为.resx(如下图)
资源文件中可以存放字符串,对象,2进制资源,如下图所示:
我们现在可以为每个窗口创建对应不同语言版本的资源文件,将文字字符作为资源存放在资源文件(resx文件其实是XML格式的文件,你可以用IE打开浏览其内容)而不是使用默认的资源文件。比如我们要实现简体中文,繁体中文,英文三种不同类型文字信息的切换。我们就要为每个窗口创建3个对应相应语言的资源文件。如下图,我们在工程中为主窗口新建一个资源文件
需要注意的是,窗口资源文件的命名是有严格规定的。比如主窗口类是MainForm,创建对应该窗口简体中文版本的资源文件的名字前面必须就是该窗口的类名(MainForm)然后一个.后面接着是语言类型的标志之后又是一个.最后是resx后缀名。语言类型的标志也是有预先规定的,比如简体中文必须是zh-CHS,具体的相关设定你需要查看MSDN的说明:
对于一个窗口,我们添加了其相应的几个语言版本的resx资源文件以后,就应该在资源文件中添加不同语言版的字符串资源。需要注意的是,不同语言版本的资源文件中,相应各个语言的版本的字符串的名字必须是相同的!见下面的截图,两个资源文件中的不同版本的字符串资源的名字是相同的。
资源文件准备好以后,我们还需要将窗口的Localizable属性设置为True,然后就做好了所有的工作,下面添加代码来实现各国语言文字的切换。在菜单英文选项单击事件函数中添加下面的代码
private void languageMenuEnglish_Click(object sender, EventArgs e)
{
Thread.CurrentThread.CurrentUICulture = new CultureInfo("en");
UpDataMainFormUILanguage();
}
//根据当前的语言区域,更新主窗口的语言信息
private void UpDataMainFormUILanguage()
{
ResourceManager rm = new ResourceManager(typeof(MainForm));
UpDataMainFormMenuLanguage(rm);
UpDataMainFormToolBarLanguage(rm);
}
//根据当前的语言区域,更新主窗口菜单的语言
private void UpDataMainFormMenuLanguage(ResourceManager rm)
{
fileMenu.Text = rm.GetString("fileMenu");
fileMenuCreate.Text = rm.GetString("fileMenuCreate");
fileMenuOpen.Text = rm.GetString("fileMenuOpen");
fileMenuSaveProject.Text = rm.GetString("fileMenuSaveProject");
fileMenuSaveAs.Text = rm.GetString("fileMenuSaveAs");
fileMenuCloseProject.Text = rm.GetString("fileMenuCloseProject");
fileMenuExit.Text = rm.GetString("fileMenuExit");
operationMenu.Text = rm.GetString("operationMenu");
operationMenuUndo.Text = rm.GetString("operationMenuUndo");
operationMenuRedo.Text = rm.GetString("operationMenuRedo");
operationMenuSelectAll.Text = rm.GetString("operationMenuSelectAll");
operationMenuSelectInvert.Text = rm.GetString("operationMenuSelectInvert");
operationMenuDeleteSelected.Text = rm.GetString("operationMenuDeleteSelected");
operationMenuCut.Text = rm.GetString("operationMenuCut");
operationMenuCopy.Text = rm.GetString("operationMenuCopy");
operationMenuPaste.Text = rm.GetString("operationMenuPaste");
displayMenu.Text = rm.GetString("displayMenu");
displayMenuRuler.Text = rm.GetString("displayMenuRuler");
displayMenuToolBox.Text = rm.GetString("displayMenuToolBox");
displayMenuImageListForm.Text = rm.GetString("displayMenuImageListForm");
displayMenuLayerListForm.Text = rm.GetString("displayMenuLayerListForm");
displayMenuHistoricalCommandForm.Text = rm.GetString("displayMenuHistoricalCommandForm");
displayMenuZoomIn.Text = rm.GetString("displayMenuZoomIn");
displayMenuZoomOut.Text = rm.GetString("displayMenuZoomOut");
imageMenu.Text = rm.GetString("imageMenu");
imageMenuAdjustSize.Text = rm.GetString("imageMenuAdjustSize");
imageMenuHorizontalFlip.Text = rm.GetString("imageMenuHorizontalFlip");
imageVerticalFlip.Text = rm.GetString("imageVerticalFlip");
imageMenuRotate90.Text = rm.GetString("imageMenuRotate90");
imageMenuRotate180.Text = rm.GetString("imageMenuRotate180");
layerMenu.Text = rm.GetString("layerMenu");
layerMenuCreateLayer.Text = rm.GetString("layerMenuCreateLayer");
layerMenuDeleteLayer.Text = rm.GetString("layerMenuDeleteLayer");
layerMenuLayerCombination.Text = rm.GetString("layerMenuLayerCombination");
filterMenu.Text = rm.GetString("filterMenu");
filterMenuGrayEffect.Text = rm.GetString("filterMenuGrayEffect");
filterMenuInvertColorEffect.Text = rm.GetString("filterMenuInvertColorEffect");
filterMenuParticleEffect.Text = rm.GetString("filterMenuParticleEffect");
languageMenu.Text = rm.GetString("languageMenu");
languageMenuSimlpeChinese.Text = rm.GetString("languageMenuSimlpeChinese");
languageMenuTaiWanChinese.Text = rm.GetString("languageMenuTaiWanChinese");
languageMenuEnglish.Text = rm.GetString("languageMenuEnglish");
helpMenu.Text = rm.GetString("helpMenu");
helpMenuHelp.Text = rm.GetString("helpMenuHelp");
helpMenuAbout.Text = rm.GetString("helpMenuAbout");
return;
}
//根据当前的语言区域,更新主窗口工具栏的语言
private void UpDataMainFormToolBarLanguage(ResourceManager rm)
{
fileButtonCreate.ToolTipText = rm.GetString("fileButtonCreate");
fileButtonOpen.ToolTipText = rm.GetString("fileButtonOpen");
fileButtonSave.ToolTipText = rm.GetString("fileButtonSave");
operationButtonCut.ToolTipText = rm.GetString("operationButtonCut");
operationButtonCopy.ToolTipText = rm.GetString("operationButtonCopy");
operationButtonPaste.ToolTipText = rm.GetString("operationButtonPaste");
operationButtonUndo.ToolTipText = rm.GetString("operationButtonUndo");
operationButtonRedo.ToolTipText = rm.GetString("operationButtonRedo");
displayButtonZoomIn.ToolTipText = rm.GetString("displayButtonZoomIn");
displayButtonZoomOut.ToolTipText = rm.GetString("displayButtonZoomOut");
toolBoxPopButton.Text = rm.GetString("toolBoxPopButton");
return;
}
ResourceManager是操作资源的类,使用这个类的对象来操作字符串资源。 Thread.CurrentThread.CurrentUICulture 的属性设置为英文以后,ResourceManager对象rm的调用rm.GetString会调用当前语言对应的字符资源。GetString根据字符串资源名字,找到相应的语言版本的资源,所以之前我们不同版本的字符串资源的名字必须是相同的。
当切换到简体中文时,所加的代码也类似
private void languageMenuSimlpeChinese_Click(object sender, EventArgs e)
{
Thread.CurrentThread.CurrentUICulture = new CultureInfo("zh-CHS");
UpDataMainFormUILanguage();
}
以上的处理方法,在有众多语言版本需要实现时,代码量都差不多,添加一种语言版本,只要添加相应的资源文件,代码中只要加上两句,1设置程序当前语言区域属性,2调用读取资源的函数。当发现语言有需要更正的地方时,可以相当方便在资源文件中修改,而不用动源代码。切换文字区域后,程序也不用重新启动,Paint.Net程序切换后需要重新启动,我不知道他们的具体做法是怎样的。但我使用的方法避免了重新启动程序,应该更好些吧。
切换为中文的情况:
切换为英文的情况: