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