(3日目) Sphinx の文書を翻訳してみよう (gettext機能)

こんばんは、Sphinx & blockdiag アドベントカレンダー 3日目です。

今日は Sphinx 1.1 で実装された gettext 機能をご紹介します。
gettext は多言語に対応したアプリケーションを開発するときに利用する API で、
メニューに表示される単語やエラーメッセージなどを利用言語ごとに置き換える仕組みを提供しています。

gettext を利用することで翻訳元のドキュメントファイルを変更することなくドキュメントの翻訳を行い
他の言語(日本語や中国語など)のドキュメントを生成することができます。

概要

Sphinx では .rst ファイルに書かれた文章を言語ごとに置き換えることができます。
最初に英語でドキュメントを書き、gettext を介して翻訳を行うことで複数の言語のドキュメントを作ることができます。
gettext では中間ファイルとして pot ファイル、po ファイル、mo ファイルの 3つのファイルを使用します。

  • pot ファイル
    • rst ファイルから翻訳の対象となる文章を抽出したファイルです。
    • Sphinx では rst ファイルごと、もしくはサブディレクトリごとに 1つの pot ファイルが作成されます。
  • po ファイル
    • pot ファイルから生成されるファイルで、英文と対訳を記述していくファイルです。
    • 翻訳者は po ファイルを書き換えることで翻訳を行います。
    • po ファイルは言語ごとに作成します。日本語は ja という名称で翻訳を行います。
  • mo ファイル (メッセージカタログ)
    • po ファイルをコンパイルし、プログラムから読みやすい形式に変換したものです。
    • Sphinx はこの mo ファイルを参照して翻訳を行います。
    • po ファイル 1つにつき 1個作成されます

Sphinx ではファイルの生成の流れは以下のようになります。

Sphinx での翻訳の流れ

では Sphinx を使って翻訳を行ってみましょう。

まずはサンプルとして index.rst だけで構成されるかんたんなドキュメントの翻訳を行ってみます。

$ ls *.rst
index.rst
$ cat index.rst
===========================
gettext Translation Sample
===========================

This is sample page for translation using gettext.

Sphinx is very good documentation tool,
And blockdiag is simple and powerful diagram generator.
They let you be fun in documentation!

事前設定

まず gettext を利用するための設定を conf.py に書き加えます。

locale_dirs = ["locale"]
language = "ja"

変数 locale_dirs には poファイルや moファイルを配置するディレクトリを指定します(複数指定可能)。
ここでは locale ディレクトリに置くことにしました。
変数 language には翻訳に利用する言語を指定します。*1

rst ファイルから pot ファイルを生成する

次に pot ファイルを生成します。pot ファイルは Sphinx から出力することができます。

$ make gettext
$ ls _build/locale
index.pot

生成された pot ファイルを確認してみましょう。
index.rst から翻訳対象が抜き出されていることが分かります。

$ cat _build/locale/index.pot
 SOME DESCRIPTIVE TITLE.
# Copyright (C) 2011, test
# This file is distributed under the same license as the test package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: test test\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-12-03 21:03\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"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"

#: ../../index.rst:3
# ddfc79cb1d234e3ba5288af09b5ad843
msgid "gettext Translation Sample"
msgstr ""

#: ../../index.rst:5
# be3a44d5720645dca3bbb51170ba6120
msgid "This is sample page for translation using gettext."
msgstr ""

#: ../../index.rst:7
# 4495f0888ea84dc0b5c009de6e5003b8
msgid "Sphinx is very good documentation tool, And blockdiag is simple and powerful diagram generator. They let you be fun in documentation!"
msgstr ""

pot ファイルから po ファイルを生成する

続けて pot ファイルから po ファイルを生成します。
最初に locale ディレクトリを作成します。*2
pot ファイルから po ファイルの生成する際は msginit コマンドを使用します。
msginit を実行するとメールアドレスを聞かれるので、自身のメールアドレスを入力してください。*3

$ mkdir -p locale/ja/LC_MESSAGES
$ msginit --locale=ja --input=_build/locale/index.pot --output=locale/ja/LC_MESSAGES/index.po
ユーザが翻訳に関するフィードバックをあなたに送ることができるように,
新しいメッセージカタログにはあなたの email アドレスを含めてください.
またこれは, 予期せぬ技術的な問題が発生した場合に管理者があなたに連絡が取れる
ようにするという目的もあります.

Is the following your email address?
  tkomiya@...
Please confirm by pressing Return, or enter your email address.
i.tkomiya@gmail.com
http://translationproject.org/team/index.html を検索中... 完了.
A translation team for your language (ja) does not exist yet.
If you want to create a new translation team for ja, please visit
  http://www.iro.umontreal.ca/contrib/po/HTML/teams.html
  http://www.iro.umontreal.ca/contrib/po/HTML/leaders.html
  http://www.iro.umontreal.ca/contrib/po/HTML/index.html

locale/ja/LC_MESSAGES/index.po を生成.

生成された po ファイルは pot ファイルとほぼ同じ形式をしています。
翻訳を行う際はこの po ファイルの msgstr の欄に訳文を入れていきます。

$ cat locale/ja/LC_MESSAGES/index.po
# Japanese translations for test package.
# Copyright (C) 2011, test
# This file is distributed under the same license as the test package.
# Takeshi Komiya <i.tkomiya@gmail.com>, 2011.
#
msgid ""
msgstr ""
"Project-Id-Version: test test\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-12-03 21:03\n"
"PO-Revision-Date: 2011-12-03 21:05+0900\n"
"Last-Translator: Takeshi Komiya <i.tkomiya@gmail.com>\n"
"Language-Team: Japanese\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Language: ja\n"
"Plural-Forms: nplurals=1; plural=0;\n"

# ddfc79cb1d234e3ba5288af09b5ad843
#: ../../index.rst:3
msgid "gettext Translation Sample"
msgstr ""

# be3a44d5720645dca3bbb51170ba6120
#: ../../index.rst:5
msgid "This is sample page for translation using gettext."
msgstr ""

# 4495f0888ea84dc0b5c009de6e5003b8
#: ../../index.rst:7
msgid ""
"Sphinx is very good documentation tool, And blockdiag is simple and powerful "
"diagram generator. They let you be fun in documentation!"
msgstr ""

翻訳する

po ファイルは元の文章と翻訳する分が対になるような形式になっています。
po ファイルをエディタで開いて、それぞれの箇所に訳を埋めていきましょう。

# ddfc79cb1d234e3ba5288af09b5ad843
#: ../../index.rst:3
msgid "gettext Translation Sample"
msgstr "gettext 翻訳サンプルドキュメント"

# be3a44d5720645dca3bbb51170ba6120
#: ../../index.rst:5
msgid "This is sample page for translation using gettext."
msgstr "この文書は gettext を用いた翻訳のサンプルです。"

# 4495f0888ea84dc0b5c009de6e5003b8
#: ../../index.rst:7
msgid ""
"Sphinx is very good documentation tool, And blockdiag is simple and powerful "
"diagram generator. They let you be fun in documentation!"
msgstr ""
"Sphinx はとてもいいドキュメンテーションツールです。"
"そして blockdiag はシンプルかつ強力な図生成ツールです。"
"これらを使って楽しくドキュメンテーションを行いましょう"

po ファイルから mo ファイルに変換する

翻訳が終わったら、Sphinx から利用できるように po ファイルから mo ファイルに変換します。

$ msgfmt locale/ja/LC_MESSAGES/index.po -o locale/ja/LC_MESSAGES/index.mo
翻訳されたドキュメントを生成する

ここまでの道のりを得ると、ドキュメントの生成は簡単です。
いつも通り make コマンドを実行しましょう。

$ make clean html

これで翻訳された HTML ドキュメントが生成されます。

なお、引数に clean ターゲットを含めているのは、
Sphinx ビルダーが rst ファイルのタイムスタンプを見て、
ファイルが更新されていない(ビルド不要)と判断するケースがあるためです。

元のドキュメントを更新するとき

翻訳元のドキュメント(rst) が更新されたときは、上記の手順を繰り返します。

  • make gettext
  • po ファイル毎に以下の手順を実施
    • msgmerge (msginit しないように注意)
    • 翻訳
    • msgfmt
  • make html (など)

一点異なる箇所は、pot ファイルから po ファイルへの変換に msginit コマンドではなく msgmerge コマンドを利用することです。
なお、msginit コマンドは po ファイルを上書きしてしまうため、
更新を行う際は msgmerge コマンドを使用してください。

$ msgmerge -U locale/ja/LC_MESSAGES/index.po _build/locale/index.pot
.. 完了.

なお、rst ファイルが増えたときは pot ファイルも増えます。
増えたファイルはまた新しい po ファイルを作成する必要があるので、
ファイルの増減には気を払う必要があります。

まとめ

Sphinxgettext を使った翻訳は以下の流れで行います。

Sphinxgettext 機能で英語のドキュメントを変更せず、翻訳を行うことができるようになりました。
反面、Sphinx でサポートしている範囲は pot ファイルの生成までとなっているため、
それ以降の変換処理は手動で行う必要があります。

この複雑かつ面倒な変換処理については、sphinx-gettext-helper というスクリプトで改善することができます。
sphinx-gettext-helper については明日のアドベントカレンダーで紹介する予定です。

*1:変数 language は目次やノートの見出しなど、ちょっとしたところに出てくる単語を日本語にしてくれる(Note -> ノート など)ので、翻訳を行わない場合でも ja にしておくと幸せになれると思います。

*2:LC_MESSAGES というディレクトリは gettext のルールに基づいたもので、mo ファイル(メッセージカタログ)はここに設置します。

*3:msginit コマンドがない場合は OS の gettext パッケージをインストールして下さい。Debian であれば sudo apt-get install gettext でインストールできます。