Translate Toolkitで翻訳ツールを作る

# Translate Toolkit
[Translate Toolkit](http://toolkit.translatehouse.org/)とは、翻訳作業に役立つライブラリおよびコマンドラインツールのセットです。GPLv2ライセンスで配布されており、誰でも自由に利用できます。開発元はTranslate Houseで、Pythonで実装されています。Python 2系統をサポートしており、次期1.11.0からはPython 2.5以前はサポート対象外になる予定です。Translate Houseは、翻訳プラットフォームのPootleの開発も行っており、PootleでもこのTranslate Toolkitが利用されています (Doc-ja Advent Calendar 2013の[1日目](http://d.hatena.ne.jp/naruoga/20131201/1385838237)、[3日目](http://d.hatena.ne.jp/naruoga/20131203/1386063346)で紹介されたLibreOfficeの翻訳もPootle上で行われています)。

この記事では、Translate Toolkitのライブラリを利用して簡単な翻訳ツールを作成してみます。特にPOファイルの編集を自動化するツールを扱います。編集作業は単純だが対象箇所が膨大にある場合などに役立つでしょう。機械的な編集と言うと、本来sedなどの既存のUnix系ツールが得意とするところですが、POは行指向ではないためUnix系ツールとは相性が悪く一筋縄では行きません。ここでTranslate Toolkitを利用してみようというわけです。

なお、この記事ではメッセージカタログの形式として[GNU gettext](http://www.gnu.org/software/gettext/manual/gettext.html)によるPOを前提としますが、Translate ToolkitはPO以外にもXLIFFなど様々な形式に対応しています。PO自体については[2日目](http://qiita.com/iwaim@github/items/883e4aeb29085e39581a)の記事で解説されており、ここでは触れません。

## インストール方法
```sh
$ pip install translate-toolkit
```
あるいは、お使いのOSでtranslate-toolkitパッケージが提供されていれば、そちらを利用するのもよいでしょう。ソースコードは[github](https://github.com/translate/translate)で管理されています。


# 事例
たとえば、次のような作業例を考えてみましょう。「(GUI部品などでよくある)原文メッセージにサフィックスとして付与されたピリオド三つが三点リーダーに置換され、これにより大量のfuzzyが発生した。翻訳側の修正自体は単純だが対象箇所が膨大なため機械的に処理したい」。

## PO 例
以下は編集するPOの抜粋例です。このような例が手で編集したくないくらい膨大にあるものとイメージしてください。効果を分かりやすくするために、作為的な記述も一部含んでいます。

```po
# 更新対象
#, fuzzy
#| msgid "Open..."
msgid "Open…"
msgstr "開く..."

# 更新対象
# 翻訳側ピリオドの途中に改行が...
#, fuzzy
#| msgid "Save As..."
msgid "Save As…"
msgstr "名前を付けて保存."
".."

# なぜか以前からリーダーとなっている。更新不要
msgid "Print…"
msgstr "印刷…"

# 事情があって翻訳はサフィックス無しのままとしたい。fuzzyだけ落とす
#, fuzzy
#| msgid "Print Preview..."
msgid "Print Preview…"
msgstr "印刷プレビュー"

# なぜか原文がピリオドのまま(とりあえず翻訳もそれに従う)
msgid "Preference..."
msgstr "設定..."
```

## やりたいこと

更新された原文に合わせて翻訳側もピリオド三つを三点リーダーに置換する。
対象メッセージの条件は以下のようになります。

* fuzzy
* 古いmsgidのサフィックスがピリオド三つ
* 現在のmsgidのサフィックスが三点リーダー
* 新旧のmsgidはサフィックスを除いて同一


## サンプルスクリプト
このスクリプトは、標準入力からPOを読み込み、編集結果を標準出力に書き出します。

```py
# -*- coding: utf-8 -*-
import sys
from translate.storage.po import pofile

PREV_SUFFIX = '...'
NEW_SUFFIX = u'…'

for unit in pofile.parsefile(sys.stdin).units:
    prev_source = unit.prev_source
    new_source = unit.source
    if unit.isfuzzy() and \
       prev_source.endswith(PREV_SUFFIX) and \
       new_source.endswith(NEW_SUFFIX) and \
       prev_source.rstrip(PREV_SUFFIX) == new_source.rstrip(NEW_SUFFIX):
        if unit.target.endswith(PREV_SUFFIX):
            updated_target = unit.target.replace(PREV_SUFFIX, NEW_SUFFIX)
            unit.settarget(updated_target)
        unit.markfuzzy(False)
        unit.prev_source = None
    print unit
```

## 処理結果
上記POの処理結果は以下のようになります。fuzzyの処理が過不足なくできていること、テキスト途中での行折り返しなども適切に対応できていることが分かるでしょうか。

```po
# 更新対象
msgid "Open…"
msgstr "開く…"

# 更新対象
# 翻訳側ピリオドの途中に改行が...
msgid "Save As…"
msgstr "名前を付けて保存…"

# なぜか以前からリーダーとなっている。更新不要
msgid "Print…"
msgstr "印刷…"

# 事情があって翻訳はサフィックス無しのままとしたい。fuzzyだけ落とす
msgid "Print Preview…"
msgstr "印刷プレビュー"

# なぜか原文がピリオドのまま(とりあえず翻訳もそれに従う)
msgid "Preference..."
msgstr "設定..."
```


## スクリプトの説明

全体的にsource、targetという単語がよく登場しますが、これらは翻訳界隈でよく使われる用語です。SourceテキストとTargetテキストとは、それぞれ原文と翻訳文の意味です。POで言うところのmsgidとmsgstrに相当します。

PO関連のAPIはtranslate.storage.poモジュールをインポートして使用できるようになります。APIの詳細については[APIリファレンス](http://docs.translatehouse.org/projects/translate-toolkit/en/1.11.0-rc1/api/index.html)を参照してください。

pofileクラスのparsefileメソッドでPOを解析すれば、一連のメッセージがunitsというリストに収められます。リストの要素となる各メッセージはpounitクラスのオブジェクトとして操作できます。pounitはメッセージ操作用のAPIを提供し、msgidやmsgstrはもちろん、previousなmsgidや各種コメント、複数形など[gettextで定義される諸属性](http://www.gnu.org/software/gettext/manual/gettext.html#PO-Files)にアクセスできます。pounitのAPIを介することで、何かと厄介なPOファイルの物理的な記述にとらわれることなくメッセージを操作できます。

最初のifから4行が先述の4条件に該当します。条件に合致するメッセージを編集しています。

forループの最後にprintで各pounitを標準出力に出力しています。pounitは__str__メソッドを定義しており、そのままprintするだけでPOのメッセージとして妥当な形式で出力できます。


# 他にも
似たような作業として、タイポの機械的なチェック、翻訳スタイル変更にともなう一括修正など、様々な用途に応用できます。他によくあるケースとしては、二つのPOの更新差分を取る、差分を一方にマージするなどのツールも簡単に作成できます。

実際に、私が[GNOMEプロジェクトの日本語翻訳](https://l10n.gnome.org/teams/ja/)で長音表記のスタイル変更(「ユーザ」を「ユーザー」にするなど)のお手伝いをしたときにも、Translate Toolkitで編集ツールを作成して一括処理しました。GNOMEプロジェクトのPOメッセージ数はざっくり見積もってもmsgid単位で十万件以上あります。到底人力で編集できるものではなく、Translate Toolkitが本当に役立ちました。


# まとめ
今回は、Translate Toolkitライブラリのごくごく一部だけ紹介しました。他にも有用な機能が多数用意されています。また、ライブラリ以外にも、すぐに使えるコマンドラインツールも提供されています。詳細については、APIリファレンスなど[各種ドキュメント](http://docs.translatehouse.org/projects/translate-toolkit/en/1.11.0-rc1/)を参照してください。日々の翻訳ライフにTranslate Toolkitを利用してみてください。Happy translating!

明日はknokさんです。