Winform 界面的动态翻译

来源:互联网 发布:static java 编辑:程序博客网 时间:2024/05/01 04:40

 分析

    实现多语言支持对软件的重要性不用多说了吧,对于C#来说,改变Thread.CurrentThread.CurrentUIInfo (注:CurrentUIInfo掌控的是form界面,CurrentInfo掌控的是如日期,时间格式) 可以很简单的做到界面的翻译, 但有个问题,如果是多个Form的话,要想翻译生效每次改变语言都需要重新启动软件.

    那么怎么实现动态翻译呢,一切换语言所有界面都立马更新.而不需要重启.我们考虑下动态翻译的工作流程:用户选择相应语言,发送一个消息,然后通知所有的Form,form接受到这条消息,做相应的翻译动作,ok,这可以说是典型的观察者模式.我们画uml图如下

  

实现

   1 首先创建两个资源文件,ResLanguage.Resx,ResLanguage.zh-CN.Resx,在里面直接写入我们需要翻译的文本资料.

   2 然后创建Translate.cs文件,定义好delegate和event事件,代码如下:

     

  3 创建2个form,MainForm 和Form2,MainForm里设置MenuStrip,file菜单以调用Form2,language菜单切换中英文的如图

   

   其中关键处是form在onload的时候将自身的AssignLanguage Method注册给Translate类的event.Form2也采用相同的方法处理,当切换语言的时候,Translate调用event发送消息给所有的已注册的Form,form接受到消息,即可做到同步界面更新.

    MainForm事件代码如下(这里忽略了vs自动创建的代码):

  

   在Form2随便添加一个testLabel用来示范,事件代码如下

  

运行

   打开所有Form,当切换语言版本的时候,2个form即时响应,同时更新界面,如下:

   切换为英语的界面:

  

   切换为中文的界面:

 

 

增强

    动态翻译很轻松实现了,但组件多了的时候有时候就觉得很烦, 每个form都需要填写AssignLanguage把所有的需要翻译的文字写一遍,我添加一个新的组件,就需要修改AssignLanguage.即时相关的翻译信息已经在Resx资源文件里了,可不可以实现form自动翻译呢,从Resx里获取信息.自动翻译Form里常用的组件,比如label,buttonbase,menuitem等.

  ok,新的需求来了,我们先来分析,自动翻译的话,首先要得到form里的所有需要翻译的组件,然后根据组件的Text,去resx里获取翻译.但是这有个问题,

    举个例子,我们了解resx里翻译是针对key来翻译的,比如"test"->"测试",这里"test"是key,"测试"是value,resx是根据key来获取value的,当我们翻译"test"的时候,可以很轻松得到"测试"的value,但再切换语言的时候,我们从组件的属性只能获得"测试",而在resx里根本没有"测试"的key.导致翻译失败.

   这里的问题是组件属性已经变成"测试",而把原始信息"test"覆盖了.所有我们所做的就是获的原始信息,当原始信息,被改变的时候,我们需要把它存放在一个table里面,记录下 原始信息-语言-当前信息 3段资料.uml序列图如下

  

   1 :实现Translate.cs代码,实现主要的功能.

  

  2:然后实现通用的父类TranslateForm,很简短,就是对translate类事件的引用.

  

  3:ok,所有的form只要继承了TranslateForm这个父类,不需要写任何代码,就可以实现即时翻译.代码量大幅度减小.

  4:调用事件,这个没变化,就是调用Translate.AssignEventLanguage(string language) ,当调用这个event的时候,就做到了动态翻译.

  5:问题:这个看上去很完美,摆脱了繁琐的一一翻译.但是

     问题(1)如果某些form部分字段不想翻译,而resx资源库里存在这段字段的话,就会自动给它翻译.当遇到这种情况的时候,我们需要特别处理,比如我们新建form3,有个"test"字,我不想让翻译,怎么办呢,

     问题(2) 当不同的form不同的文字,但是翻译成相同的文字的话,就是说多个key有相同的value,通过value寻找key,而获得原始信息的时候,就会出现找错key的问题,

     解决(1):方法一,就是override掉AssignLanguage方法,自己重写,

                 方法二,就是直接把"test"字改成别的字符,如"test_for_form3",然后添加翻译文件,把它翻译成英文"test".

     解决(2):如果要考虑到这个的话,就需要重新定义存放原始信息和翻译信息的关系表,添加一列备注,备注form信息,这样通过判断form信息,就可以获得唯一的key.