C#资源文件比对与自动翻译。

先暂时记录下,界面以后有时间做,做这个主要是因为有一份资源文件,对应英,简,繁。现在的情况就是英文最全,然后简体次之,繁体最不全,因为直接从英文翻译到繁体错误几率大,所以要求先从简翻译到繁。其实这种网上工具也有,用了一下感觉太复杂,不好操作,要么全部给翻译了(这也就没有意义了),于是自己写一个,先做完再说。

 

资源文件需要处理的数据主要有几种形式.

    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
        <value>[base64 mime encoded serialized .NET Framework object]</value>
    </data>
    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
        <comment>This is a comment</comment>
    </data>
  <data name="title" xml:space="preserve">
    <value>Title</value>
  </data>
  <data name="titleComment" xml:space="preserve">
    <value>Title</value>
    <comment>comment</comment>
  </data>

定义如下一个类,主要描述这几种形式的公共处理方式。

   public class ResxData : ICloneable
    {
        public const string str_data = "data";
        public const string str_name = "name";
        public const string str_value = "value";
        public const string str_comment = "comment";
        public string Name { get; set; }
        public string Value { get; set; }
        public string Comment { get; set; }

        public virtual XmlElement InsertElement(XmlDocument doc)
        {
            XmlElement dataElement = doc.CreateElement(str_data);
            dataElement.SetAttribute(str_name, Name);
            if (!string.IsNullOrEmpty(Value))
            {
                XmlElement valueElement = doc.CreateElement(str_value);
                valueElement.InnerText = Value;
                dataElement.AppendChild(valueElement);
            }
            if (!string.IsNullOrEmpty(Comment))
            {
                XmlElement commentElement = doc.CreateElement(str_comment);
                commentElement.InnerText = Comment;
                dataElement.AppendChild(commentElement);
            }
            return dataElement;
        }
        public XmlElement InsertElement(XmlDocument doc, bool bAdd)
        {
            var element = InsertElement(doc);
            if (bAdd)
                doc.DocumentElement.AppendChild(element);
            return element;
        }

        public virtual object Clone()
        {
            ResxData data = new ResxData();
            data.Name = this.Name;
            data.Value = this.Value;
            data.Comment = this.Comment;
            return data;
        }
    }

因为我要做的只是针对后面加个属性的那种资源文件,没有那种对应type的那种,所以我暂时只做一个扩展。

    public class ResxDataSpace : ResxData
    {
        public const string str_space = "space";
        public const string str_nameSpace = "xml:space";
        public string Space { get; set; }
        public override XmlElement InsertElement(XmlDocument doc)
        {
            var element = base.InsertElement(doc);
            element.SetAttribute(str_nameSpace, Space);
            return element;
        }
        public override object Clone()
        {
            ResxData data = base.Clone() as ResxData;
            if (data != null)
            {
                ResxDataSpace space = GetData(data, Space);
                return space;
            }
            return data;
        }

        public static ResxDataSpace GetData(ResxData data, string spaceValue)
        {
            ResxDataSpace space = new ResxDataSpace();
            space.Name = data.Name;
            space.Value = data.Value;
            space.Comment = data.Comment;
            space.Space = spaceValue;
            return space;
        }
    }

然后是对应文件的处理类。

    public class ReadResxData
    {
        public const string str_root = "root";
        public const string str_sperate = "/";
        private string filePath;
        public string FilePath
        {
            get
            {
                return filePath;
            }
            set
            {
                filePath = value;
                string fileName = Path.GetFileName(filePath);
                string[] sp = fileName.Split('.');
                if (sp.Length > 1)
                {
                    if (sp.Length > 2)
                    {
                        Mark = sp[1];
                    }
                    else
                    {
                        Mark = "en-US";
                    }
                }
            }
        }
        public string Mark { get; set; }

        public List<ResxData> GetData()
        {
            System.Xml.XmlDocument xmlDoc = new System.Xml.XmlDocument();
            xmlDoc.Load(FilePath);
            XmlNodeList nodes = xmlDoc.SelectNodes(str_root + str_sperate + ResxData.str_data);
            List<ResxData> datas = new List<ResxData>();
            foreach (XmlNode node in nodes)
            {
                ResxData resxData = new ResxData();
                resxData.Name = node.Attributes[ResxData.str_name].InnerText;
                if (node.ChildNodes.Count > 0)
                {
                    XmlNode valueNode = node.SelectSingleNode(ResxData.str_value);
                    XmlNode commentNode = node.SelectSingleNode(ResxData.str_comment);
                    if (valueNode != null)
                    {
                        resxData.Value = valueNode.InnerText;
                    }
                    if (commentNode != null)
                    {
                        resxData.Comment = valueNode.InnerText;
                    }
                }
                var spaceAttributes = node.Attributes[ResxDataSpace.str_nameSpace];
                if (spaceAttributes != null)
                {
                    ResxDataSpace space = ResxDataSpace.GetData(resxData, spaceAttributes.Value);
                    datas.Add(space);
                }
                else
                {
                    datas.Add(resxData);
                }
            }
            return datas;
        }

        public XmlDocument GetDoc()
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(FilePath);
            return doc;
        }
    }

然后就需要比对文件。

    public class CompareResxData
    {
        public ReadResxData Source { get; set; }

        public ReadResxData Des { get; set; }

        public CompareResxData()
        {
            Source = new ReadResxData();
            Des = new ReadResxData();
        }
        private string sourceFilePath;
        public string SourceFilePath
        {
            get
            {
                return sourceFilePath;
            }
            set
            {
                sourceFilePath = value;
                Source.FilePath = sourceFilePath;
            }
        }
        private string desFilePath;
        public string DesFilePaht
        {
            get
            {
                return desFilePath;
            }
            set
            {
                desFilePath = value;
                Des.FilePath = desFilePath;
            }
        }

        public List<ResxData> CompareFormT()
        {
            var souDatas = Source.GetData();
            var desDatas = Des.GetData();

            List<ResxData> results = new List<ResxData>();
            foreach (var souData in souDatas)
            {
                var result = desDatas.FirstOrDefault(p => p.Name == souData.Name);
                if (result == null || string.IsNullOrEmpty(result.Value))
                {
                    results.Add(souData);
                }
            }
            return results;
        }

    }

翻译比较简单,主要是参考http://www.cnblogs.com/gsyifan/archive/2011/11/14/microsoft_Translate_api.html引用service实现。

    public class TranslateLanguage
    {
        public const string appID = "82A171654F003025C2524F9AFDA1951A6D116C89";
        private static LanguageService.LanguageServiceClient client = new LanguageService.LanguageServiceClient();
        public static string Translate(string value, string from, string to)
        {
            string result = client.Translate(appID, value, from, to, "text/html", "general");
            return result;
        }

    }

最后是测试功能如下,实现的结果还是比较可以。

    public class Test
    {
        public void t1()
        {
            CompareResxData c = new CompareResxData();
            c.SourceFilePath = @"D:\WorkSpace\resx\Strings.zh-CHS.resx";
            c.DesFilePaht = @"D:\WorkSpace\resx\Strings.zh-CHT.resx";
            var tt = c.CompareFormT();
            List<ResxData> ts = new List<ResxData>();
            object obj = new object();
            Parallel.For(0, tt.Count, (i) =>
            {
                var s = tt[i];
                string result = TranslateLanguage.Translate(s.Value, c.Source.Mark, c.Des.Mark);
                ResxData data = s.Clone() as ResxData;
                s.Value = result;
                lock (obj)
                {
                    ts.Add(s);
                }
            });
            var doc = c.Des.GetDoc();
            foreach (var s in ts)
            {
                s.InsertElement(doc, true);
            }
            doc.Save(c.Des.FilePath);
        }
    }

主要实现就是如上,当然后面要加上一些界面,还有一些辅助处理的类,以便处理更多的情况。

原文地址:https://www.cnblogs.com/zhouxin/p/2442915.html