先暂时记录下,界面以后有时间做,做这个主要是因为有一份资源文件,对应英,简,繁。现在的情况就是英文最全,然后简体次之,繁体最不全,因为直接从英文翻译到繁体错误几率大,所以要求先从简翻译到繁。其实这种网上工具也有,用了一下感觉太复杂,不好操作,要么全部给翻译了(这也就没有意义了),于是自己写一个,先做完再说。
资源文件需要处理的数据主要有几种形式.
<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); } }
主要实现就是如上,当然后面要加上一些界面,还有一些辅助处理的类,以便处理更多的情况。