以我做的一个C# winform 项目为例。
首先设计多语言文件,这里我用XML来保存,基本结构如下。
1
<?
xml version = "1.0" encoding = "GB2312"
?>
2
<
AirControl
language
="简体中文"
>
3
<
Menu
>
4
<
Project
>
5
<
Item
id
="0"
key
="MenuProject"
value
="项目(&P)"
/>
6
<
Item
id
="1"
key
="MenuProjectItem1"
value
="新建(&N)"
/>
7
<
Item
id
="2"
key
="MenuProjectItem2"
value
="打开(&O)"
/>
8
<
Item
id
="3"
key
="MenuProjectItem3"
value
="保存(&S)"
/>
9
<
Item
id
="5"
key
="MenuProjectItem5"
value
="退出(&X)"
/>
10
</
Project
>
11
<
Manage
>
12
<
Item
id
="0"
key
="MenuManage"
value
="管理(&M)"
/>
13
<
Item
id
="1"
key
="MenuManageItem1"
value
="登录(&I)"
/>
14
<
Item
id
="2"
key
="MenuManageItem2"
value
="注销(&O)"
/>
15
<
Item
id
="3"
key
="MenuManageItem3"
value
="修改密码(&C)"
/>
16
<
Item
id
="4"
key
="MenuManageItem4"
value
="用户管理(&U)"
/>
17
</
Manage
>
18
<
Help
>
19
<
Item
id
="0"
key
="MenuHelp"
value
="帮助(&H)"
/>
20
<
Item
id
="1"
key
="MenuHelpItem1"
value
="帮助内容(&H)"
/>
21
<
Item
id
="2"
key
="MenuHelpItem2"
value
="关于(&A)"
/>
22
</
Help
>
23
</
Menu
>
24
<
Toolbar
>
25
<
Statusbar
>
26
<
Item
id
="1"
key
="StatusItem1"
value
="用户名: "
/>
27
<
Item
id
="2"
key
="StatusItem2"
value
="用户组: "
/>
28
<
Item
id
="3"
key
="StatusItem3"
value
="上次登录时间: "
/>
29
<
Item
id
="4"
key
="StatusItem4"
value
="本次登录时间:"
/>
30
</
Statusbar
>
31
</
Toolbar
>
32
<
Form
>
33
<
MainForm
>
34
<
Item
id
="0"
key
="MainForm"
value
="xx"
/>
35
<
Item
id
="1"
key
="buttonGo"
value
="开始"
/>
36
<
Item
id
="2"
key
="buttonStop"
value
="停止"
/>
37
<
Item
id
="3"
key
="groupBox1"
value
="用户信息"
/>
38
<
Item
id
="4"
key
="groupBox2"
value
="常规数据"
/>
39
</
MainForm
>
40
<
UserLoginForm
>
41
<
Item
id
="0"
key
="UserLoginForm"
value
="用户登录"
/>
42
<
Item
id
="1"
key
="labelTitle"
value
="xx"
/>
43
<
Item
id
="2"
key
="labelUsername"
value
="用户名"
/>
44
<
Item
id
="3"
key
="labelPassword"
value
="密码"
/>
45
<
Item
id
="4"
key
="buttonLogin"
value
="登录"
/>
46
</
UserLoginForm
>
47
<
ChangePasswordForm
>
48
<
Item
id
="0"
key
="ChangePasswordForm"
value
="修改密码"
/>
49
<
Item
id
="1"
key
="label1"
value
="原密码"
/>
50
<
Item
id
="2"
key
="label2"
value
="新密码"
/>
51
<
Item
id
="3"
key
="label3"
value
="再输入"
/>
52
<
Item
id
="4"
key
="buttonConfirm"
value
="确认"
/>
53
<
Item
id
="5"
key
="buttonCancel"
value
="取消"
/>
54
</
ChangePasswordForm
>
55
</
Form
>
56
<
Dialog
>
57
<
Title
>
58
<
Item
id
="0"
key
="0001"
value
="xx"
/>
59
<
Item
id
="1"
key
="0002"
value
="添加测试"
/>
60
<
Item
id
="2"
key
="0003"
value
="添加用户"
/>
61
<
Item
id
="3"
key
="0004"
value
="修改密码"
/>
62
</
Title
>
63
<
Message
>
64
<
Item
id
="0"
key
="0000"
value
="一切正常"
/>
65
<
Item
id
="1"
key
="2001"
value
="用户名或密码错误"
/>
66
<
Item
id
="5"
key
="2002"
value
="密码不一致"
/>
67
<
Item
id
="6"
key
="2003"
value
="用户名已存在"
/>
68
<
Item
id
="7"
key
="2004"
value
="添加用户成功"
/>
69
</
Message
>
70
</
Dialog
>
71
</
AirControl
>
这里是语言文件的局部,主体分为四个部分,Menu, Toolbar, Form 和 Dialog,分别对应菜单,工具栏,窗体和对话框的显示字符串。
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
2
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
3
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
4
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
5
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
6
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
7
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
8
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
9
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
10
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
11
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
12
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
13
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
14
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
15
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
16
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
17
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
18
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
19
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
20
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
21
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
22
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
23
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
24
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
25
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
26
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
27
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
28
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
29
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
30
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
31
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
32
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
33
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
34
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
35
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
36
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
37
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
38
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
39
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
40
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
41
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
42
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
43
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
44
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
45
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
46
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
47
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
48
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
49
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
50
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
51
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
52
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
53
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
54
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
55
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
56
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
57
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
58
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
59
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
60
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
61
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
62
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
63
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
64
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
65
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
66
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
67
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
68
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
69
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
70
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
71
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
在Form里面,其每个子树分别对应一个窗体。XML每项有三个域,id 这个只是用来标号,程序中为用,key,value形成一个字典,key是控件
的名称,value是控件的text。在Dialog中key用数字编号。
做其他语言文件时,只用将value里面的值改成对应的语言即可。
当然,我们也不一定用XML来写语言文件,简单的ini文件也行。我现在觉得在一般的中小型程序中用XML,出于一个最基本的目的就是装B。
下面设计读取这个XML的类,
1
using
System;
2
using
System.Collections.Generic;
3
using
System.Linq;
4
using
System.Text;
5
using
System.Xml;
6![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
7
namespace
AirLibrary
8![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
{
9![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
10
/// 本地化类
11
/// </summary>
12
public static class Localization
13![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
14![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
Property#region Property
15![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public static string Lang
{ get; private set; }
16![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
public static bool HasLang
{ get; set; }
17
#endregion //Property
18![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
19![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
Attribute#region Attribute
20
private static Dictionary<string, Dictionary<string, string>> forms = new Dictionary<string, Dictionary<string, string>>();
21
private static Dictionary<string, string> menu = new Dictionary<string, string>();
22
private static Dictionary<string, string> toolbar = new Dictionary<string, string>();
23
private static Dictionary<string, string> dialog = new Dictionary<string, string>();
24
#endregion //Attribute
25![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
26![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
Method#region Method
27
public static void AddForm(string formName)
28![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
29
forms.Add(formName, new Dictionary<string, string>());
30
//formMap.Add(formName, count++);
31
}
32![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
33![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
/**//// <summary>
34
/// 加载语言文件
35
/// </summary>
36
/// <param name="lang">语言</param>
37
/// <returns></returns>
38
public static bool Load(string lang)
39![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
40
string path = "";
41
Localization.Lang = "English";
42![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
43
menu.Clear();
44
toolbar.Clear();
45
dialog.Clear();
46
exception.Clear();
47
foreach (Dictionary<string, string> form in forms.Values)
48
form.Clear();
49
50
switch (lang)
51![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
52
case "zh":
53
path = @"resources/lang-zh.xml";
54
break;
55
case "en":
56
path = @"resources/lang-en.xml";
57
break;
58
default:
59
path = @"resources/lang-zh.xml";
60
break;
61
}
62![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
63
return readLanguage(path);
64
}
65
#endregion //Method
66![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
67![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
Function#region Function
68
private static bool readLanguage(string path)
69![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
70
// Read the language file
71
XmlReader reader;
72
try
73![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
74
reader = XmlReader.Create(path);
75
}
76
catch (Exception)
77![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
78
return false;
79
}
80![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
81
// Begin to parase
82
try
83![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
84
reader.ReadToFollowing("AirControl");
85
Localization.Lang = reader.GetAttribute("language");
86![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
87
paraseXml(reader, "Menu", menu);
88
paraseXml(reader, "Toolbar", toolbar);
89
90
foreach (string formName in forms.Keys)
91![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
92
paraseXml(reader, formName, forms[formName]);
93
}
94
paraseXml(reader, "Dialog", dialog);
95
}
96
catch (Exception)
97![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
98
return false;
99
}
100
return true;
101
}
102![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
103
private static void paraseXml(XmlReader reader, string item, Dictionary<string, string> obj)
104![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
105
// Get the attribute key & value
106
reader.ReadToFollowing(item);
107![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
108
XmlReader subreader = reader.ReadSubtree();
109
while (subreader.Read())
110![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
111
if (subreader.NodeType == XmlNodeType.Element && subreader.Name == "Item")
112
obj.Add(subreader.GetAttribute("key"), subreader.GetAttribute("value"));
113
}
114
}
115
#endregion //Function
116![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
117![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
Property#region Property
118
public static Dictionary<string, string> Menu
119![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
120
get
121![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
122
return menu;
123
}
124
private set
125![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{ }
126
}
127![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
128
public static Dictionary<string, string> Toolbar
129![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
130
get
131![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
132
return toolbar;
133
}
134
private set
135![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{ }
136
}
137![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
138
public static Dictionary<string, Dictionary<string, string>> Forms
139![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
140
get
141![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
142
return forms;
143
}
144
private set
145![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{ }
146
}
147
148
public static Dictionary<string, string> Dialog
149![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
150
get
151![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{
152
return dialog;
153
}
154
private set
155![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
{ }
156
}
157
#endregion //Property
158
}
159
}
160
这里我使用静态类来读取和保存,这样效率相对会高一些。读取XML时,我使用的是XmlReader,它使用流式读取,速度也比较快。
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
2
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
3
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
4
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
5
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
6
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
7
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
8
![ExpandedBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif)
![ContractedBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
![](https://www.cnblogs.com/Images/dot.gif)
9
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
10
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
11
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
12
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
13
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![](https://www.cnblogs.com/Images/dot.gif)
14
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
15
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![](https://www.cnblogs.com/Images/dot.gif)
16
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![](https://www.cnblogs.com/Images/dot.gif)
17
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
18
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
19
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
20
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
21
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
22
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
23
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
24
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
25
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
26
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
27
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
28
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![](https://www.cnblogs.com/Images/dot.gif)
29
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
30
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
31
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
32
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
33
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
34
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
35
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
36
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
37
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
38
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
39
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![](https://www.cnblogs.com/Images/dot.gif)
40
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
41
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
42
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
43
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
44
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
45
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
46
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
47
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
48
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
49
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
50
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
51
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![](https://www.cnblogs.com/Images/dot.gif)
52
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
53
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
54
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
55
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
56
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
57
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
58
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
59
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
60
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
61
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
62
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
63
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
64
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
65
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
66
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
67
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
68
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
69
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![](https://www.cnblogs.com/Images/dot.gif)
70
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
71
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
72
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
73
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![](https://www.cnblogs.com/Images/dot.gif)
74
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
75
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
76
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
77
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![](https://www.cnblogs.com/Images/dot.gif)
78
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
79
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
80
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
81
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
82
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
83
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![](https://www.cnblogs.com/Images/dot.gif)
84
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
85
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
86
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
87
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
88
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
89
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
90
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
91
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![](https://www.cnblogs.com/Images/dot.gif)
92
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
93
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
94
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
95
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
96
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
97
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![](https://www.cnblogs.com/Images/dot.gif)
98
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
99
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
100
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
101
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
102
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
103
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
104
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![](https://www.cnblogs.com/Images/dot.gif)
105
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
106
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
107
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
108
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
109
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
110
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![](https://www.cnblogs.com/Images/dot.gif)
111
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
112
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
113
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
114
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
115
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
116
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
117
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
118
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
119
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![](https://www.cnblogs.com/Images/dot.gif)
120
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
121
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![](https://www.cnblogs.com/Images/dot.gif)
122
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
123
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
124
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
125
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![](https://www.cnblogs.com/Images/dot.gif)
126
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
127
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
128
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
129
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![](https://www.cnblogs.com/Images/dot.gif)
130
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
131
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![](https://www.cnblogs.com/Images/dot.gif)
132
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
133
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
134
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
135
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![](https://www.cnblogs.com/Images/dot.gif)
136
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
137
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
138
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
139
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![](https://www.cnblogs.com/Images/dot.gif)
140
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
141
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![](https://www.cnblogs.com/Images/dot.gif)
142
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
143
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
144
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
145
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![](https://www.cnblogs.com/Images/dot.gif)
146
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
147
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
148
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
149
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![](https://www.cnblogs.com/Images/dot.gif)
150
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
151
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![](https://www.cnblogs.com/Images/dot.gif)
152
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
153
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
154
![](https://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif)
155
![ExpandedSubBlockStart.gif](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![ContractedSubBlock.gif](https://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif)
![](https://www.cnblogs.com/Images/dot.gif)
156
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
157
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
158
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
159
![](https://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif)
160
![](https://www.cnblogs.com/Images/OutliningIndicators/None.gif)
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 }
然后加载语言文件。
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 ;
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();
2 RefreshLanguage();
//
更新窗体语言
public static void RefreshLanguage(Form form)
{
form.Text = Localization.Forms[form.Name][form.Name];
SetControlsLanguage(form, Localization.Forms[form.Name]);
}
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 < string , string > 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 }
2 /// 设置control子控件语言
3 /// </summary>
4 /// <param name="control"> 父控件 </param>
5 /// <param name="obj"> 语言字典 </param>
6 public static void SetControlsLanguage(Control control, Dictionary < string , string > 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属性即可。
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 }
需要转变为不同语言时只需要再调用一次Localization.Load方法。
小结:
这种实现多语言界面的方式我思考了很久,也在网上查了一些资料,最后设计了这样一种方式,XML中利用字典来记录控件的语言
在添加,读取时非常方便,Localization类做成静态类,在运行时就相当于一个常量,没有构造函数这样的开销,整个界面也可以再运行时
直接改变界面语言。
当然这种方法不一定是最好的, 如果有更好的方法欢迎指点。