Legato Systems MC文件的翻译思路

24 篇文章 0 订阅

Legato Systems MC文件的翻译

Legato Systems https://legato.io/
An open source Linux-based embedded platform designed to simplify connected IoT application development
一个基于Linux的开源嵌入式平台,旨在简化联网物联网应用程序的开发

这个系统一般是制作Linux驱动用的,导出的文件是*.mc文件

这个文件格式比较特殊 还有一定的容错,并不能被翻译软件 Trados直接支持,本文给出一个*.mc*.xml的思路,通过转换为XML进行翻译,翻译后再写回MC

首先MC的文件结构

MC文件分为文件头和文件体两部分,文件本身设计上支持多语言,采用Unicode或UTF-8编码

;//
;// Copyright (C) 1994 - 2004 Legato Systems, Inc.
;// All rights reserved.
;//
;//
;//
;//
MessageIdTypedef = NTSTATUS
;// SeverityNames = (name=number[:name])
;// FacilityNames = (name=number[:name])
;// LanguageNames = (name=number:filename)
;//LanguageNames = (French=2:MSG00002)

SeverityNames=(Success=0x0:SUCCESS
           Informational=0x1:INFO
           Warning=0x2:WARNING
           Severe=0x3:SEVERE
              )

LanguageNames = (
	English=1033:MSG1033
	Chinese=2052:MSG2052
	French=1036:MSG1036
	Korean=1042:MSG1042
	Japanese=1041:MSG1041
	German=1031:MSG1031
	Russian=1049:MSG1049
	Spanish=2058:MSG2058
	Italian=1040:MSG1040
	Portuguese=1046:MSG1046
	)

FacilityNames=(
    System=0x0FF
	Exception=0xFFE
    Application=0x000
    General=0x100
    Framework=0x200
    Resource=0x300
    Module=0x400
    AtmosFsDriver=0x0FFD:FAV_ATMOS_FS_DRIVER
    ) 

其中;//开头的行是注释行
主体采用类似INI的ID=内容格式

SeverityNames 是一段无关的内容不需要翻译
LanguageNames 是语言名的预定义
FacilityNames 是此文件相关的具体说明

总之文件头是不需要翻译的
我这批MC文件都是来自一个系统,格式统一
因此我设置
public const int preservedHeaderCount = 42;
在循环中直接跳过

while (sr.Peek() >= 0)
{
    linecounter++;
    line = sr.ReadLine();

    if (linecounter > preservedHeaderCount)
    {
    ...
    }
}

文件体部分

MessageId=0
Severity=Success
Facility=Application
SymbolicName=MSG_NO_ERROR
Language=English
No Error
.

;  // this first set of messages are the Event Categories

MessageId=
Severity=Informational
SymbolicName=MSG_TCP_IP_BUF_SIZE_REDUCED_BY_TIMEOUT
Language=English
The TcpIp Buffer size was reduced due to a timeout. Was %1 is now %2.

Description
The Tcp Ip buffer size was automatically reduced due to a communications timeout. 

Resolution
None required.
.

MessageId=
Severity=Success
SymbolicName=MSG_CAT_SERVER
Language=English
Server
.

文件体由多个统一规格的小单元组成
每个单元包含六个部分

  1. MessageId=
  2. Facility=
    可选
  3. Severity=
  4. SymbolicName=
    此为唯一值
  5. Language=
    原文的值为English翻译后的应设置为文件头中定义的语言名 例如Russian
  6. 待翻译的正文部分
    正文部分存在多行情况,需要保留换行符
  7. .
    独自成一行的一个句点.
    标志单元结束
    第六个部分是可容错的,有的时候没有这个部分

可能存在注释行
;//开头的行是注释行

设计一个类通过泛型方式存取这种单元

public class item
{
    public string MessageId { get; set; }
    public string Severity { get; set; }
    public string Facility { get; set; } //Optional
    public string SymbolicName { get; set; }
    public LanguageNames Language { get; set; }
    public string Text { get; set; }
    public bool isComments { get; set; }
}

MC转XML

MC转XML采用从上到下的读写方式

逻辑图:

Created with Raphaël 2.2.0 开始 读一行 确认到达preservedHeaderCount? 检测MessageId行 初始化最小单元 检测是否Facility行 读取Facility行 读取Symbolic行 读取Language行 连续读取到.行 最小单元赋值 是否最后一行 结束 yes no yes no yes no yes no

代码示例

StreamReader sr = new StreamReader(file, Encoding.Unicode, true);
string line = string.Empty;
bool isStart = false;
bool isFirstLine = false;
string text = string.Empty;

Match mMessageId = null;
Match mSeverity = null;
Match mFacility = null;
Match mSymbolicName = null;
Match mLanguage = null;

int linecounter = 0;

while (sr.Peek() >= 0)
{
    linecounter++;
    line = sr.ReadLine();

    if (linecounter > preservedHeaderCount)
    {
        if (regMessageId.IsMatch(line) && isStart == false)
        {
            Console.Write(".");

            isStart = true;
            item i = new item();
            i.isComments = false;

            mMessageId = regMessageId.Match(line);
            i.MessageId = mMessageId.Groups["value"].Value;
            line = sr.ReadLine();

            mSeverity = regSeverity.Match(line);
            i.Severity = mSeverity.Groups["value"].Value;
            line = sr.ReadLine();

            if (regFacility.IsMatch(line))
            {

                mFacility = regFacility.Match(line);
                i.Facility = mFacility.Groups["value"].Value;
                line = sr.ReadLine();

                mSymbolicName = regSymbolicName.Match(line);
                i.SymbolicName = mSymbolicName.Groups["value"].Value;
                line = sr.ReadLine();

                while (line == "")
                {
                    line = sr.ReadLine();
                }

                mLanguage = regLanguage.Match(line);
                i.Language = (LanguageNames)Enum.Parse(typeof(LanguageNames), mLanguage.Groups["value"].Value);
                isFirstLine = true;

                line = sr.ReadLine();
                while (line != ".")
                {
                    if (isFirstLine)
                    {
                        text = line;
                        isFirstLine = false;
                    }
                    else
                    {
                        text = text + "\r\n" + line;
                    }
                    line = sr.ReadLine();
                }
                isFirstLine = false;
                isStart = false;
                i.Text = text;

                items.Add(i);
                text = string.Empty;
            }
            else if (regSymbolicName.IsMatch(line))
            {
                mSymbolicName = regSymbolicName.Match(line);
                i.SymbolicName = mSymbolicName.Groups["value"].Value;
                line = sr.ReadLine();

                while (line == "")
                {
                    line = sr.ReadLine();
                }

                mLanguage = regLanguage.Match(line);
                i.Language = (LanguageNames)Enum.Parse(typeof(LanguageNames), mLanguage.Groups["value"].Value);
                isFirstLine = true;

                line = sr.ReadLine();
                while (line != ".")
                {
                    if (isFirstLine)
                    {
                        text = line;
                        isFirstLine = false;
                    }
                    else
                    {
                        text = text + "\r\n" + line;
                    }
                    line = sr.ReadLine();
                }
                isFirstLine = false;
                isStart = false;
                i.Text = text;

                items.Add(i);
                text = string.Empty;
            }
       }
}

sr.Close();

然后输出XML,例如

  <item isComments="no">
    <Facility>Application</Facility>
    <MessageId>0</MessageId>
    <Severity>Success</Severity>
    <Language>English</Language>
    <Text SymbolicName="MSG_NO_ERROR"><![CDATA[No Error]]></Text>
  </item>
  <item isComments="yes">
    <Comment><![CDATA[;  // this first set of messages are the Event Categories]]></Comment>
  </item>
  <item isComments="no">
    <MessageId>
    </MessageId>
    <Severity>Informational</Severity>
    <Language>English</Language>
    <Text SymbolicName="MSG_TCP_IP_BUF_SIZE_REDUCED_BY_TIMEOUT"><![CDATA[The TcpIp Buffer size was reduced due to a timeout. Was %1 is now %2.

Description
The Tcp Ip buffer size was automatically reduced due to a communications timeout. 

Resolution
None required.]]></Text>
  </item>
  <item isComments="no">
    <MessageId>
    </MessageId>
    <Severity>Success</Severity>
    <Language>English</Language>
    <Text SymbolicName="MSG_CAT_SERVER"><![CDATA[Server]]></Text>
  </item>

方法如下

StreamWriter sw = new StreamWriter(file + ".XML", false, Encoding.Unicode);
XmlDocument doc = new XmlDocument();
XmlDeclaration dec = doc.CreateXmlDeclaration("1.0", "Unicode", string.Empty);
doc.AppendChild(dec);

XmlElement root = doc.CreateElement("resources");

for (int i = 0; i < items.Count; i++)
{
    if (items[i].isComments)
    {
        XmlElement elem_item = doc.CreateElement("item");

        XmlAttribute AttComments = doc.CreateAttribute("isComments");
        AttComments.Value = "yes";
        elem_item.Attributes.Append(AttComments);

        XmlElement elem_Text = doc.CreateElement("Comment");
        XmlCDataSection cdata = doc.CreateCDataSection(items[i].Text);
        elem_Text.AppendChild(cdata);

        elem_item.AppendChild(elem_Text);
        root.AppendChild(elem_item);
    }
    else
    {
        XmlElement elem_item = doc.CreateElement("item");

        XmlAttribute AttComments = doc.CreateAttribute("isComments");
        AttComments.Value = "no";
        elem_item.Attributes.Append(AttComments);

        XmlElement elem_MessageId = doc.CreateElement("MessageId");
        elem_MessageId.InnerText = items[i].MessageId;

        XmlElement elem_Severity = doc.CreateElement("Severity");
        elem_Severity.InnerText = items[i].Severity;

        if (items[i].Facility != null)
        {
            XmlElement elem_Facility = doc.CreateElement("Facility");
            elem_Facility.InnerText = items[i].Facility;
            elem_item.AppendChild(elem_Facility);
        }

        //XmlElement elem_SymbolicName = doc.CreateElement("SymbolicName");
        //elem_SymbolicName.InnerText = items[i].SymbolicName;
        XmlElement elem_Language = doc.CreateElement("Language");
        elem_Language.InnerText = Enum.GetName(typeof(LanguageNames), items[i].Language);
        XmlElement elem_Text = doc.CreateElement("Text");
        XmlCDataSection cdata = doc.CreateCDataSection(items[i].Text);
        elem_Text.AppendChild(cdata);

        XmlAttribute attSymbolicName = doc.CreateAttribute("SymbolicName");
        attSymbolicName.Value = items[i].SymbolicName;
        elem_Text.Attributes.Append(attSymbolicName);


        elem_item.AppendChild(elem_MessageId);


        elem_item.AppendChild(elem_Severity);

        //elem_item.AppendChild(elem_SymbolicName);
        elem_item.AppendChild(elem_Language);
        elem_item.AppendChild(elem_Text);

        root.AppendChild(elem_item);
    }
}
doc.AppendChild(root);
doc.Save(sw);
sw.Close();

最后翻译完成xml转回MC

StreamReader sr = new StreamReader(file, Encoding.Unicode, true);
StreamWriter sw = new StreamWriter(file+(".")+Enum.GetName(typeof(LanguageNames), language), false, Encoding.Unicode);

XmlDocument doc = new XmlDocument();
doc.Load(sr);

XmlElement root = doc.DocumentElement;
XmlNodeList itemsNode = root.SelectNodes("item");

XmlNode ndMessageId=null;
XmlNode ndSeverity=null;
XmlNode ndFacility=null;
//XmlNode ndSymbolicName=null;
XmlNode ndLanguage=null;
XmlNode ndText=null;
XmlCDataSection cdata=null;

foreach(XmlNode itemNode in itemsNode)
{
    if (itemNode.Attributes["isComments"].Value == "no")
    {
        ndMessageId = itemNode.SelectSingleNode("MessageId");

        sw.WriteLine(string.Format("MessageId={0}", ndMessageId.InnerText));


        ndSeverity = itemNode.SelectSingleNode("Severity");
        sw.WriteLine(string.Format("Severity={0}", ndSeverity.InnerText));

        ndFacility = itemNode.SelectSingleNode("Facility");
        if (ndFacility != null)
        {
            sw.WriteLine(string.Format("Facility={0}", ndFacility.InnerText));
        }

        ndText = itemNode.SelectSingleNode("Text");
        //ndSymbolicName = itemNode.SelectSingleNode("SymbolicName");
        //sw.WriteLine(string.Format("SymbolicName={0}", ndSymbolicName.InnerText));
        sw.WriteLine(string.Format("SymbolicName={0}", ndText.Attributes["SymbolicName"].Value));

        sw.WriteLine(string.Format("Language={0}", Enum.GetName(typeof(LanguageNames), language)));

        sw.WriteLine(ndText.InnerText);

        sw.WriteLine(".");
        sw.WriteLine("");
    }
    else
    {
        ndText = itemNode.SelectSingleNode("Comment");
        sw.WriteLine(ndText.InnerText);
    }
}

sr.Close();
sw.Close();

源码
https://github.com/Dark-20001/Legato-MC2XML

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值