ローカライズされるテキストメッセージは、アプリケーションのソースコードとは切り離して、個別のファイルに格納する必要があります。これらのファイルは、メッセージバンドル、メッセージカタログ、または移植可能メッセージファイルと呼ばれます。各プログラミング言語には、これらのファイルを操作するためのツールセットが用意されています。たとえば、C、Python、Perl などのプログラミング言語では、メッセージを翻訳するための gettext 関数が提供されています。
移植可能メッセージファイルは gettext ユーティリティーを使用して作成します。これらのファイルはプレーンテキストで表示され、ファイル拡張子として .po が付きます。翻訳対象の移植可能メッセージファイルをトランスレータに送信し、トランスレータは翻訳済みのテキストでファイルを更新します。翻訳後の .po ファイルには、対応する翻訳済みのテキストとメッセージ ID が含まれます。例:
$ cat cs.po . . #: code.c:37 #,c-format msgid "My hovercraft is full of eels.\n" msgstr "Moje vznášedlo je plné úhořů.\n"
ただし、移植可能オブジェクトファイルをメッセージオブジェクトファイルに変換することで、システムのパフォーマンスを向上できます。メッセージオブジェクトファイルにはファイル拡張子として .mo が付きます。移植可能オブジェクトファイルをメッセージオブジェクトファイルに変換するには、msgfmt ユーティリティーを使用します。
この例は、シェルスクリプトのローカライズ済みメッセージオブジェクトを生成する方法を示しています。gettext 関数の呼び出しを含む、次のシェルスクリプトがあることを想定します。
#!/usr/bin/bash # # set TEXTDOMAIN and TEXTDOMAINDIR as per the gettext(1) manual page TEXTDOMAIN=test_gettext_sh export TEXTDOMAIN TEXTDOMAINDIR=/home/xxxxx/lib/locale export TEXTDOMAINDIR PATH=/usr/gnu/bin:/usr/bin export PATH # source gettext.sh for using eval_gettext and eval_ngettext . gettext.sh f="filename.dat" # Use eval_gettext or eval_ngettext if it refers to shell variables # TRANSLATORS: $f is replaced with a file name eval_gettext "\$f not found"; echo gettext "file not found"; echo echo "`eval_gettext "\\\$f not found"`" echo "`gettext "file not found"`"
このシェルスクリプト用に、次の手順を使用して、ローカライズされたメッセージオブジェクトを作成できます。
gettext ツールの GNU バージョンを使用するには、PATH 環境変数の前に usr/gnu/bin を追加します。
$ PATH=/usr/gnu/bin:$PATH
xgettext コマンドを使用して、シェルスクリプトからメッセージを抽出し、メッセージファイルテンプレートに配置します。
$ xgettext -c"TRANSLATORS:" -L"Shell" test_gettext.sh
messages.po という名前のファイルが作成されます。ここにはシェルスクリプトのヘッダー情報およびメッセージ文字列が含まれます。トランスレータ向けの説明コメントも含まれます。次の例は、messages.po ファイルからの抜粋を示しています。
#. TRANSLATORS: $f is replaced with a file name #: test_gettext.sh:18 test_gettext.sh:21 #, sh-format msgid "$f not found" msgstr "" #: test_gettext.sh:19 test_gettext.sh:22 msgid "file not found" msgstr ""
msginit コマンドを使用して、翻訳言語に固有の移植可能メッセージ (.po) ファイルを作成します。たとえば、日本語の ja_JP.UTF-8 ロケールでは、次のコマンドを使用して .po ファイルを作成します。
$ msginit --no-translator --locale=ja_JP.UTF-8 --input=messages.po
ja.po という名前のファイルが作成されます。
ja.po ファイル内のメッセージを翻訳します。
TEXTDOMAINDIR環境変数で指定したディレクトリに、LC_MESSAGES ディレクトリを作成します。
$ mkdir -p lib/locale/ja/LC_MESSAGES
シンボリックリンクを作成するか、LANGUAGE 変数を設定します。
シンボリックリンクを作成します。
$ ln -s ja lib/locale/ja_JP.UTF-8
LANGUAGE 変数を設定します。
$ LANGUAGE=ja_JP.UTF-8:ja $ export LANGUAGE
メッセージオブジェクト (.mo) ファイルを作成します。
$ msgfmt -o lib/locale/ja/LC_MESSAGES/test_gettext_sh.mo ja.po
この例は、C プログラムのローカライズ済みメッセージオブジェクトを生成する方法を示しています。gettext 関数の呼び出しを含む、次の C プログラムがあることを想定します。
#include <stdio.h> #include <sys/types.h> #include <libintl.h> #include <locale.h> #include <time.h> /* * _() is used for the strings to extract messages. * N_() is used for the string array message to extract messages. * T_() is used for the strings to extract messages with working on LC_TIME */ #define _(String) gettext (String) #define gettext_noop(String) String #define N_(String) gettext_noop (String) #define T_(String) gettext_noop (String) #define LOCALEDIR "/home/xxxxx/lib/locale" #define PACKAGE "test_gettext" static const char *msg[] = { N_("The first message"), N_("The second message"), }; int main(int ac, char **av) { char *file = "test.dat"; int line = 40; int column = 10; time_t tloc; char time_buf[BUFSIZ]; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); /* * By default, the characters are converted to current locale's encoding. * If this is not desired, call bind_textdomain_codeset(). For example, * if you want "UTF-8" encoding, specify "UTF-8" in the second argument. * * bind_textdomain_codeset("test_gettext", "UTF-8"); */ printf(_("This is a test\n")); printf("%s\n", _(msg[0])); printf("%s\n", _(msg[1])); /* TRANSLATORS: First %d is replaced by a line number. Second %d is replaced by a column number. %s is replaced by a file name. */ printf(_("ERROR: invalid input at line %1$d, %2$d in %3$s\n"), line, column, file); /* * strftime() works with LC_TIME not LC_MESSAGES so to get properly * formatted time messages we have to call dcgettext() with LC_TIME category. */ (void) time(&tloc); (void) strftime(time_buf, sizeof (time_buf), /* TRANSLATORS: This is time format used with strftime(). Please modify time format to fit your locale by using date '+%a %b %e %H:%M:%S' */ dcgettext(NULL, T_("%a %b %e %H:%M:%S"), LC_TIME), localtime(&tloc)); printf("%s\n", time_buf); return(0); }
この C プログラム用に、次の手順を使用して、ローカライズされたメッセージオブジェクトを作成できます。
PATH 環境変数の前に /usr/gnu/bin を追加します。
$ PATH=/usr/gnu/bin:$PATH
xgettext コマンドを使用して、ソースコードからメッセージを抽出し、メッセージファイルテンプレートに配置します。
$ xgettext -c"TRANSLATORS:" -k -k"_" -k"N_" -L"C" test_gettext.c
messages.po ファイルが LC_MESSAGES ロケールカテゴリに対して作成されます。ここには、ヘッダー情報やメッセージ文字列が格納され、トランスレータ向けの説明コメントも含まれています。次の例は、messages.po ファイルからの抜粋を示しています。
#: test_gettext.c:21 msgid "The first message" msgstr "" #: test_gettext.c:22 msgid "The second message" msgstr "" #: test_gettext.c:43 #, c-format msgid "This is a test\n" msgstr "" #. TRANSLATORS: #. First %d is replaced by a line number. #. Second %d is replaced by a column number. #. %s is replaced by a file name. #: test_gettext.c:51 #, c-format msgid "ERROR: invalid input at line %1$d, %2$d in %3$s\n" msgstr ""
LC_TIME ロケールカテゴリに .po ファイルをもう 1 つ作成します。
$ xgettext -c"TRANSLATORS:" -k -k"T_" -L"C" -o messages_t.po test_gettext.c
messages_t.po ファイルが LC_TIME ロケールカテゴリに対して作成されます。
msginit コマンドを使用して、翻訳言語に固有の移植可能メッセージ (.po) ファイルを作成します。
たとえば、日本語の ja_JP.UTF-8 ロケールでは、次のコマンドを使用して移植可能ファイルメッセージを作成します。
$ msginit --no-translator --locale=ja_JP.UTF-8 --input=messages.po $ msginit --no-translator --locale=ja_JP.UTF-8 --input=messages_t.po --output-file=ja_t.po
ja.po および ja_t.po ファイルが作成されます。
作成された ja.po および ja_t.po ファイルを翻訳します。
LOCALEDIR 変数で指定されているディレクトリに、LC_MESSAGES および LC_TIME ディレクトリを作成します。
$ mkdir -p lib/locale/ja/LC_MESSAGES lib/locale/ja/LC_TIME
シンボリックリンクを作成するか、LANGUAGE 変数を設定します。
シンボリックリンクを作成します。
$ ln -s ja lib/locale/ja_JP.UTF-8
LANGUAGE 変数を設定します。
$ LANGUAGE=ja_JP.UTF-8:ja $ export LANGUAGE
メッセージオブジェクト (.mo) ファイルを作成します。
$ msgfmt -o lib/locale/ja/LC_MESSAGES/test_gettext.mo ja.po $ msgfmt -o lib/locale/ja/LC_TIME/test_gettext.mo ja_t.po
メッセージオブジェクトファイルは、次の形式で作成されます。
/usr/lib/locale/locale/category/textdomain.mo
このパスには複数のコンポーネントがあります。
メッセージオブジェクトファイルを断定するデフォルトパス。たとえば、テキストドメインの衝突が発生した場合、bindtextdomain() 関数の呼び出しによってパスが指定されます。サードパーティソフトウェアの場合、メッセージオブジェクトファイルは /usr/share/locale ディレクトリで使用できます。
ロケールディレクトリ。
ロケールのカテゴリ。
textdomain() 関数の呼び出しで指定されるテキストドメイン。メッセージカタログの一意の識別子とファイル名です。
次の例を考えてみましょう。
/usr/lib/locale/it_IT.UTF-8/LC_MESSAGES/mymessages.mo
ここでは:
ロケールディレクトリ。このメッセージオブジェクトにはイタリア語の翻訳が含まれており、このロケールと、このディレクトリへのシンボリックリンクとなるその他のロケールで使用されます。
ロケールのカテゴリ。
メッセージカタログ名。
Oracle Solaris gettext API は、Oracle Solaris と GNU 互換のメッセージカタログファイルの両方をサポートします。ただし、一部の gettext API は、GNU 互換のメッセージカタログファイルに固有のものです。Solaris および GNU 互換の gettext インタフェースは次のとおりです。
メッセージカタログからテキスト文字列を取得します
特定のドメインのメッセージカタログからメッセージを取得します
現在のドメインを設定して問い合わせます
メッセージドメインのパスをバインドします
特定のドメインおよびカテゴリのメッセージカタログからメッセージを取得します
GNU 互換のメッセージカタログファイルでのみ機能する gettext API は次のとおりです。
メッセージカタログからテキスト文字列を取得して複数形を選択します
特定のドメインのメッセージカタログからテキスト文字列を取得して、複数形を選択します
ドメインのメッセージカタログの出力 codeset を指定します
特定のドメインおよびカテゴリのメッセージカタログからテキスト文字列を取得して、複数形を選択します
GNU テキストメッセージ処理の詳細は、GNU gettext リファレンスを参照してください。
gettext 関数の詳細は、msgfmt(1)、xgettext(1)、gettext(1) のマニュアルページを参照してください。
gettext は、メッセージオブジェクトファイルを作成して処理するための関数とコマンド行ツールを提供しています。Oracle Solaris メッセージオブジェクトは、GNU gettext メッセージオブジェクトとは異なる形式です。メッセージを処理するためのコマンド行ツールの Oracle Solaris バリアントは次のとおりです。
メッセージカタログからテキスト文字列を取得します
移植可能メッセージファイルからメッセージオブジェクトを作成します
gettext 文字列への呼び出しを C プログラムから取得します
メッセージを処理するためのコマンド行ツールの GNU バリアントは次のとおりです。
メッセージカタログからテキスト文字列を取得します
メッセージファイルからメッセージオブジェクトを作成します。
gettext 呼び出し文字列を取得します
Oracle Solaris ツールと区別するために、GNU バリアントツールには g という文字が接頭辞として付き、/usr/gnu/bin ディレクトリへのシンボリックリンクになっています。たとえば、/usr/bin/ggettext は /usr/gnu/bin/gettext へのシンボリックリンクです。
GNU gettext ツールは text/gnu-gettext パッケージの一部で、このパッケージにはメッセージカタログの処理用のその他のユーティリティーも含まれています。
詳細は、msgcat(1)、msgcmp(1)、msgmerge(1) のマニュアルページを参照してください。