poファイル翻訳において前バージョン翻訳済みpoを効果的に利用する方法

# 序文

linuxでのアプリの翻訳にはGNU gettextというツールが使用されています。このツールは未翻訳の英文メッセージと翻訳済みメッセージの対応付けをpoファイルという形式に保存してロケールに合わせて翻訳済みメッセージを表示します。

gettextは本来、プログラムソース中のユーザーの目に触れる文字列リソース(GUIメニュー文字列やメッセージ文字列など)を対象としたものですが、gettextのpoファイル形式はgettextが対応していないドキュメントの翻訳にも多用されるようになりました。

かくいう私もpo4aというツールでgettextやemacsのマニュアルを、infoドキュメントの元となるtexiドキュメントからpoファイルを生成、翻訳したりしました。

アプリのドキュメントというものは、アプリのバージョンアップとともにバージョンアップされます。poファイル翻訳において、前バージョンの翻訳済みファイルを新バージョンの未翻訳ファイルに適用するためのツールがgettextには存在するのですがあまり情報がなく、わたし自身も翻訳を中断・再開するたびに「あれ、どーやんだっけ?」とマニュアルを調べ直すことも多く、備忘録を兼ねてここに記します。

なお、ここではpoファイル生成にはわたしが翻訳したtexiファイルに対応しているpo4aを、翻訳ツールとしてemacsを例としますが、それぞれのソース形式に応じたpoファイルツールや、emacs以外にもpoファイル編集のための専用翻訳ツールがあるので、それらを使用されている人は適宜読み替えてください。

# 初版の翻訳
とりあえずemacs-24.5のマニュアルを例にします。自分で試したい人は`git clone https://github.com/ayatakesi/emacs-24.5-doc-emacs.git`してください。

## poファイル作成
まずpo4aによりインストールされるpo4a-gettextizeにより、texinfoファイルからpoファイルを生成します。

```shell
po4a-gettextize -M utf8 -f texinfo -m custom.texi -p custom.texi.po
```

以下のようなpoファイルが生成されます。

```po:custom.texi.po
# SOME DESCRIPTIVE TITLE
# Copyright (C) YEAR Free Software Foundation, Inc.
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2018-01-03 18:45+0900\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"

#. type: chapter
#: custom.texi:5 custom.texi:6
#, no-wrap
msgid "Customization"
msgstr ""

#. type: cindex
#: custom.texi:7
#, no-wrap
msgid "customization"
msgstr ""
```

## 翻訳
poファイルのmsgidに対応する翻訳をmsgstrに記述していきます。poファイルのフォーマットにはお約束があって、コメントにも`#.`、`#:`、`#,`のようにいくつか種類があります(詳細はマニュアル、または[拙訳](https://ayatakesi.github.io/gettext/0.19.8.1/html/PO-Files.html#PO-Files)を参照してください)。poファイル編集のためのツールが各種ありますが、いずれもこれらフォーマットの約束事を自動的に処理してくれるので、poファイルの編集にはそれらの使用をお勧めします(vimなどでもシンタックスハイライトくらいはしてくれますが、手編集ではフォーマットを壊してしまうかもしれませんよ)。

わたしはemacs＋gettextとともにインストールされるpo-modeを使用しています。po-modeのために必要なファイルはgettextインストールとともに適切な場所にインストールされるはずですが、インストールされない場合(apt-getなどでインストール時)は、`{gettext's source directory}/gettext-tools/misc/*.el`をEmacsの`load-path`にコピーしてください。

po-modeではエントリー間の移動に`n(po-next-entry)`、`p(po-previous-entry)`、`u(po-next-untranslated-entry)`、`f(po-next-fuzzy-entry)`などを使用します。またエントリーのステータスの変更は`{TAB}(po-unfuzzy)`でfuzzy→翻訳ずみ、`{Backspace}(po-fade-out-entry)`で翻訳済み→fuzzy→obsoleteに変更します。詳しい使用法はマニュアル、または[拙訳](https://ayatakesi.github.io/gettext/0.19.8.1/html/PO-Mode.html#PO-Mode)を参照してください。

他のツールは知りませんが、po-modeではpoヘッダー(msgidが""のエントリー。通常はpoファイルの最初にある。)の`charset=CHARSET`に適切な文字セットを指定しないと日本語が入力できません。はやる気持ちを抑えて、`charset=UTF-8`に修正します。

ポイント位置のエントリーを翻訳するには`{RET}(po-edit-msgstr)`を押下します。すると翻訳を編集するためのウィンドウが開くので、そこでpoヘッダーを修正します。`charset`以外の項目(`POT-Creation-Date`はpo作成ツール、`PO-Revision-Date`はpoエディターなどにより自動的に更新されるので編集不要)も修正します。

![Screenshot_20180105-185033.png](https://qiita-image-store.s3.amazonaws.com/0/134669/90772cb9-c894-6726-c62a-c73486efbb5d.png)

翻訳したら`C-c C-c(po-subedit-exit)`でコミット(取り消す場合は`C-c C-k(po-subedit-abort)`)して、`C-x C-s(save-buffer)`で保存、`q(po-confirm-and-quit)`で閉じて、再度開き直します。

翻訳したものが[こちら](https://github.com/ayatakesi/emacs-24.5-doc-emacs/blob/master/custom.texi.po)です。

## 翻訳済みpoファイルから元ドキュメントを翻訳
翻訳したpoファイルから翻訳済みtexinfoを作成するにはpo4a-translateを使用します。

```shell
po4a-translate -f texinfo -k 0 -M utf8 -m custom.texi.orig -p custom.texi.po -l custom.texi
```

ここで、custom.texi.origは翻訳前のオリジナルtexinfoファイル、custom.texi.poは翻訳済みpoファイル、custom.texiが生成する翻訳済みtexinfoファイルです。翻訳済みのtexinfoは[こちら](https://ayatakesi.github.io/emacs/25.1/emacs-ja.texis.tar.gz)を参照してください(poファイルで対応が難しいメッセージは一部perlのsedエミュレーションを使用して置換してます)。

# 改訂版の翻訳
emacs-24.5からemacs-25.1へのマニュアルバージョンアップを例にします。自分で試したい人は`git clone https://github.com/ayatakesi/emacs-25.1-doc-emacs.git`してください。

## poファイル作成
初版と同様です。作成した未翻訳のpoファイルはcustom.texi.po.25.1とでもしておきます。

## 旧版翻訳済みpoファイルのマージ
旧版の翻訳済みpoファイルはcustom.texi.po.24.5とします。作成される旧版翻訳マージ後のpoファイルがcustom.texi.poです。ここでは[compendiumオプションとpreviousオプション](https://ayatakesi.github.io/gettext/0.19.8.1/html/msgmerge-Invocation.html#msgmerge-Invocation)、および[ここ](https://ayatakesi.github.io/gettext/0.19.8.1/html/Using-Compendia.html#Using-Compendia)に説明されている方法を使用してます。

```shell
msgmerge --previous --compendium custom.texi.po.24.5 -o custom.texi.po /dev/null custom.texi.po.25.1
```

マージされたpoファイルは以下のようになります。

```po:custom.texi.po
#. type: cindex
#: custom.texi:1767
#, no-wrap
msgid "modifier keys"
msgstr "modifier keys"

#. type: Plain text
#: custom.texi:1775
#, fuzzy
#| msgid ""
#| "The default key bindings in Emacs are set up so that modified "
#| "alphabetical characters are case-insensitive.  In other words, @kbd{C-A} "
#| "does the same thing as @kbd{C-a}, and @kbd{M-A} does the same thing as "
#| "@kbd{M-a}.  This concerns only alphabetical characters, and does not "
#| "apply to ``shifted'' versions of other keys; for instance, @kbd{C-@@} is "
#| "not the same as @kbd{C-2}."
msgid ""
"The default key bindings in Emacs are set up so that modified alphabetical "
"characters are case-insensitive.  In other words, @kbd{C-A} does the same "
"thing as @kbd{C-a}, and @kbd{M-A} does the same thing as @kbd{M-a}.  This "
"concerns only alphabetical characters, and does not apply to shifted "
"versions of other keys; for instance, @kbd{C-@@} is not the same as "
"@kbd{C-2}."
msgstr ""
"Emacsでは、デフォルトのキーバインディングがセットアップされているので、修飾さ"
"れたアルファベット文字は大文字小文字が区別されません。つまり@kbd{C-A}は"
"@kbd{C-a}と同じことを行い、@kbd{M-A}は@kbd{M-a}と同じことを行ないます。これは"
"アルファベット文字だけに当てはまり、他のキーの``シフトキーが押された"
"(shifted)''バージョンには適用されません。たとえば、@kbd{C-@@}は@kbd{C-2}と同"
"じではありません。"
```

msgidには新版の英文、msgstrには旧版の翻訳がセットされます。`#|`で始まるコメントが旧版の英文です。

## 翻訳
untranslatedとfuzzyを潰していきます。untranslatedは1から翻訳ですが、fuzzyに関しては`--previous`により、旧英文と新英文、旧翻訳を見比べて翻訳できます。見ていただくとわかると思いますが、旧版／新版の英文目視diffは結構辛いものがあります。

以前使用したことのある翻訳ツールでは[virtaal](http://virtaal.translatehouse.org)が差分表示に対応してました。

![virtaalスクショ](https://qiita-image-store.s3.amazonaws.com/0/134669/297d04a3-79b6-ab9b-d193-593d272bc7bc.png)

スクショで推測できると思いますが、わたしはAndroid上のtermuxのemacsで翻訳しているんですが、Xアプリはいまいちトロくて使い勝手が悪く、Emacsのediff-window-wordwiseを改造したものでdiffをとってます(とても公開できる代物ではありませんが、ソースは[こちら](https://github.com/ayatakesi/.emacs.d/blob/master/my_lisp.el)。現在elisp勉強中です)。

![emacsスクショ](https://qiita-image-store.s3.amazonaws.com/0/134669/16a7a572-8f3f-caea-8f33-1db616e45a88.png)

## 翻訳済みpoファイルから元ドキュメントを翻訳
初版と同様です。

# 結び
巷では翻訳マニュアルは英語習得の妨げになるという意見も目立ちますが、わたしは違う意見です。自分が本当に興味をもっている分野ではオリジナルの英文をよみますが、自分の興味がある分野の前提知識を調べるときに、いちいち英文を読むのは正直かったるいです。htmlの知識が0だったとして、最初に英文情報を当たることはまずありません。日本語情報でザクっと調べて、その上で特定の情報を調べるとき英文を読む感じです。そもそも、今のわたしが英文を読めるようになったのは、豊富な日本語情報が背景にあったわけですから。この投稿が日本語情報の充実に役立つことを願います。おわり