銀月の符号

Python 使い見習いの日記・雑記

gettext モジュールメモ

Python gettext モジュールと戯れる。多言語対応 Python アプリを作るためのモジュール。しかし、オレには日本語以外まともに使える語がない罠。いや、日本語も怪しいけれど。

前提

次のコードを hello.py とする。実行すると「Hello」と挨拶するだけのスクリプト。これをいろんな語の挨拶に代えられるようにしたい、とする。たとえば日本語環境だと「こんにちは」。

# coding: utf-8

def main():
    print u'Hello'

if __name__ == '__main__':
    main()

手順1、マーキング

翻訳対象となる語を _ でマーキングする。次のようになる。

# coding: utf-8

def main():
    print _(u'Hello')

if __name__ == '__main__':
    main()

しかし、この段階で実行すると、 _ ってなに? というエラーが起こる。

>python hello.py
Traceback (most recent call last):
  File "hello.py", line 7, in <module>
    main()
  File "hello.py", line 4, in main
    print _(u'Hello')
NameError: global name '_' is not defined

手順2、 _ をインストール

_ に文字列を置き換えてくれるなんらかの呼び出し可能オブジェクトを対応付ける。ひとつの方法は gettext.translation 関数で得られた「翻訳オブジェクト」の ugettext メソッドを _ とすること。その他の方法については http://pythonjp.sourceforge.jp/dev/library/gettext.html#id3 参照。

# coding: utf-8

import os
import gettext

_ = gettext.translation(
        domain='hello',
        localedir=os.path.join(os.path.dirname(__file__), 'locale'),
        fallback=True).ugettext

def main():
    print _(u'Hello')

if __name__ == '__main__':
    main()

translation 関数の引数の内容はこう。

domain
.mo ファイルの名前
localedir
.mo ファイルの置き場所(省略可能)
fallback
.mo ファイルが見つからなかったとき、翻訳せずに続行するかどうか(デフォルトは False で例外が発生する。 True だとなにもしない NullTranslations オブジェクトが返る。 NullObject パターン。)

この段階で実行すると、まだ翻訳を収めた .mo ファイルが作成されていないため、そのまま Hello と表示される。

>python hello.py
Hello

手順3、.pot ファイルの作成

翻訳対象となる語をまとめた .pot ファイルを作成する。これには pygettext.py スクリプトを用いる。 WindowsPython 2.6.4 には入ってなかったのでソースの Tools\i18n から持ってきた。 pygettext.py hello.py とすると次のような messages.pot ができあがる。

# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR ORGANIZATION
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2010-03-19 21:34+東京 (標準時)\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=CHARSET\n"
"Content-Transfer-Encoding: ENCODING\n"
"Generated-By: pygettext.py 1.5\n"


#: hello.py:12
msgid "Hello"
msgstr ""

次の .po ファイル作成は翻訳担当者の作業。

手順4、.po ファイルの作成

.po ファイルを作成する。まずは先ほどの messages.pot をコピーして hello.po という名のファイルを作る。そして翻訳作業に入る。たとえばこんな感じ。

# Hello
# Copyright (C) 2010 fgshun
# fgshun <fgshun.lazy-moon.jp>, 2010.
#
msgid ""
msgstr ""
"Project-Id-Version: 0.1\n"
"POT-Creation-Date: 2010-03-19 19:44+JST\n"
"PO-Revision-Date: 2010-03-19 19:57+JST\n"
"Last-Translator: fgshun <fgshun@lazy-moon.jp>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: pygettext.py 1.5\n"


#: hello.py:12
msgid "Hello"
msgstr "こんにちは"

.po ファイルのヘッダ部分については http://www.gnu.org/software/gettext/manual/gettext.html#Header-Entry 参照。

なお、 .po ファイルを編集するエディタもあるみたい。 poedit など。

手順5、.mo ファイルの作成

hello.po が出来上がったら、これを元に hello.mo ファイルを作ることができる。変換には msgfmt.py スクリプトを用いる。 msgfmt.py も Windows 版にはないので pygettext.py 同様に用意。 msgfmt.py hello.po とすると hello.mo ファイルができる。

次の .mo ファイルの設置はユーザーもしくはインストーラー作成者の作業。

手順6、.mo ファイルの設置

hello.mo ファイルを gettext が読める位置におく。日本語用 .mo は ja\LC_MESSAGES\hello.mo という階層におくべし。

完成

以上で終了。早速日本語で挨拶させてみる。

>python hello.py
こんにちは