多语言开发

     项目推广到其它国家的时候要做本地化。.net提供了本地化和国际化的操作,但有些不便利。最近在做项目的时候,遇到了资源国际化的问题。网上有不少的介绍,但很多都是介绍.net是怎么处理的或者如何用.net来处理。后来根据.net里面的设计思想进行了改进,很好的解决了问题。大致介绍一下。

     在.net中,提供了对资源文件供操作(较早的是resouce格式,现都是resx格式)。resx格式的资源简化了开发,但实际是与操作resource一样的(有兴趣可看下.net对resx操作的大致情况,就会知道两者间的联系)。多语言的资源根据不同的语言进行了命名,resourcefile.language.resx。根据不同的语言加载对应的资源文件进行解析(它提供了culture类)。

     借鉴这一思想,增加xml作为资源存储文件,最终发布的时候可将xml做处理,如加密等。文件的命名同上filename.language.xml,设置culture,根据不同的culture加载不同的xml资源文件,然后进行解析。

     在项目中已经使用了,这里贴一下代码(C#):

     访问接口:

ContractedBlock.gif ExpandedBlockStart.gif ResourceManager
 1ExpandedBlockStart.gifContractedBlock.gifnamespace MultiLanguage{
 2        static UnKnowInforManage m_unKnowMan = null;
 3        public string GetItemValueOfUnKnownXml(string xmlFile, string item)
 4ExpandedSubBlockStart.gifContractedSubBlock.gif        {
 5            if (!isLastProccessedXml(xmlFile))
 6                recordLastProccessdXml(xmlFile);
 7
 8            if (m_unKnowMan == null)
 9                m_unKnowMan = new UnKnowInforManage(xmlFile);
10
11            return m_unKnowMan.GetItem(item);
12        }

13
14ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
15        /// 纪录上一次处理的信息
16        /// </summary>
17        /// <param name="xmlFile"></param>

18        void recordLastProccessdXml(string xmlFile)
19ExpandedSubBlockStart.gifContractedSubBlock.gif        {
20            m_lastUnKnowXml = xmlFile;
21            m_unKnowMan = new UnKnowInforManage(xmlFile);
22        }

23
24ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
25        /// 本次要处理的文件是不是已经处理过
26        /// </summary>
27        /// <param name="xmlFile"></param>
28        /// <returns></returns>

29        bool isLastProccessedXml(string xmlFile)
30ExpandedSubBlockStart.gifContractedSubBlock.gif        {
31            return string.Compare(m_lastUnKnowXml, xmlFile, true== 0;
32        }

33
34        string m_unKnowXml;
35        string m_lastUnKnowXml;//上一次使用的未知xml,用于与下一次要访问的xml文件比较,如果相同,不用进行解析
36        public void SetDefaultUnKnowXmlPath(string xmlFile)
37ExpandedSubBlockStart.gifContractedSubBlock.gif        {
38            xmlFile=FormatXmlFile( xmlFile);
39            m_unKnowXml =xmlFile;
40            recordLastProccessdXml(xmlFile);
41        }

42
43        bool isSetUnKnowXml()
44ExpandedSubBlockStart.gifContractedSubBlock.gif        {
45            return !string.IsNullOrEmpty(m_unKnowXml);
46        }

47
48        public string GetItemValueOfUnKnownXml(string item)
49ExpandedSubBlockStart.gifContractedSubBlock.gif        {
50            if (!isSetUnKnowXml())
51                throw (new Exception("没有设置要解析的xml文件,先调用SetDefaultUnKnowXmlPath(string xmlFile)设置文件路径"));
52            return GetItemValueOfUnKnownXml(m_unKnowXml, item);
53        }

54
55ExpandedSubBlockStart.gifContractedSubBlock.gif        string FormatXmlFile(string xmlFileName) {
56            System.Text.RegularExpressions.Regex regx = new System.Text.RegularExpressions.Regex(@".*(\.xml)$");
57            if (regx.IsMatch(xmlFileName))
58                return xmlFileName;
59           
60           return string.Format("{0}Resources\\{2}.{1}.xml", System.AppDomain.CurrentDomain.BaseDirectory, _culture.Name,xmlFileName);
61        }

62}

     资源操作类,对资源文件进行解析:

 

ContractedBlock.gif ExpandedBlockStart.gif ResourceParse
 1ExpandedBlockStart.gifContractedBlock.gif    /**//// <summary>
 2    /// 未知文件的处理(不知道里面的节点信息),但必需是xml格式
 3    /// 暂不能处理同名不同根的节点,同名不同根的节点须传入完整路径的节点
 4    /// author:胡艳波
 5    /// time:2008/10/15
 6    /// </summary>

 7    public class UnKnowInforManage
 8ExpandedBlockStart.gifContractedBlock.gif    {
 9        string m_file,m_culture;
10        static Dictionary<stringstring> ItemsZh=null,ItemsEn=null;
11
12ExpandedSubBlockStart.gifContractedSubBlock.gif        public UnKnowInforManage(string xmlFile) {
13            m_file = xmlFile;
14            m_culture = CommonUtil.getCultureNameByFile(xmlFile);
15        }

16
17ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
18        /// 可传入带父级的节点,即完整路径,或者直接传入节点名称
19        /// 传入节点即可,不传入父级及以上的节点,如root/a/b/c,取c的值只需传入c
20        /// 暂不能处理同名不同根的节点,同名不同根的节点须传入完整路径的节点
21        /// </summary>
22        /// <param name="item"></param>
23        /// <returns></returns>

24ExpandedSubBlockStart.gifContractedSubBlock.gif        public string GetItem(string item) {
25            string result=string.Empty;
26            if (string.Compare(m_culture, "zh-CN"true== 0)
27ExpandedSubBlockStart.gifContractedSubBlock.gif            {
28                if (ItemsZh == null)
29ExpandedSubBlockStart.gifContractedSubBlock.gif                {
30                    UnKnowInfor infor = new UnKnowInfor(m_file);
31                    ItemsZh = infor.GetItems();
32                }

33                result = getValue(ItemsZh, item);
34            }

35
36            else
37ExpandedSubBlockStart.gifContractedSubBlock.gif            {
38                if (string.Compare(m_culture, "en-US"true== 0)
39ExpandedSubBlockStart.gifContractedSubBlock.gif                {
40                    if (ItemsEn == null)
41ExpandedSubBlockStart.gifContractedSubBlock.gif                    {
42                        UnKnowInfor infor = new UnKnowInfor(m_file);
43                        ItemsEn = infor.GetItems();
44                    }

45                    result = getValue(ItemsEn, item);
46                }

47
48ExpandedSubBlockStart.gifContractedSubBlock.gif                else {
49                    UnKnowInfor infor = new UnKnowInfor(m_file);
50                    result = getValue(infor.GetItems(),item);
51                }

52            }

53            return result;
54        }

55
56ExpandedSubBlockStart.gifContractedSubBlock.gif        /**//// <summary>
57        /// 使用dictionary处理的原因:为处理不确定层次及节点信息的xml,支持使用完整路径和只提供节点名称的方式
58        /// </summary>
59        /// <param name="dic"></param>
60        /// <param name="key"></param>
61        /// <returns></returns>

62ExpandedSubBlockStart.gifContractedSubBlock.gif        string getValue(Dictionary<string,string> dic,string key) {
63            string result;
64            //是否是带父级的节点
65            if (key.IndexOf("/">= 0)
66ExpandedSubBlockStart.gifContractedSubBlock.gif            {
67                UnKnowInfor infor = new UnKnowInfor(m_file);
68                result = infor.GetItemValue(key);
69            }

70            else
71                dic.TryGetValue(key, out result);
72            return result;
73        }

74    }

    通过ResouceManger对象进行访问,先设置文件路径。为简化操作,在访问的时候,提供文件的filename,由程序根据当前的语言文化形成完整的文件路径。如传入filename,假设当前是en-us,最终形成的解析文件就是appdomain/Resources/filename.en-us.xml,如果是简体中文,要解析的就是appdomain/Resources/filename.zh-CN.xml。

    利用这一思想,可很方便进行修改。但缺点就是不能对图片等文件隐藏,只能纪录文本信息,这也是由xml特性决定的。利用resx则可以对图片、声音等处理,在编译的时候设置embed。resx+xml很好的解决了这一问题。其它语言开发,也可以采用这一思想。

ps:当时做多语言开发的时候,很自然的想到已经有不少方案了,于是上网一搜,太多太多,但都不适合。后来索性好好的看看.net是怎么处理的,毕竟ms这方面已经做了不少工作,看看它的处理。后来终于搞定。


转载于:https://www.cnblogs.com/huankfy/articles/1343824.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值