Copy From
陈迪臣
.Net
中两个比较重要的命名空间System.Globalization和System.Resources提供多语言版本的很好解决方案。在这个命名空间中你可以使用手工或者自动的方式来实现你的多语言版本。如果是手工的话,在工程中自己添加一个资源文件或者借助其它工作来生成资源文件,然后通过ResourceManager来读取就可以。在VS2003中,你不用写任何代码也能实现多语言界面的体现。和没有考虑多语言版本之前一样,按照单语言版本来画你的窗口和自定义控件,完成以后把窗口或者自定义控件的Language属性改为你想要转变的一种语言类型。然后修改你的文字显示就可以。怎么样在两个语言版本之间转换呢?你只要改变当前线程的特殊区域语言标记就可以。如转换成英文:System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("en"),但是在程序中的文字,比如显示给用户的消息。如何不同版本之间改变呢?除了使用资源文件外,也可以通过其它配置文件来完成。下面我将重点描述通过XML配置文件来描述你的多语言版本文字描述。 publicclass DataMsg {
// Xml资源文件列表
privatestatic Hashtable _ReXmlDocs;
//根节点
privatestaticreadonly string ROOT_PATH = "Msg/";
#region internal 方法...
internalstaticvoid EnsureResources(object pClassObj) {
EnsureResources(pClassObj.GetType().FullName);
}
internalstaticvoid EnsureResources(string pResxXmlName) {
if(_ReXmlDocs == null) {
_ReXmlDocs = new Hashtable();
}
try {
string filePath = AppDomain.CurrentDomain.BaseDirectory + pResxXmlName +".xml";
bool b = System.IO.File.Exists(filePath);
if(b && !_ReXmlDocs.ContainsKey(pResxXmlName)) {
XmlDocument doc = new XmlDocument();
doc.Load( filePath );
_ReXmlDocs.Add(pResxXmlName, doc);
}
else{
UP.Utils.TraceEx.Write("文件" + filePath + "不存在." );
}
}
catch(Exception e){
UP.Utils.TraceEx.Write("获取设置的XML资源文件时出错." + e.Message);
}
}
#endregion internal 方法...
#region Public Static 方法...
// 返回指定的 <see cref="String"/>资源的值
publicstaticstring GetString(object pClassObj, string name,paramsstring[] pParamValues) {
EnsureResources(pClassObj);
XmlDocument res = _ReXmlDocs[pClassObj.GetType().FullName] as XmlDocument;
if(res!=null)
return getMsgString(res,pClassObj,name,pParamValues);
returnstring.Empty;
}
publicstaticvoid ReleaseAllResources() {
if(_ReXmlDocs!=null) {
_ReXmlDocs.Clear();
}
}
#endregion Public Static 方法...
#region Private 静态方法处理...
//获取指定名称的描述
private staticstring getMsgString(XmlDocument pXmlDoc,object pClassObj,string pMsgName,paramsstring[] pParamValues){
CultureInfo curInfo = DesignView.CultInfo;
string msgPath = ROOT_PATH + pClassObj.GetType().FullName.Replace('.','/') ;
string msgVal = "";
XmlNode parentNode = pXmlDoc.SelectSingleNode(msgPath);
if(parentNode!=null){
foreach(XmlNode node in parentNode.ChildNodes){
if(node.Attributes["Name"]!=null && node.Attributes["Name"].Value.ToUpper() == pMsgName){
foreach(XmlNode dataNode in node.ChildNodes){
if(dataNode.Name.ToUpper()==curInfo.Name.ToUpper()){
string txt = dataNode.InnerText;
//去掉回车和换行符
txt = Regex.Replace(txt,@"[\r\n]+"," ",RegexOptions.IgnoreCase);
//去掉空格符
txt = Regex.Replace(txt,@"[\t]+"," ",RegexOptions.IgnoreCase);
if(pParamValues!=null && pParamValues.Length > 0){
for(int i = 0 ; i< pParamValues.Length ;i++){
txt = txt.Replace("{" + i + "}", pParamValues[i].ToString());
}
}
msgVal = txt;
break;
}
}
break;
}
}
}
if(msgVal == ""){
//如果没有配置那么从代码中读取对应的常数值
System.Type type = pClassObj.GetType();
System.Reflection.FieldInfo info = type.GetField(pMsgName);
if(info!=null){
object val = info.GetValue(pClassObj);
if(val!=null){
msgVal = val.ToString();
}
}
}
return msgVal;
}
#endregion Private 静态方法处理...
}
XMl的配置文件如下:
<?xmlversion="1.0"encoding="utf-8"?>
<Msg>
<MyControl>
<TextBox>
<DataName="MSG_CHECK_LENGTH">
<en>{0}very good!</en>
<zh-CN>{0}非常好!</zh-CN>
</Data>
</ TextBox >
</MyControl>
</Msg>
字父{0}为参数,0表示第一个参数。
在代码中只要这样调用就可以:
publicreadonlystring MSG_CHECK_LENGTH = "{0}非常好!";
string str = MultiLanguage.MsgResource.GetString(this," MSG_CHECK_LENGTH ",Name);
如果MSG_CHECK_LENGTH在XML文件中没有配置,那么就读取常量的值。
通过这个类,再结合上面提到的自动化处理方法,实现多语言版本将是非常简单的一件事。