gettextによるメッセージ国際化(NLS: Native Language Support)の概要
多くのコマンド/アプリケーションにおいて、表示されるメッセージが日本語になっているのだが、これは、メッセージを国際化する仕組み(gettext)を使用して、英語で書かれた「元」のメッセージに対応した、それぞれの言語のメッセージを表示させることで実現している。
(2008/7/8)この記事ではかなり大まかな内容しか扱っていないため、実際の例としてコードを作成した(言語はPython)。
(2008/7/11)更にそのコードと同じ処理をC言語でも書いてみた。
関連記事:
- Pythonでgettextを使用してNLS(Native Language Support)によるメッセージの国際化を行う(作業の流れと動作確認・前半)
- Pythonでgettextを使用してNLS(Native Language Support)によるメッセージの国際化を行う(作業の流れと動作確認・後半)
- Pythonでgettextを使用してNLS(Native Language Support)によるメッセージの国際化を行う(Pythonのコードについて)
- Pythonで作成したgettextのテストプログラムをC言語で書いてみる
作者・翻訳者側が行う対応
Wikipediaなども参照。
- アプリケーションの作者が、プログラム内のメッセージ表示処理において、gettextに対応した書き方でメッセージを記述する(例: 「今日」という意味のメッセージを出力するのに、「"Today"」を「_("Today")」と書く)他、幾つかの記述(bindtextdomain ()関数を呼ぶなど)を行う
- 各言語の翻訳者が、それぞれの英語メッセージに対応した訳を、決められた書式で決められた場所(一般的には、ソースツリーのpoディレクトリの中)に、ja.poなどの、ロケール名を含むテキストファイルに書いていく。このファイルをカタログと呼ぶ。*1
- アプリケーションのビルド時に、「.po」形式のカタログファイルは、msgfmtコマンドにより、機械語の「.mo」形式へとコンパイル*2され、インストール時に/usr/share/locales/ja/LC_MESSAGES/[名前].moといった場所に配置される
メッセージ国際化の動作
現在のGNU/Linuxにおいて、国際化に必要な機能(libintl)は、GNU Cライブラリ(glibc)の中に含まれていて、追加のライブラリをインストールしたりする必要はない。glibc自体のカタログファイルも存在し、「そのようなファイルやディレクトリはありません」などのメッセージを日本語で表示できるようになっている。また、エンコーディング変換機能(libiconv)もglibcに含まれている。
アプリケーション内での処理としては
- アプリケーション名(名前はプログラムの中で指定される)に対応した、現在のロケールにおけるメッセージカタログファイル(/usr/share/locales/ja/LC_MESSAGES/[名前].mo)を探す
- 英語のメッセージに対応した、現在のロケールのメッセージがあれば、それを表示させる
という流れで、開発版パッケージや最新版パッケージを使ったとき、訳が完全に対応されていなくて、一部英語のメッセージが出たりすることがある。また、gettext自体に対応していても、日本語のカタログファイルを誰も作成していない場合、メッセージは基本的に英語となる。*3
tarコマンドでの例
英語でのメッセージ。
$ LC_ALL=C tar tar: You must specify one of the `-Acdtrux' options Try `tar --help' or `tar --usage' for more information.
日本語でのメッセージ。
$ tar tar: オプション `-Acdtrux' のうち、いずれかを指定しなければなりません より詳しい情報は `tar --help' または `tar --usage' で.
カタログファイル内の該当部分を見る。
$ msgunfmt /usr/share/locale/ja/LC_MESSAGES/tar.mo | iconv -f eucjp -t utf8 | less -p "You must" $ msgunfmt /usr/share/locale/ja/LC_MESSAGES/tar.mo | iconv -f eucjp -t utf8 | less -p usage
面白い訳の例
幸いなのか不幸なのか、いずれのメッセージも、お目にかかったことはない。
$ msgunfmt /usr/share/locale/ja/LC_MESSAGES/util-linux.mo | iconv -f eucjp -t utf8 | less -p alive $ msgunfmt /usr/share/locale/ja/LC_MESSAGES/findutils.mo | iconv -f eucjp -t utf8 | less -p oops $ msgunfmt /usr/share/locale/ja/LC_MESSAGES/libc.mo | iconv -f eucjp -t utf8 | less -p bought