言語ゲーム

とあるエンジニアが嘘ばかり書く日記

Twitter: @propella

gettext その1

gettext とは

最近のソフトは使う人に応じて勝手にメニューなんかの言語が変わるようになってますが、そういう事をするのが gettext です。例えばソースコードに"menu" と書いてあった場合、それをそのまま表示するのではなくてプログラムの外部の辞書を引いて 「menu」 -> 「メニュー」の対応を見つけ表示します。この対応を見つける部分に gettext の特徴があります。

gettext 辞書

gettext 辞書は、ディレクトリ/言語/LC_MESSAGES/ドメイン.mo と言う名前で保存されるバイナリのファイルです。このうち、ディレクトリはソース内で指定(システムの規定値として、たとえば /usr/share/locale/)、言語は環境変数で指定(例えば ja)、ドメインは大抵ソフトの名前です。例えば /usr/share/locale/ja/LC_MESSAGES/hello.mo のような名前になります。

gettext 辞書を編集する

gettext 辞書は次のような手順で作成します。まずgettext 対応のソースコードを書く。

#define PACKAGE "hello"

#include <stdio.h>
#include <locale.h>
#include <libintl.h>

#define _(String) gettext(String)

int main(int argc, char *argv[])
{
	bindtextdomain(PACKAGE, ".");
	textdomain(PACKAGE);

	puts(_("Hello, world"));
	puts(_("Bye, world"));

	return 0;
}

ソースコードから辞書テンプレートを抽出

$ xgettext -c -d hello -k_ hello.c -o hello.pot

辞書テンプレートから言語ごとの辞書を作成

$ touch ja.po
$ msgmerge ja.po hello.pot -o ja.po # 初回は cp で作っても良い。

ja.po を編集後、

#: hello.c:14
msgid "Hello, world"
msgstr "こんにちは 世界"

#: hello.c:15
msgid "Bye, world"
msgstr "さようなら 世界"

辞書ファイルを作成

$ mkdir -p ja/LC_MESSAGES
$ msgfmt -o ja/LC_MESSAGES/hello.mo ja.po

テスト

$ cc -o hello hello.c -lintl
$ LANG=ja # Fedora の場合は export LANG=ja_JP.eucjp のように
$ ./hello
こんにちは 世界
さようなら 世界
$ export TEXTDOMAINDIR=.
$ gettext -d hello "Bye, world" # コマンドラインからもテスト出来ます。
さようなら 世界