一直想做一个多语言的程序,研究了一下.net的本地化方法,觉得做起来比较麻烦,而且不能快速切换,就自己琢磨着写一个。
以我做的一个C# winform 项目为例。
       首先设计多语言文件,这里我用XML来保存,基本结构如下。
 1C#实现动态多语言界面程序<?xml version = "1.0" encoding = "GB2312"?>
 2C#实现动态多语言界面程序<AirControl language="简体中文">
 3C#实现动态多语言界面程序    <Menu>
 4C#实现动态多语言界面程序        <Project>
 5C#实现动态多语言界面程序            <Item id="0" key="MenuProject" value="项目(&amp;P)" />
 6C#实现动态多语言界面程序            <Item id="1" key="MenuProjectItem1" value="新建(&amp;N)" />
 7C#实现动态多语言界面程序            <Item id="2" key="MenuProjectItem2" value="打开(&amp;O)" />
 8C#实现动态多语言界面程序            <Item id="3" key="MenuProjectItem3" value="保存(&amp;S)" />
 9C#实现动态多语言界面程序            <Item id="5" key="MenuProjectItem5" value="退出(&amp;X)" />
10C#实现动态多语言界面程序        </Project>
11C#实现动态多语言界面程序        <Manage>
12C#实现动态多语言界面程序            <Item id="0" key="MenuManage" value="管理(&amp;M)" />
13C#实现动态多语言界面程序            <Item id="1" key="MenuManageItem1" value="登录(&amp;I)" />
14C#实现动态多语言界面程序            <Item id="2" key="MenuManageItem2" value="注销(&amp;O)" />
15C#实现动态多语言界面程序            <Item id="3" key="MenuManageItem3" value="修改密码(&amp;C)" />
16C#实现动态多语言界面程序            <Item id="4" key="MenuManageItem4" value="用户管理(&amp;U)" />
17C#实现动态多语言界面程序        </Manage>
18C#实现动态多语言界面程序        <Help>
19C#实现动态多语言界面程序            <Item id="0" key="MenuHelp" value="帮助(&amp;H)" />
20C#实现动态多语言界面程序            <Item id="1" key="MenuHelpItem1" value="帮助内容(&amp;H)" />
21C#实现动态多语言界面程序            <Item id="2" key="MenuHelpItem2" value="关于(&amp;A)" />
22C#实现动态多语言界面程序        </Help>
23C#实现动态多语言界面程序    </Menu>
24C#实现动态多语言界面程序    <Toolbar>
25C#实现动态多语言界面程序        <Statusbar>
26C#实现动态多语言界面程序            <Item id="1" key="StatusItem1" value="用户名: " />
27C#实现动态多语言界面程序            <Item id="2" key="StatusItem2" value="用户组: " />
28C#实现动态多语言界面程序            <Item id="3" key="StatusItem3" value="上次登录时间: " />
29C#实现动态多语言界面程序            <Item id="4" key="StatusItem4" value="本次登录时间:" />
30C#实现动态多语言界面程序        </Statusbar>
31C#实现动态多语言界面程序    </Toolbar>
32C#实现动态多语言界面程序    <Form>
33C#实现动态多语言界面程序        <MainForm>
34C#实现动态多语言界面程序            <Item id="0" key="MainForm" value="xx" />
35C#实现动态多语言界面程序            <Item id="1" key="buttonGo" value="开始" />
36C#实现动态多语言界面程序            <Item id="2" key="buttonStop" value="停止" />        
37C#实现动态多语言界面程序            <Item id="3" key="groupBox1" value="用户信息" />
38C#实现动态多语言界面程序            <Item id="4" key="groupBox2" value="常规数据" />    
39C#实现动态多语言界面程序        </MainForm>
40C#实现动态多语言界面程序        <UserLoginForm>
41C#实现动态多语言界面程序            <Item id="0" key="UserLoginForm" value="用户登录" />
42C#实现动态多语言界面程序            <Item id="1" key="labelTitle"  value="xx" />
43C#实现动态多语言界面程序            <Item id="2" key="labelUsername" value="用户名" />
44C#实现动态多语言界面程序            <Item id="3" key="labelPassword" value="密码" />
45C#实现动态多语言界面程序            <Item id="4" key="buttonLogin" value="登录" />
46C#实现动态多语言界面程序        </UserLoginForm>
47C#实现动态多语言界面程序        <ChangePasswordForm>
48C#实现动态多语言界面程序            <Item id="0" key="ChangePasswordForm" value="修改密码" />
49C#实现动态多语言界面程序            <Item id="1" key="label1" value="原密码" />
50C#实现动态多语言界面程序            <Item id="2" key="label2" value="新密码" />
51C#实现动态多语言界面程序            <Item id="3" key="label3" value="再输入" />
52C#实现动态多语言界面程序            <Item id="4" key="buttonConfirm" value="确认" />
53C#实现动态多语言界面程序            <Item id="5" key="buttonCancel" value="取消" />
54C#实现动态多语言界面程序        </ChangePasswordForm>
55C#实现动态多语言界面程序    </Form>
56C#实现动态多语言界面程序    <Dialog>
57C#实现动态多语言界面程序        <Title>
58C#实现动态多语言界面程序            <Item id="0" key="0001" value="xx" />
59C#实现动态多语言界面程序            <Item id="1" key="0002" value="添加测试" />
60C#实现动态多语言界面程序            <Item id="2" key="0003" value="添加用户" />
61C#实现动态多语言界面程序            <Item id="3" key="0004" value="修改密码" />
62C#实现动态多语言界面程序        </Title>
63C#实现动态多语言界面程序        <Message>
64C#实现动态多语言界面程序            <Item id="0" key="0000" value="一切正常" />
65C#实现动态多语言界面程序            <Item id="1" key="2001" value="用户名或密码错误" />
66C#实现动态多语言界面程序            <Item id="5" key="2002" value="密码不一致" />
67C#实现动态多语言界面程序            <Item id="6" key="2003" value="用户名已存在" />
68C#实现动态多语言界面程序            <Item id="7" key="2004" value="添加用户成功" />            
69C#实现动态多语言界面程序        </Message>            
70C#实现动态多语言界面程序    </Dialog>
71C#实现动态多语言界面程序</AirControl>
        这里是语言文件的局部,主体分为四个部分,Menu, Toolbar, Form 和 Dialog,分别对应菜单,工具栏,窗体和对话框的显示字符串。
在Form里面,其每个子树分别对应一个窗体。XML每项有三个域,id 这个只是用来标号,程序中为用,key,value形成一个字典,key是控件
的名称,value是控件的text。在Dialog中key用数字编号。
   做其他语言文件时,只用将value里面的值改成对应的语言即可。
     当然,我们也不一定用XML来写语言文件,简单的ini文件也行。我现在觉得在一般的中小型程序中用XML,出于一个最基本的目的就是装B。

        下面设计读取这个XML的类,
  1C#实现动态多语言界面程序using System;
  2C#实现动态多语言界面程序using System.Collections.Generic;
  3C#实现动态多语言界面程序using System.Linq;
  4C#实现动态多语言界面程序using System.Text;
  5C#实现动态多语言界面程序using System.Xml;
  6C#实现动态多语言界面程序
  7C#实现动态多语言界面程序namespace AirLibrary
  8
        这里我使用静态类来读取和保存,这样效率相对会高一些。读取XML时,我使用的是XmlReader,它使用流式读取,速度也比较快。
        Forms, Menu, Toolbar, Dialog几个属性分别对应XML中的子树,使用.net中的Dictionary范型,Forms嵌套了一层Dictionary。
Load方法是加载语言文件,readLanguage 和paraseXML 函数对XML进行解析,并保存字符串到对应的属性中。
        AddForm这个方法是将每个窗体的动态的添加到forms 里面。
        在程序开始main 函数中,首先调用AddForm方法,添加所有窗体。
       
 1         // 添加所有窗体用于本地化(按XML中顺序)
 2         private static void AddForm()
 3         {
 4             Localization.AddForm("MainForm");
 5             Localization.AddForm("UserLoginForm");
 6             Localization.AddForm("UserManageForm");
 7             Localization.AddForm("ChangePasswordForm");
 8         }
   然后加载语言文件。
1  if (!Localization.Load("zh"))
2             {
3                 MessageBox.Show("无法加载语言配置文件, 将显示英文.""错误", MessageBoxButtons.OK,
4                     MessageBoxIcon.Exclamation);
5                 Localization.HasLang = false;
6             }
7             else
8                 Localization.HasLang = true;

       在每个Form的Load事件中初始化每个控件的Text。
1 if (Localization.HasLang)
2         RefreshLanguage();

// 更新窗体语言
public static void RefreshLanguage(Form form)
{          
     form.Text 
= Localization.Forms[form.Name][form.Name];
     SetControlsLanguage(form, Localization.Forms[form.Name]);
}

         递归更新每个控件Text
 1 /// <summary>
 2 /// 设置control子控件语言
 3 /// </summary>
 4 /// <param name="control">父控件</param>
 5 /// <param name="obj">语言字典</param>
 6 public static void SetControlsLanguage(Control control, Dictionary<stringstring> obj)
 7 {
 8      foreach (Control ctrl in control.Controls)
 9      {
10         // set the control which one's key in the dictionary
11         string text = "";
12         if (obj.TryGetValue(ctrl.Name, out text))
13               ctrl.Text = text;
14 
15         if (ctrl.HasChildren)
16               SetControlsLanguage(ctrl, obj);
17       }
18 }
  
         另外主窗体的Menu和Toolbar,我采用以下的方法更新。
 1 // Refresh the menu language
 2 foreach (ToolStripMenuItem topItem in MainMenuStrip.Items)
 3 {
 4       topItem.Text = Localization.Menu[topItem.Name];
 5       foreach (ToolStripItem item in topItem.DropDownItems)
 6       {
 7             if (item is ToolStripMenuItem)
 8             {
 9                  string text = "";
10                  if (Localization.Menu.TryGetValue(item.Name, out text))
11                       item.Text = text;
12             }
13       }
14 }
15 
16 // Refresh the statusbar language
17 foreach (ToolStripItem item in mainStatus.Items)
18 {
19      string text = "";
20      if (Localization.Toolbar.TryGetValue(item.Name, out text))
21              item.Text = text;
22 }
           Dialog就直接调用Localization中的Dialog属性即可。
           需要转变为不同语言时只需要再调用一次Localization.Load方法。
        
小结:
       这种实现多语言界面的方式我思考了很久,也在网上查了一些资料,最后设计了这样一种方式,XML中利用字典来记录控件的语言
在添加,读取时非常方便,Localization类做成静态类,在运行时就相当于一个常量,没有构造函数这样的开销,整个界面也可以再运行时
直接改变界面语言。
       当然这种方法不一定是最好的, 如果有更好的方法欢迎指点。

相关文章: