c#winform:开发多语言应用程序!!
问题是:在窗体上添加一个语言menu,有几个选项:english,Chinese(simplied),German,Japanes等选项,当选择其中一项时,程序的语言就显示该语言。
程序默认语言是english.
例如:程序的登陆界面上有几个label,分别为UserName,password,login,servername。当选择Chinese(simplied)选项时,这几个label应显示为:用户名,密码,登录,服务器名。
大概就是这个意思,很多网站都提供多语言选项的。
因本人是初学者,有些东西不明白,所以希望大家能提供一个具体可行的方法。
谢谢各位高手!!!
[解决办法]
动态加载资源文件
[解决办法]
一般情况下都是用资源文件做,不过不推荐使用.
最好是做多个XML文件,有几种语言就做几个XML文件. 用来保存控件名,以及控件的内容,
例如:英文XML文件
<form Name = 'Login'>
<Control name = 'BtnSave'>
Save
</Control>
</form>
对应的中文文件就是
<form Name = 'Login'>
<Control name = 'BtnSave'>
保存
</Control>
</form>
还要用个地方来保存默认语言.
每次启动一个窗体的时候首先识别默认语言,然后根据默认语言遍历Xml文件.
[解决办法]
把所有字段存放在一个表中,程序运行时从这表中读取相应的语言的字段。
如:建一个mFieldName表,用Form的名字和FieldName做关键字,再加几个english,Chinese(simplied),German,Japanes等字段,当然在修改或新加窗体的时候维护这个表.
然后在程序运行时根据不同的选项读取不同的字段(english,Chinese(simplied),German,Japanes)。
[解决办法]
- C# code
<?xml version="1.0" encoding="utf-8"?> <Text> <TAG key="0001" CHS="国际贸易-供应链系统" JP="" KR="?????????" EN="" /> <TAG key="0002" CHS="中文" JP="" KR="????" EN="" /> <TAG key="0003" CHS="韩文" JP="" KR="????" EN="" /> <TAG key="0004" CHS="国际贸易" JP="" KR="" EN="" /> <TAG key="0005" CHS="供应链系统" JP="" KR="" EN="" /> <TAG key="00001" CHS="添加药品类别-" JP="" KR="??????" EN="" /> </Text> <!--这个写在在Text.config里面,假设一个Label吧你起名字就的LG_lblName 其余的控件都的起这样的前面加上LG_XX 然后在aspx里面的 <form> <asp:Panel ID="LG_Panel" runat="server" Width="100%"> <table> <tr> <td>ddd </td> </tr> </table> </asp:Panel > </form>这些都是必须的。然后调用的时候也就是我 给你的那个类在上面 CS里面这样调用 Language.ChangeControlsText(LG_Panel); 支持多国语言。忘了起名字的时候假设国际贸易-供应链系统叫这个名字吧 ,那这个Label吧你起名字就的叫LG_0001必须和 Text.Config里面的 对起来 <TAG key="0001" CHS="国际贸易-供应链系统" JP="" KR="?????????" EN="" /> -->
[解决办法]
[解决办法]
- C# code
/* * //ArrayList 和 StringCollection 类以及 List 泛型类通过元素的从零开始的索引提供对元素的访问。//Hashtable、SortedList、ListDictionary 和 StringDictionary 类以及 Dictionary 和 SortedDictionary 泛型类通过元素的键提供对元素的访问。//NameObjectCollectionBase 和 NameValueCollection 类以及 KeyedCollection 和 SortedList 泛型类通过其元素的从零开始的索引或者通过其元素的键提供对元素的访问。 * * * **************** * CultureInfo 类 * * **************** 区域性/语言名称 区域性标识符 区域性 ""(空字符串) 0x007F 固定区域性 af 0x0036 南非荷兰语 af-ZA 0x0436 南非荷兰语(南非) sq 0x001C 阿尔巴尼亚语 sq-AL 0x041C 阿尔巴尼亚语(阿尔巴尼亚) ar 0x0001 阿拉伯语 ar-DZ 0x1401 阿拉伯语(阿尔及利亚) ar-BH 0x3C01 阿拉伯语(巴林) ar-EG 0x0C01 阿拉伯语(埃及) ar-IQ 0x0801 阿拉伯语(伊拉克) ar-JO 0x2C01 阿拉伯语(约旦) ar-KW 0x3401 阿拉伯语(科威特) ar-LB 0x3001 阿拉伯语(黎巴嫩) ar-LY 0x1001 阿拉伯语(利比亚) ar-MA 0x1801 阿拉伯语(摩洛哥) ar-OM 0x2001 阿拉伯语(阿曼) ar-QA 0x4001 阿拉伯语(卡塔尔) ar-SA 0x0401 阿拉伯语(沙特阿拉伯) ar-SY 0x2801 阿拉伯语(叙利亚) ar-TN 0x1C01 阿拉伯语(突尼斯) ar-AE 0x3801 阿拉伯语(阿联酋) ar-YE 0x2401 阿拉伯语(也门) hy 0x002B 亚美尼亚语 hy-AM 0x042B 亚美尼亚语(亚美尼亚) az 0x002C 阿泽里语 az-Cyrl-AZ 0x082C 阿泽里语(阿塞拜疆,西里尔语) az-Latn-AZ 0x042C 阿泽里语(阿塞拜疆,拉丁语) eu 0x002D 巴斯克语 eu-ES 0x042D 巴斯克语(巴斯克地区) be 0x0023 白俄罗斯语 be-BY 0x0423 白俄罗斯语(白俄罗斯) bg 0x0002 保加利亚语 bg-BG 0x0402 保加利亚语(保加利亚) ca 0x0003 加泰罗尼亚语 ca-ES 0x0403 加泰罗尼亚语(加泰罗尼亚地区) zh-HK 0x0C04 中文(香港特别行政区,中国) zh-MO 0x1404 中文(澳门特别行政区) zh-CN 0x0804 中文(中国) zh-Hans 0x0004 中文(简体) zh-SG 0x1004 中文(新加坡) zh-TW 0x0404 中文(台湾) zh-Hant 0x7C04 中文(繁体) hr 0x001A 克罗地亚语 hr-HR 0x041A 克罗地亚语(克罗地亚) cs 0x0005 捷克语 cs-CZ 0x0405 捷克语(捷克共和国) da 0x0006 丹麦语 da-DK 0x0406 丹麦语(丹麦) dv 0x0065 迪维希语 dv-MV 0x0465 迪维希语(马尔代夫) nl 0x0013 荷兰语 nl-BE 0x0813 荷兰语(比利时) nl-NL 0x0413 荷兰语(荷兰) en 0x0009 英语 en-AU 0x0C09 英语(澳大利亚) en-BZ 0x2809 英语(伯利兹) en-CA 0x1009 英语(加拿大) en-029 0x2409 英语(加勒比) en-IE 0x1809 英语(爱尔兰) en-JM 0x2009 英语(牙买加) en-NZ 0x1409 英语(新西兰) en-PH 0x3409 英语(菲律宾) en-ZA 0x1C09 英语(南非) en-TT 0x2C09 英语(特立尼达和多巴哥) en-GB 0x0809 英语(英国) en-US 0x0409 英语(美国) en-ZW 0x3009 英语(津巴布韦) et 0x0025 爱沙尼亚语 et-EE 0x0425 爱沙尼亚语(爱沙尼亚) fo 0x0038 法罗语 fo-FO 0x0438 法罗语(法罗群岛) fa 0x0029 波斯语 fa-IR 0x0429 波斯语(伊朗) fi 0x000B 芬兰语 fi-FI 0x040B 芬兰语(芬兰) fr 0x000C 法语 fr-BE 0x080C 法语(比利时) fr-CA 0x0C0C 法语(加拿大) fr-FR 0x040C 法语(法国) fr-LU 0x140C 法语(卢森堡) fr-MC 0x180C 法语(摩纳哥) fr-CH 0x100C 法语(瑞士) gl 0x0056 加利西亚语 gl-ES 0x0456 加利西亚语(西班牙) ka 0x0037 格鲁吉亚语 ka-GE 0x0437 格鲁吉亚语(格鲁吉亚) de 0x0007 德语 de-AT 0x0C07 德语(奥地利) de-DE 0x0407 德语(德国) de-LI 0x1407 德语(列支敦士登) de-LU 0x1007 德语(卢森堡) de-CH 0x0807 德语(瑞士) el 0x0008 希腊语 el-GR 0x0408 希腊语(希腊) gu 0x0047 古吉拉特语 gu-IN 0x0447 古吉拉特语(印度) he 0x000D 希伯来语 he-IL 0x040D 希伯来语(以色列) hi 0x0039 印地语 hi-IN 0x0439 印地语(印度) hu 0x000E 匈牙利语 hu-HU 0x040E 匈牙利语(匈牙利) is 0x000F 冰岛语 is-IS 0x040F 冰岛语(冰岛) id 0x0021 印度尼西亚语 id-ID 0x0421 印度尼西亚语(印度尼西亚) it 0x0010 意大利语 it-IT 0x0410 意大利语(意大利) it-CH 0x0810 意大利语(瑞士) ja 0x0011 日语 ja-JP 0x0411 日语(日本) kn 0x004B 卡纳达语 kn-IN 0x044B 卡纳达语(印度) kk 0x003F 哈萨克语 kk-KZ 0x043F 哈萨克语(哈萨克斯坦) kok 0x0057 贡根语 kok-IN 0x0457 贡根语(印度) ko 0x0012 朝鲜语 ko-KR 0x0412 朝鲜语(韩国) ky 0x0040 吉尔吉斯语 ky-KG 0x0440 吉尔吉斯语(吉尔吉斯坦) lv 0x0026 拉脱维亚语 lv-LV 0x0426 拉脱维亚语(拉脱维亚) lt 0x0027 立陶宛语 lt-LT 0x0427 立陶宛语(立陶宛) mk 0x002F 马其顿语 mk-MK 0x042F 马其顿语(马其顿,FYROM) ms 0x003E 马来语 ms-BN 0x083E 马来语(文莱达鲁萨兰) ms-MY 0x043E 马来语(马来西亚) mr 0x004E 马拉地语 mr-IN 0x044E 马拉地语(印度) mn 0x0050 蒙古语 mn-MN 0x0450 蒙古语(蒙古) no 0x0014 挪威语 nb-NO 0x0414 挪威语(伯克梅尔,挪威) nn-NO 0x0814 挪威语(尼诺斯克,挪威) pl 0x0015 波兰语 pl-PL 0x0415 波兰语(波兰) pt 0x0016 葡萄牙语 pt-BR 0x0416 葡萄牙语(巴西) pt-PT 0x0816 葡萄牙语(葡萄牙) pa 0x0046 旁遮普语 pa-IN 0x0446 旁遮普语(印度) ro 0x0018 罗马尼亚语 ro-RO 0x0418 罗马尼亚语(罗马尼亚) ru 0x0019 俄语 ru-RU 0x0419 俄语(俄罗斯) sa 0x004F 梵语 sa-IN 0x044F 梵语(印度) sr-Cyrl-CS 0x0C1A 塞尔维亚语(塞尔维亚,西里尔语) sr-Latn-CS 0x081A 塞尔维亚语(塞尔维亚,拉丁语) sk 0x001B 斯洛伐克语 sk-SK 0x041B 斯洛伐克语(斯洛伐克) sl 0x0024 斯洛文尼亚语 sl-SI 0x0424 斯洛文尼亚语(斯洛文尼亚) es 0x000A 西班牙语 es-AR 0x2C0A 西班牙语(阿根廷) es-BO 0x400A 西班牙语(玻利维亚) es-CL 0x340A 西班牙语(智利) es-CO 0x240A 西班牙语(哥伦比亚) es-CR 0x140A 西班牙语(哥斯达黎加) es-DO 0x1C0A 西班牙语(多米尼加共和国) es-EC 0x300A 西班牙语(厄瓜多尔) es-SV 0x440A 西班牙语(萨尔瓦多) es-GT 0x100A 西班牙语(危地马拉) es-HN 0x480A 西班牙语(洪都拉斯) es-MX 0x080A 西班牙语(墨西哥) es-NI 0x4C0A 西班牙语(尼加拉瓜) es-PA 0x180A 西班牙语(巴拿马) es-PY 0x3C0A 西班牙语(巴拉圭) es-PE 0x280A 西班牙语(秘鲁) es-PR 0x500A 西班牙语(波多黎各) es-ES 0x0C0A 西班牙语(西班牙) es-ES_tradnl 0x040A 西班牙语(西班牙,传统排序) es-UY 0x380A 西班牙语(乌拉圭) es-VE 0x200A 西班牙语(委内瑞拉) sw 0x0041 斯瓦希里语 sw-KE 0x0441 斯瓦希里语(肯尼亚) sv 0x001D 瑞典语 sv-FI 0x081D 瑞典语(芬兰) sv-SE 0x041D 瑞典语(瑞典) syr 0x005A 叙利亚语 syr-SY 0x045A 叙利亚语(叙利亚) ta 0x0049 泰米尔语 ta-IN 0x0449 泰米尔语(印度) tt 0x0044 鞑靼语 tt-RU 0x0444 鞑靼语(俄罗斯) te 0x004A 泰卢固语 te-IN 0x044A 泰卢固语(印度) th 0x001E 泰语 th-TH 0x041E 泰语(泰国) tr 0x001F 土耳其语 tr-TR 0x041F 土耳其语(土耳其) uk 0x0022 乌克兰语 uk-UA 0x0422 乌克兰语(乌克兰) ur 0x0020 乌尔都语 ur-PK 0x0420 乌尔都语(巴基斯坦) uz 0x0043 乌兹别克语 uz-Cyrl-UZ 0x0843 乌兹别克语(乌兹别克斯坦,西里尔语) uz-Latn-UZ 0x0443 乌兹别克语(乌兹别克斯坦,拉丁语) vi 0x002A 越南语 vi-VN 0x042A 越南语(越南) */
[解决办法]
观察着+工厂方法,定义事件委托的实现
楼主看懂了结贴给满分,兄弟们也帮忙测试下,是不是这样写合理!!!?
- C# code
using System;using System.Collections.Generic;using System.Text;using System.Globalization;using System.IO;namespace LocalizableLanguage{ /// <summary> /// 观察目标对象,窗体FORM作为观察者 /// </summary> public class SubjectLanguageObserver { private CultureInfo thisCulture;//具体的观察目标 public CultureInfo ThisCulture { get { return thisCulture; } set { thisCulture = value; } } /// <summary> /// 定义一个Delegate,用来规范函数结构。 /// 在激发事件时,函数会传递观察目标对象LanguageObserverSubject--》thisCulture和读到的数据 /// </summary> /// <param name="sender">LanguageObserverSubject</param> /// <param name="e">CultureInfoEventArgs</param> public delegate void CultureInfoEventHandler(Object sender, CultureInfoEventArgs e); /// <summary> /// 让观察者FORM注册delegate事件CultureInfoEventHandler /// </summary> public event CultureInfoEventHandler CultureInfoChanged; //声明事件 protected virtual void OnCultureInfoChanged(CultureInfoEventArgs e) { if (CultureInfoChanged != null)//如果有对象注册 { CultureInfoChanged(this, e);//调用所有注册对象的方法 } } /// <summary> /// 触发具体的观察目标的状态改变,改变 CultureInfo即改变UI的语言 /// </summary> public void CultureInfoChangeUILanguage() { CultureInfoEventArgs e = new CultureInfoEventArgs(thisCulture); OnCultureInfoChanged(e); } public void CultureInfoChangeUILanguage(CultureInfo c) { thisCulture = c; CultureInfoEventArgs e = new CultureInfoEventArgs(c); OnCultureInfoChanged(e); } public void CultureInfoChangeUILanguage(int cl_id) { thisCulture = new CultureInfo(cl_id); CultureInfoEventArgs e = new CultureInfoEventArgs(thisCulture); OnCultureInfoChanged(e); } /// <summary> /// 传递给Observer所感兴趣的信息 /// </summary> public class CultureInfoEventArgs : EventArgs { private readonly CultureInfo culture; private readonly ILocalizableLanguage langDictionary; public CultureInfoEventArgs(CultureInfo thisCulture) { culture = thisCulture; ill = LocalizableLanguageFactory.CreateLocalizableLanguage(thisCulture); langDictionary =ill ; } } private static ILocalizableLanguage ill; public ILocalizableLanguage languageDictionary { get { return ill; } } public SubjectLanguageObserver() { if (thisCulture == null) thisCulture = System.Threading.Thread.CurrentThread.CurrentCulture; ill = LocalizableLanguageFactory.CreateLocalizableLanguage(thisCulture); } } public interface ILocalizableLanguage { string GetLocalizableLanguageByKey(string key); } internal abstract class AbstractLocalizableLanguage : ILocalizableLanguage { public abstract string GetLocalizableLanguageByKey(string key); public abstract IDictionary<string, string> LoadLanguageFile(string path); private IDictionary<string, string> languageDictionary; public IDictionary<string, string> LanguageDictionary { get { return languageDictionary; } set { languageDictionary = value; } } }
[解决办法]
我的代码的思想是:
在窗体类中,窗体作为观察者,监视CultureInfo对象,
CultureInfo的改变,将激发界面语言的改变,
所以,在form类中建立观察者的基类,并注册事件,
CultureInfo的改变要使得ILocalizableLanguage 接口对象的改变,
而用工厂方法返回依据CultureInfo创建的不同的语言对象!
[解决办法]
一般可以用两种方式,
1.资源文件。
2.xml配置,程序启动时根据用户选择加载对应语言的xml。
[解决办法]
多语言支持实际上是两个问题:
1、字符串储存,这个有好多方法,可以用资源文件、Xml甚至普通文本文件都可以
2、怎么在程序中赋值,这才是麻烦的问题。一般都是在设计界面中给控件设定名称的,而设计界面中只能赋简单的字符串,显然不符合要求。而完全通过在程序中写代码赋值虽然可行,但是少数几个控件可以,成百上千个控件都要这样干就成问题了。我的想法是,在设计界面中设定名称的控件,通过递归遍历所有控件,根据ID或者其他可行的方式查找资源文件里的字符串,并赋值。而对于写代码赋值的,比如动态创建的控件名称、异常信息等等,直接改成从资源文件读取就可以。
具体实施起来可能不止这么简单,最近也需要实现全球化支持,等研究了再来讨论。