先暫時記錄下,介面以後有時間做,做這個主要是因為有一份資源檔,對應英,簡,繁。現在的情況就是英文最全,然後簡體次之,繁體最不全,因為直接從英文翻譯到繁體錯誤幾率大,所以要求先從簡翻譯到繁。其實這種網上工具也有,用了一下感覺太複雜,不好操作,要麼全部給翻譯了(這也就沒有意義了),於是自己寫一個,先做完再說。
資源檔需要處理的資料主要有幾種形式.
<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); } }
主要實現就是如上,當然後面要加上一些介面,還有一些輔助處理的類,以便處理更多的情況。