Office関連

MemsourceのバイリンガルMXLIFFファイルから情報を抽出するWordマクロ

近年翻訳業界では「Trados」や「memoQ」といった、“翻訳支援ツール”(Computer-Assisted Translation(CAT)ツール)が流行っています。

翻訳支援ツール(CATツール)とは?

最初に断っておくと、私自身は英語が苦手で翻訳なんかもできないので、「翻訳支援ツールってなに?」と聞かれても上手く答えられる自信はありません。

なので詳しくは下記Webページをご参照いただければと思います。

Memsourceとは?

Memsourceは、2010年にチェコで生まれた新しいCATツールです。

上記公式サイトから概要を引用すると、

Memsourceはどなたにでも翻訳ソリューションを提供できます。ご自身で翻訳しても、又は翻訳をアウトソースしても、Memsourceを使えば翻訳プロセスはより効率的になります。世界最大規模の翻訳会社や企業の翻訳部門の方々がMemsourceを利用し翻訳の生産性を最適化しています。

Memsource Webエディター は、完全にウェブ型の翻訳環境です。ウェブ型に代わるデスクトップ型のMemsource エディター は、無料でダウンロード可能です。どちらをお使いいただいても、Memsource Cloud 内の翻訳メモリとタームべースにシームレスに接続されます。Memsourceを好んで利用する世界中で数万人いる翻訳者の仲間入りをしませんか

強力な分析機能を使えば、リアルタイムで翻訳プロセスを分析し、プロジェクト全体を見渡すことができます。翻訳量、ファイルタイプ、コスト計算、ベンダー毎の翻訳品質、又は機械翻訳の利用状況を分析できます。Memsource Cloudでデータを直接調べ、そしてデータをエクスポート、又はMemsourceAPIを介して社内システムとMemsourceを統合できます。

Memsource Cloud は、ウェブ型/デスクトップ型の翻訳エディタを備え、翻訳メモリや用語ベースの管理、機械翻訳の搭載、共同作業を実現する画期的な翻訳プラットフォームです。翻訳バイヤー、翻訳会社、翻訳者など翻訳業務に関わる全ての人の作業を大幅に効率化します。

のようになっています。
要するに、プロジェクト管理から翻訳メモリ管理、エディターを使っての翻訳まで、一気通貫でいろいろできるクラウドサービス、と認識しておけば良さそうです。

MXLIFFファイルとは?

MXLIFFファイルの説明をする前に、「XLIFFファイル」の説明をしておきます。

XLIFF (XML Localization Interchange File Format) はソフトウェアや文書の国際化、翻訳のために開発された XMLベースのファイル形式である。XLIFF は2002年に OASIS において制定された。現在のバージョンは2008年1月22日制定の 1.2 である。企業などの組織内における翻訳作業を想定し、その支援となるよう各種の要素や属性が制定されている。

XLIFF – Wikipedia より

要するに、CATツール等で使う共通のファイルフォーマットですね。
XLIFF形式でエクスポートしておけば、ツール間でやり取りできてとっても便利!、というわけです。

そしてMXLIFFファイルとは、XLIFF準拠のMemsource専用フォーマット(Memsource XLIFF)です。
(と、私は認識しているのですが、もしかしたら間違っているかもしれません…)

今回は、このMXLIFFファイルから、原文や訳文、コメント情報等を抜き出すWordマクロを作ってしまおう、という話です。
(ここまで前置き。長かった…。)

バイリンガルMXLIFFファイルから情報を抽出するWordマクロ

先述の通り、MXLIFFファイルは実質XMLなので、MSXMLを使えば簡単にVBAから扱うことができます。

Option Explicit

Public Sub GetMxliffInfo()
'MemsourceのバイリンガルMXLIFFファイルから原文・訳文等の情報抽出
  Dim d As Object
  Dim colTransUnit As Object
  Dim elmTransUnit As Object
  Dim elmSource As Object
  Dim elmTarget As Object
  Dim elmComment As Object
  Dim elmFile As Object
  Dim doc As Word.Document
  Dim tbl As Word.Table
  Dim r As Word.Row
  Dim fn As String
  Dim str As String
  Dim idx As Long: idx = 0
  
  'ファイル選択
  With Application.FileDialog(msoFileDialogFilePicker)
    .AllowMultiSelect = False
    .Title = "バイリンガルMXLIFFファイルを選択してください。"
    .Filters.Add "バイリンガルMXLIFFファイル", "*.mxliff"
    .FilterIndex = 2
    If .Show = 0 Then Exit Sub
    fn = .SelectedItems.Item(1)
  End With
  
  Set d = CreateObject("MSXML2.DOMDocument")
  d.async = False
  If d.Load(fn) = True Then
    '情報出力用文書作成
    Set doc = Application.Documents.Add
    With doc.PageSetup
      .TopMargin = MillimetersToPoints(10)
      .BottomMargin = MillimetersToPoints(10)
      .LeftMargin = MillimetersToPoints(10)
      .RightMargin = MillimetersToPoints(10)
      .Orientation = wdOrientLandscape
    End With
    
    'ジョブ情報
    If d.getElementsByTagName("file").Length > 0 Then
      Set elmFile = d.getElementsByTagName("file").Item(0)
      str = "<ジョブ情報>"
      '元ファイル
      If HasSpecificAttribute(elmFile, "original") = True Then
        str = str & vbNewLine & "元ファイル:" & elmFile.Attributes.getNamedItem("original").Text
      End If
      '翻訳元言語
      If HasSpecificAttribute(elmFile, "source-language") = True Then
        str = str & vbNewLine & "翻訳元言語:" & elmFile.Attributes.getNamedItem("source-language").Text
      End If
      '翻訳先言語
      If HasSpecificAttribute(elmFile, "target-language") = True Then
        str = str & vbNewLine & "翻訳先言語:" & elmFile.Attributes.getNamedItem("target-language").Text
      End If
      'ファイル形式
      If HasSpecificAttribute(elmFile, "m:file-format") = True Then
        str = str & vbNewLine & "ファイル形式:" & elmFile.Attributes.getNamedItem("m:file-format").Text
      End If
      doc.Range.InsertAfter str
    End If
    
    Set colTransUnit = d.getElementsByTagName("trans-unit")
    If colTransUnit.Length > 0 Then
      'テーブル作成
      With doc
        Set tbl = .Tables.Add(.Range(.Range.End - 1, .Range.End), 1, 9, wdWord9TableBehavior, wdAutoFitWindow)
        tbl.Cell(1, 2).Range.Text = "原文"
        tbl.Cell(1, 3).Range.Text = "訳文"
        tbl.Cell(1, 4).Range.Text = "コメント" & vbNewLine & "本文"
        tbl.Cell(1, 5).Range.Text = "コメント" & vbNewLine & "作成日時"
        tbl.Cell(1, 6).Range.Text = "コメント" & vbNewLine & "変更日時"
        tbl.Cell(1, 7).Range.Text = "翻訳ユニット" & vbNewLine & "作成日時"
        tbl.Cell(1, 8).Range.Text = "翻訳ユニット" & vbNewLine & "変更日時"
        tbl.Cell(1, 9).Range.Text = "確認"
      End With
      
      For Each elmTransUnit In colTransUnit
        idx = idx + 1
        Set r = tbl.Rows.Add
        r.Cells(1).Range.Text = idx
        
        '原文
        If HasSpecificNode(elmTransUnit, "source") = True Then
          Set elmSource = elmTransUnit.SelectSingleNode("source")
          r.Cells(2).Range.Text = elmSource.Text
        End If
        
        '訳文
        If HasSpecificNode(elmTransUnit, "target") = True Then
          Set elmTarget = elmTransUnit.SelectSingleNode("target")
          r.Cells(3).Range.Text = elmTarget.Text
        End If
        
        'コメント
        If HasSpecificNode(elmTransUnit, "m:comment") = True Then
          Set elmComment = elmTransUnit.SelectSingleNode("m:comment")
          'コメント本文
          r.Cells(4).Range.Text = elmComment.Text
          'コメント作成日時
          If HasSpecificAttribute(elmComment, "created-at") = True Then
            r.Cells(5).Range.Text = UnixTimeStampToJST(elmComment.Attributes.getNamedItem("created-at").Text)
          End If
          'コメント変更日時
          If HasSpecificAttribute(elmComment, "modified-at") = True Then
            r.Cells(6).Range.Text = UnixTimeStampToJST(elmComment.Attributes.getNamedItem("modified-at").Text)
          End If
        End If
        
        '翻訳ユニット(trans-unit)作成日時
        If HasSpecificAttribute(elmTransUnit, "m:created-at") = True Then
          r.Cells(7).Range.Text = UnixTimeStampToJST(elmTransUnit.Attributes.getNamedItem("m:created-at").Text)
        End If
        
        '翻訳ユニット(trans-unit)変更日時
        If HasSpecificAttribute(elmTransUnit, "m:modified-at") = True Then
          r.Cells(8).Range.Text = UnixTimeStampToJST(elmTransUnit.Attributes.getNamedItem("m:modified-at").Text)
        End If
        
        '確認
        If HasSpecificAttribute(elmTransUnit, "m:confirmed") = True Then
          r.Cells(9).Range.Text = elmTransUnit.Attributes.getNamedItem("m:confirmed").Text
        End If
        
        Set elmSource = Nothing
        Set elmTarget = Nothing
        Set elmComment = Nothing
      Next
      
      'テーブル整形
      With tbl
        .AutoFitBehavior wdAutoFitContent
        .Range.ParagraphFormat.WordWrap = False '英単語の途中で改行する
        With .Rows(1)
          .Range.ParagraphFormat.Alignment = wdAlignParagraphCenter
          .Cells.VerticalAlignment = wdCellAlignVerticalCenter
        End With
      End With
    End If
  End If
  
  MsgBox "処理が終了しました。", vbInformation + vbSystemModal
End Sub

Private Function HasSpecificNode(ByVal elm As Object, ByVal node_name As String) As Boolean
'指定した子要素の有無を調べる
  Dim ret As Boolean: ret = False '初期化
  If Not elm.SelectSingleNode(node_name) Is Nothing Then ret = True
  HasSpecificNode = ret
End Function

Private Function HasSpecificAttribute(ByVal elm As Object, ByVal attr_name As String) As Boolean
'指定した属性の有無を調べる
  Dim ret As Boolean: ret = False '初期化
  If Not elm.Attributes.getNamedItem(attr_name) Is Nothing Then ret = True
  HasSpecificAttribute = ret
End Function

Private Function UnixTimeStampToJST(ByVal ts As String) As Date
'UNIXタイムスタンプを日本標準時に変換
  Const TimeDiff As Double = 32400 '時差(9時間(秒))
  
  If Len(ts) > 10 Then ts = Left(ts, 10) 'ミリ秒は無視
  UnixTimeStampToJST = DateAdd("s", CDbl(ts) + TimeDiff, DateSerial(1970, 1, 1))
End Function

上記がさっそく書いたコードで、GetMxliffInfoプロシージャを実行すると、MXLIFFファイルを読み込んで、原文や訳文、コメント等の情報を新規Word文書に出力します。
(動作の仕様上、読み込むファイルが大きければ大きいほど処理に時間が掛かります。)

テーブルの書式設定をしているせいでコードが長くなっていますが、やっていることはシンプルですね。
XMLファイルから要素や属性を指定して読み込んでいるだけです。

MXLIFFファイルの要素や属性

MXLIFFファイルをテキストエディタで開くと、下記のような構造になっていました。
(下記コードは一部省略しています。)

※ 原文と訳文はEspacenetから取得したものを使用。

<?xml version='1.0' encoding='UTF-8'?>
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:m="http://www.memsource.com/mxlf/2.0" version="1.2" m:version="2.3" m:level="1">
  <file original="EN.docx" source-language="en" target-language="ja" datatype="x-undefined" m:file-format="DOC" m:task-id="*****">
    <header>
      <m:in-ctx-preview-skel>
        .....
      </m:in-ctx-preview-skel>
    </header>
    <body>
      <group id="0" m:para-id="0">
        <context-group>
          <context context-type="x-file-part">word/document.xml::body</context>
        </context-group>
        <trans-unit id="*****" xml:space="preserve" m:score="0.0" m:gross-score="0.0" m:trans-origin="null" m:confirmed="1" m:locked="false" m:para-id="0" m:created-at="1487061099818" m:created-by="*****" m:modified-at="1487119671084" m:modified-by="*****" m:level-edited="false">
          <source>The present invention conventional, and access analysis, as the analysis means in the advertising effectiveness measurement, beacon type, it is divided into a large two types of server log type, in both cases lack the accuracy and reliability, and browse to the previous time spent in the essential meaning can not be obtained because there is only the difference from when was page.{j}The present invention in order to solve the above problems, and when that has left only on the page that was first visited by simply paste the tag (javascript) to the WEB site, the residence time, such as if you move to an external site It can be acquired.{j}Attempt to solve the above problems by page tag (javascript) is provided with a function to sense that a transition.{j}The present invention performs a WEB site registration, to obtain a unique ID, subject to issuance of the tag.{j}Paste issued a tag to the WEB site, it is possible to stay time acquisition of each visitor of the relevant page. .FIELD 1</source>
          <target>従来、アクセス解析や、広告効果測定における解析手段としては、ビーコン型、サーバーログ型の大きく二種類に分かれており、どちらの場合も正確性および確実性に欠け、ひとつ前に閲覧していたページからの差分でしかないため本質的な意味での滞在時間が取得できない。{j}【解決手段】上記課題を解決するために本発明は、WEBサイトにタグ(javascript)を貼り付けるだけで最初に訪れたページだけで離脱した際や、外部サイトへ移動した場合などの滞在時間の取得が可能。{j}タグ(javascript)にページが遷移したことを感知する機能を持たせることによって上記課題の解決を図る。{j}本発明はWEBサイト登録を行い、ユニークなIDを取得し、タグの発行を受ける。{j}発行されたタグをWEBサイトに貼り付け、該当ページの訪問者ごとの滞在時間取得が可能になる。図1</target>
          <alt-trans origin="machine-trans">
            <target />
          </alt-trans>
          <alt-trans origin="memsource-tm">
            <target />
          </alt-trans>
          <m:comment created-at="1487118123756" created-by="*****" modified-at="1487118155610" modified-by="*****" resolved="true">コメント1
テスト</m:comment>
        </trans-unit>
      </group>
      <group id="1" m:para-id="0">
        <context-group>
          <context context-type="x-file-part">word/document.xml::body</context>
        </context-group>
      </group>
      <group id="2" m:para-id="0">
        <context-group>
          <context context-type="x-file-part">word/document.xml::body</context>
        </context-group>
      </group>
      <group id="3" m:para-id="0">
        <context-group>
          <context context-type="x-file-part">word/document.xml::body</context>
        </context-group>
      </group>
      <group id="4" m:para-id="0">
        <context-group>
          <context context-type="x-file-part">word/document.xml::body</context>
        </context-group>
      </group>
      <group id="5" m:para-id="1">
        <context-group>
          <context context-type="x-file-part">word/document.xml::body</context>
        </context-group>
        <trans-unit id="*****" xml:space="preserve" m:score="0.0" m:gross-score="0.0" m:trans-origin="null" m:confirmed="1" m:locked="false" m:para-id="1" m:created-at="1487118023908" m:created-by="*****" m:modified-at="1487118380343" m:modified-by="*****" m:level-edited="false">
          <source>WEB system</source>
          <target>Webシステム</target>
          <alt-trans origin="machine-trans">
            <target />
          </alt-trans>
          <alt-trans origin="memsource-tm">
            <target />
          </alt-trans>
          <m:comment created-at="1487118138205" created-by="*****" modified-at="1487118380342" modified-by="*****" resolved="true">コメント2
あいうえお</m:comment>
        </trans-unit>
      </group>
    </body>
  </file>
  <m:extra>
    <m:users>
      <m:user id="*****" username="*****" fullname="*****" />
    </m:users>
  </m:extra>
</xliff>

基本的にはXLIFFに従っている(はず)なので、下記Webページを見れば、各要素や属性が何を示しているのか、ある程度分かります。

おわりに

というわけで、今回は真面目なマクロに取り組んでみました。
が、誰の役に立つかは不明・・・。

思いつきでコードを書いては見たものの、そもそも需要があるのかどうか謎なマクロです。
もしMemsourceをお使いの方で、「MXLIFFファイルの情報をアレコレしたい!」という方がいるのであれば、ご参考にしていただければ幸いです。

コメント

  • コメント (0)

  • トラックバックは利用できません。

  1. この記事へのコメントはありません。

Time limit is exhausted. Please reload CAPTCHA.

最近の記事

アーカイブ

RapidSSL_SEAL-90x50
PAGE TOP