試験運用中なLinux備忘録・旧記事

はてなダイアリーで公開していた2007年5月-2015年3月の記事を保存しています。

gettextによるメッセージ国際化(NLS: Native Language Support)の概要

多くのコマンド/アプリケーションにおいて、表示されるメッセージが日本語になっているのだが、これは、メッセージを国際化する仕組み(gettext)を使用して、英語で書かれた「元」のメッセージに対応した、それぞれの言語のメッセージを表示させることで実現している。

(2008/7/8)この記事ではかなり大まかな内容しか扱っていないため、実際の例としてコードを作成した(言語はPython)。
(2008/7/11)更にそのコードと同じ処理をC言語でも書いてみた。
関連記事:

作者・翻訳者側が行う対応

Wikipediaなども参照。

  1. アプリケーションの作者が、プログラム内のメッセージ表示処理において、gettextに対応した書き方でメッセージを記述する(例: 「今日」という意味のメッセージを出力するのに、「"Today"」を「_("Today")」と書く)他、幾つかの記述(bindtextdomain ()関数を呼ぶなど)を行う
  2. 各言語の翻訳者が、それぞれの英語メッセージに対応した訳を、決められた書式で決められた場所(一般的には、ソースツリーのpoディレクトリの中)に、ja.poなどの、ロケール名を含むテキストファイルに書いていく。このファイルをカタログと呼ぶ。*1
  3. アプリケーションのビルド時に、「.po」形式のカタログファイルは、msgfmtコマンドにより、機械語の「.mo」形式へとコンパイル*2され、インストール時に/usr/share/locales/ja/LC_MESSAGES/[名前].moといった場所に配置される

メッセージ国際化の動作

現在のGNU/Linuxにおいて、国際化に必要な機能(libintl)は、GNU Cライブラリ(glibc)の中に含まれていて、追加のライブラリをインストールしたりする必要はない。glibc自体のカタログファイルも存在し、「そのようなファイルやディレクトリはありません」などのメッセージを日本語で表示できるようになっている。また、エンコーディング変換機能(libiconv)もglibcに含まれている。
アプリケーション内での処理としては

  1. アプリケーション名(名前はプログラムの中で指定される)に対応した、現在のロケールにおけるメッセージカタログファイル(/usr/share/locales/ja/LC_MESSAGES/[名前].mo)を探す
  2. 英語のメッセージに対応した、現在のロケールのメッセージがあれば、それを表示させる

という流れで、開発版パッケージや最新版パッケージを使ったとき、訳が完全に対応されていなくて、一部英語のメッセージが出たりすることがある。また、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

*1:なお、カタログファイルのエンコーディングEUC-JPのものとUTF-8のものが混在しているが、manページと違い、先頭にエンコーディングを記述する部分があり、適切に処理されるため、どちらで書いても化けることはない

*2:msgunfntで逆の処理ができるが、コメントの記述は消えたまま

*3:アプリケーション自身が直接出していないメッセージ(Cライブラリによる「そのようなファイルや〜」といったメッセージや、GUIライブラリによる、ダイアログでの「キャンセル」「閉じる」など)は日本語になる