プログラムの出力メッセージの国際化について

最終更新: 1999.4.30


目次

  1. はじめに
  2. UNIXの国際化サポートとメッセージカタログ
  3. メッセージカタログの使用法 I
  4. メッセージカタログの使用法 II
  5. メッセージカタログの利用上の注意点
  6. MS-DOS上のメッセージカタログの実装
  7. おまけ
  1. 付録
  2. 参考文献
  3. リンク集

[目次][前節][次節]

1. はじめに

本稿では、アプリケーションプログラマを対象に、 プログラムの出力メッセージの国際化(多言語対応)の手法について解説します。 プラットフォームはUNIX(CUI)とMS-DOSです。

地域化(localization, L10N)

システムを特定の言語・地域・文化環境に適応させること。 ハードコーディングによる場合と、国際化による場合がある。 複数の環境に対応する場合は多地域化(multilocalization)という。

国際化(internationalization, I18N)

特定の言語・地域・文化環境に依存する部分を、 システムから分離・排除すること。 (多)地域化の手法の一つでもある。


[目次][前節][次節]

2. UNIXの国際化サポートとメッセージカタログ

UNIX上のCプログラミング環境における国際化サポートは、 ISO/ANSI Cのlocaleという概念をもとに構成されており、 その機能はおおむね以下のように分類されます。

  1. localeの設定とlocale固有情報の取得

    setlocale(3), localeconv(3)など

  2. マルチバイト文字・ワイド文字サポート (LC_CTYPE,LC_COLLATE)

    mbstowcs(3), strcoll(3)など

  3. 日付・時刻サポート(TZ,LC_TIME)

    strftime(3)など

  4. メッセージカタログ(LC_MESSAGES)

    catopen(3)など

  5. その他(LC_MONETARY,LC_NUMERIC)

    strfmon(3)など

本稿では4.を扱います。

localeとは、特定の言語や地域に依存する情報のことです。 本稿の範囲では、 localeとは英語や日本語といった言語の区別のことであると考えて差し支えありません。 ただし、同じ日本語でも、日本語EUCとシフトJISのようにコードセットが異なる場合は、 別のlocaleとして扱います。

localeはlocale名によって識別されます。 使用可能なlocaleは、システムのlocaleデータベースに登録されています。

locale名 locale
C デフォルト(英語)
en_US 英語・米国
en_GB 英語・英国
fr_FR フランス語・フランス
ja_JP.EUC 日本語・日本・EUC
ja_JP.SJIS 日本語・日本・シフトJIS

出力メッセージの多言語化とは、 プログラムが出力するメッセージの言語を実行時に選択できることをいいます。 一般に、以下のような方法によって実現されています。

  1. 言語ごとに別々のソースコード・実行ファイルを使用する。
  2. 各言語のメッセージをコードに埋め込み、実行時にユーザーに選択させる。
  3. メッセージをプログラムの外部に持ち、実行時にユーザーに選択させる。

1.や2.のようなハードコーディングによる方法では、 新たな言語を追加したり、メッセージを修正するたびに、 コードの変更と再コンパイルが必要となります。 これに対して、3.のような国際化による方法では、 再コンパイルなしで言語を選択・追加することができます。 これを実現するメカニズムを、メッセージカタログといいます。

XやWindowsなどのGUI環境では、一般にリソースというメカニズムがあり、 文字列やアイコンなどの情報をプログラムの外部にもたせることができます。 したがって、メッセージカタログは特に必要ありません。 ここでは、CUI環境でのメッセージカタログに対象を絞ります。

UNIXのメッセージカタログの仕様としては、X/OpenのXPG(X/Open Portability Guide)仕様インターフェースや、 SunOS/GNUのgettextインターフェースがあります。 このうち前者はPOSIXを補完する事実上の標準として広く採用されていますので、 これについて解説します。


[目次][前節][次節]

3. メッセージカタログの使用法 I

メッセージカタログを利用するプログラムの作成および実行にあたっては、 以下のような手順を踏みます。

ではさっそく、おなじみのHello Worldプログラムを例にとって、 実際の手順を見ていきます。

国際化されていない通常のプログラムは以下のようになっています。

hello.c:

#include <stdio.h>

void main (void)
{
	printf ("Hello, world.\n");
}

コンパイルと実行:

% cc -o hello hello.c

% ./hello
Hello, world

これを国際化します。

まず、メッセージテキストファイル(.msg)を作成します。 ここでは、日本語(ja_JP.EUC)とフランス語(fr_FR)をサポートすることにします。

hello.ja.msg:

1 世界よ、こんにちは。\n

hello.fr.msg:

1 Bonjour, tout le monde.\n

これをもとに、メッセージカタログファイル(.cat)を生成します。 格納先ディレクトリは/usr/lib/nls/$LANG/とします。

% gencat /usr/lib/nls/ja_JP.EUC/hello.cat hello.ja.msg
% gencat /usr/lib/nls/fr_FR/hello.cat     hello.fr.msg

一方、プログラムの方は次のようになります。

hello.c:

#include <stdio.h>
#include <nl_types.h>

void main (void)
{
	nl_catd catd;
	catd = catopen ("hello", 0);
	printf (catgets (catd, 1, 1, "Hello, world.\n"));
	catclose (catd);
}

コンパイルと実行:

% cc -o hello hello.c

% unsetenv LANG; ./hello
Hello, world

% env LANG=ja_JP.EUC ./hello
世界よ、こんにちは。

% env LANG=fr_FR ./hello
Bonjour, tout le monde.

% env LANG=C ./hello
Hello, world

% env LANG=No_Such_Locale ./hello
Hello, world

詳しい説明は後述しますが、だいたい何をやっているかは想像がつくことと思います。 なお、locale名やメッセージカタログのディレクトリ名はOSによって違いますので、 実際に試す場合は注意してください(ディレクトリは変更可能です)。 また、OSによってはlibxpg4などのライブラリをリンクする必要があります。

OS 日本語EUC フランス語 メッセージカタログ
SunOS5 ja fr /usr/lib/locale/%L/LC_MESSAGES/
FreeBSD ja_JP.EUC fr_FR.ISO_8859-1 /usr/share/nls/%L/
HP-UX japanese.euc french /usr/lib/nls/%L/
Digital UNIX ja_JP.eucJP fr_FR.ISO8859-1 /usr/lib/nls/msg/%L/

%L$LANGのことです(後述)。


[目次][前節][次節]

4. メッセージカタログの使用法 II

ここでは、メッセージカタログの使用法を詳しくみていきます。

4.1 メッセージテキストファイルの作成

プログラムで使用する文字列定数のうち、 翻訳する必要のあるもの(メッセージ)を抜き出し、 メッセージテキストファイルを作成します。 拡張子は何でもかまいませんが、通常は.msgとします。

$quote "
$set 1
1 "世界よ、こんにちは。\n"

メッセージテキストファイルの各行は、コマンド行またはメッセージ行です。 コマンド行には$に続いてコマンドを記述します。 メッセージ行にはメッセージ番号とメッセージを記述します。 空白やタブで始まる行、あるいは$と空白またはタブで始まる行はコメントとなります。

メッセージ番号は、プログラムからメッセージを取得する際のIDとして使われます。 これは1〜NL_MSGMAXの整数で、昇順に並んでいなければなりません。 番号とメッセージの間は空白かタブで区切ります。 $quoteで引用文字を指定している場合(後述)には、 引用文字でメッセージを囲みます。 デフォルトでは引用文字は使わず、メッセージをそのまま記述します。 メッセージを複数行にわたって記述したい場合、 \による継続行が使用できます。 その他、C言語と同様のエスケープ文字が使用可能です。

メッセージカタログ内のメッセージは、 任意にグループ化することができます。 これをセットといいます。 各メッセージカタログは1つ以上のセットを含み、 各セットは1つ以上のメッセージを含みます。 メッセージは、セット番号とメッセージ番号によって識別されます。 セットが異なれば、メッセージ番号が同じでも違うメッセージとなります。 セットを利用することで、メッセージを用途などによって分類し、 また、メッセージ番号の増大を抑えることができ、管理が容易になります。

コマンドは何種類かありますが、通常使うのは$quote$setです。

$quote [引用文字]

引用文字を指定し、あるいは取り消します。 引用文字が指定されている場合と、そうでない場合では、 メッセージ番号とメッセージとの間の空白文字の扱いが若干異なります。 デフォルトでは、引用文字は指定されていません。

$set セット番号

セット番号を1〜NL_SETMAXの範囲で指定します。 これ以降のメッセージは指定のセットに属します。 デフォルトのセット番号は1(NL_SETD)です。

4.2 メッセージカタログファイルの準備

gencat(1)により、メッセージテキストファイルをメッセージカタログファイルに変換します。 メッセージカタログファイルの拡張子は一般に.catです。

gencat メッセージカタログファイル [メッセージテキストファイル...]

メッセージカタログファイルがすでに存在する場合は、 メッセージテキストファイルの内容によって追加・更新します。

できたメッセージカタログファイルは、 所定のディレクトリ(OSによって異なります)に置きます。 ディレクトリは一般にlocale名によって分かれています。 なお、プログラムの実行時に、 環境変数NLSPATHによってディレクトリを指定することができます。 ホームディレクトリにカタログを置きたい場合などに便利でしょう。 NLSPATHに指定するディレクトリ名には、以下のような変数が使えます。

変数
%N メッセージカタログファイル名(catopen(3)の第1引数) hello
%L locale名 ja_JP.EUC
%l locale名の言語(language)部分 ja
%t locale名の地域(territory)部分 JP
%c locale名のコードセット(codeset)部分 EUC

メッセージカタログファイルは一般にバイナリファイルであり、 OS・機種間の互換性はありません。

4.3 メッセージカタログの利用

メッセージカタログファイルをオープンするには、catopen(3)を使います。

#include <nl_types.h>
nl_catd catopen (const char *name, int oflag);

nameはメッセージカタログファイル名です。 oflagは0を指定します。 これは、$LANGによってlocaleを決定することを意味します。 これにより、所定のディレクトリ(または$NLSPATHで指定されたディレクトリ)でメッセージカタログファイルを検索し、オープンします。 拡張子.catが自動的に付加されるようです。

成功した場合、カタログ記述子(ファイル記述子のようなもの)を返します。 失敗した場合は、(nl_catd)-1を返します。 ただし、エラーチェックをする必要は特にありません(後述)。

メッセージカタログからメッセージを取得するには、catgets(3)を使います。

#include <nl_types.h>
char *catgets(nl_catd catd, int set_num, int msg_num, const char *dfl_msg);

カタログ記述子catdの示すカタログの、 セット番号set_numのセットから、 メッセージ番号msg_numのメッセージを取得し、 そのメッセージへのポインタを返します。

dfl_msgには、 メッセージが取得できない場合に使われるデフォルトメッセージを指定します(通常これは英語です)。 引数の値が不正であるなどの理由でメッセージが取得できない場合、 catgets()dfl_msgを返します。 つまり、取得に成功すればそのメッセージが、 失敗すればデフォルトメッセージが得られます。

catopen()が失敗してcatdが-1になっている場合でも、 気にせずcatgets()を呼び出してかまいません。 この場合、常にdfl_msgが返されますので、 自動的にデフォルトメッセージを選択したことになります。

メッセージカタログをクローズするには、catclose(3)を使います。

#include <nl_types.h>
int catclose (nl_catd catd);

使用するカタログの数がNL_MAXOPENを超える場合は、 明示的にクローズする必要があります。

4.4 その他

OSによっては、perror(3)/strerror(3)が メッセージカタログによって国際化されている場合があります。

XPG3の仕様では、catopen(3)の第2引数oflagは0であり、 $LANGによってlocale名を決定します。 XPG4では、NL_CAT_LOCALEという値を指定することもでき、 この場合LC_MESSAGESカテゴリによってlocale名を決定します。 あらかじめsetlocale(3)を呼び出しておく必要があります。


[目次][前節][次節]

5. メッセージカタログの利用上の注意点

ここでは、拙作 mei/moeのメッセージカタログ対応化の経験をまじえながら、 注意点について述べます。

5.1 コーディングの注意

既存のコードを書き換える場合でも、あるいは新規に開発する場合でも、 文字列定数の代わりにcatgets()の呼び出しを記述することになりますので、 いくつか注意が必要です。

5.1.1 取得したメッセージの上書きに注意

catgets()により取得したメッセージは、 静的領域に置かれている可能性があります。 したがって、次のcatgets()の呼び出しの後は内容が保証されません。 たとえば、

printf (catgets(catd, NL_SETD, 1, "function: %s"),
        func == READ ?
        catgets(catd, NL_SETD, 2, "read") :
        catgets(catd, NL_SETD, 3, "write"));

などとすると、期待した結果が得られないことがあります。

こういう場合は、以下のようにする必要があります。

char msg2 [NL_TEXTMAX], msg3 [NL_TEXTMAX];
strcpy (msg2, catgets(catd, NL_SETD, 2, "read"));
strcpy (msg3, catgets(catd, NL_SETD, 3, "write"));
printf (catgets(catd, NL_SETD, 1, "function: %s"),
        func = READ ? msg2 : msg3);

5.1.2 初期化文字列の扱い

char msg1 [10] = "foo";

のような場合、msg1が自動変数なら

char msg1 [10];
strcpy (msg1, catgets (catd, NL_SETD, 1, "foo"));

でいいのですが、静的変数の場合はこれができませんので、 適宜変更する必要があります。

また、配列を初期化している場合、

char *ordinal [] = { NULL, "1st", "2nd", "3rd", "4th" };
printf (ordinal [i]);

以下のようなメッセージカタログを作り、

$set 2
1 "第1"
2 "第2"
3 "第3"
4 "第4"

次のようにするとスマートです。

printf (catgets (catd, 2, i, ordinal [i]));

このように、セットを利用すると、 一連のメッセージに連続したメッセージ番号を割り当てることが容易で、 しかも将来メッセージが増えても安心です。

5.1.3 メッセージカタログの使用・不使用の選択

メッセージカタログをサポートしないOSへの移植や、 サポートしていても何らかの理由で使わない場合などを考えると、 メッセージカタログを使うかどうかをコンパイル時に選択できるのが好ましいといえます。 そのためには、以下のようにするとよいでしょう。

#ifdef NLS
#include <locale.h>
#include <nl_types.h>
#else
#define catgets(i,sn,mn,s) (s)
#endif

void main (int argc, char **argv)
{
#ifdef NLS
	nl_catd catd;
	setlocale (LC_ALL, "");
	catd = catopen ("foo", 0);
#endif
	:
	:
	:
#ifdef NLS
	catclose (catd);
#endif
}

5.1.4 yes/no文字の取得

CUI環境のプログラムでは、ユーザーに対してyes/noの選択を求める際に、 y/nの文字を入力させるのが一般的です。 しかし、これもlocaleに従うほうが望ましいといえます。 たとえば、フランス語ではoui/nonですから、 o/nとなります。

これを実現するには、そのlocaleでのyes/noを表す文字(列)を取得する必要があります。 一般には、nl_langinfo(3)を使います。

#include <nl_types.h>
#include <langinfo.h>
int yes, no;
setlocale (LC_ALL, "");
yes = tolower (*nl_langinfo (YESSTR));
no  = tolower (*nl_langinfo (NOSTR ));

しかし、nl_langinfo(3)を持たないOSのことを考えて、 メッセージカタログで代用することもできます。

$set 3
1 oui
2 non

このようにlocaleに合ったメッセージカタログを作ります。

#include <nl_types.h>
int yes, no;
yes = tolower (*catgets (catd, 3, 1, "yes"));
no  = tolower (*catgets (catd, 3, 2, "no" ));

5.1.5 printfでの語順の変更

printfの書式指定文字列を翻訳した場合、 語順が変わるために後続の引数を入れ替える必要が生じることがあります。 たとえば、

printf ("error at offset %d in file %s\n", offset, filename);

これを自然な日本語にすると

printf ("ファイル%sのオフセット%dでエラー\n", filename, offset);

となります。 これは、書式指定文字列をcatgets()で取得するだけでは対応できず、 コードの変更を余儀なくされることになります。

このような状況に対応するため、printfの書式指定子が拡張されています。 これを利用すると、上記の例は、

printf ("ファイル%2$sのオフセット%1$dでエラー\n", offset, filename);

となります。%s%dの間にはさまっているn$は、 後続の引数のうちn番目のものを使うことを表しています。 ここでは、%2$sには2番目の引数であるfilenameが使われ、 %1$dには1番目の引数であるoffsetが使われます。 この機能を使うことにより、翻訳で語順が変わっても、 printfの引数の順序を変更する必要はなく、 書式指定文字列をcatgets()で書き換えるだけですみます。

なお、一つの書式指定文字列の中で、 上記の形式の書式指定子と通常の書式指定子を混在させることはできません。

scanfにも同様の拡張機能がありますが、 こちらはあまり使うことはないと思われるので割愛します。

5.1.6 シェルスクリプトでの利用

メッセージカタログは通常、 Cで記述したアプリケーションから利用する機能ですが、 できればシェルスクリプトでも利用したいところです。 一部のOSでは、シェルスクリプトからメッセージカタログを利用するための dspmsg(1)というコマンドがあります。

dspmsg [-s セット番号] カタログ名 メッセージ番号
	['デフォルトメッセージ' [引数...]]

指定のメッセージをカタログから取得し、標準出力に出力します。

メッセージの中には、printfのように%s (または%n$s)を含むことができ、 対応する後続の引数で置き換えて表示されます。

5.2 メッセージカタログ作成の注意

XPGのメッセージカタログのメカニズムは、いささか原始的であり、 プログラマの負担を抑えるためには工夫が必要です。

5.2.1 メッセージ番号の自動生成

メッセージを番号で指定しなければならないというのはかなり大変です。 せめて記号定数を使いたいところです。 これを実現するために、一部のOSにはmkcatdefs(1)というプリプロセッサがあります。 これは、メッセージ番号の代わりに記号定数を使った形式のメッセージテキストファイルを入力とし、 記号定数を適当なメッセージ番号で置き換えて出力します。 さらに、記号定数とメッセージ番号の対応をヘッダファイルとして出力します。

5.2.2 デフォルトメッセージの扱い

デフォルトメッセージ(C locale用のメッセージ)は、 catgets()の引数という形でコード中に埋め込まれますので、 メッセージテキスト/カタログを作成する必要は本来ありません。 しかし、デフォルトメッセージのメッセージテキストがリファレンスとして用意されていないと、 他のlocaleのメッセージテキストの翻訳・作成作業が困難ですので、 実際にはメッセージテキストは必要になります。 また、他のlocaleとの扱いを統一するという観点から、 C localeに対してもメッセージカタログを作成することもありえます。

さて、そうなると、ソースコード中のデフォルトメッセージと、 デフォルトメッセージのメッセージテキストとの間で、 メッセージ内容を同一に保たなくてはなりません。 それには、一方から他方を自動生成するのが確実です。 そこで、両方の場合を比較検討してみましょう。

ソースコードからメッセージテキストを生成

ソースコード中の文字列定数 (すでにメッセージカタログ対応化されている場合は、catgets()の引数) を抜き出し、メッセージテキストを生成します。

printf (catgets (catd, 1, 1, "Hello, world\n"));
strcpy (yesstr, catgets (catd, 1, 2, "yes"));
fp = fopen ("/etc/passwd", "rt");

$set 1
1 Hello, world\n
2 yes
メッセージテキストからソースコード(用のデフォルトメッセージ定義)を生成

メッセージテキストの文字列をマクロ定義するヘッダファイルを生成します。

$set 1
1 Hello, world\n
2 yes

#define MSG_1_1 "Hello, world\n"
#define MSG_1_2 "yes"

printf (catgets (catd, 1, 1, MSG_1_1));
strcpy (yesstr, catgets (catd, 1, 2, MSG_1_2));
fp = fopen ("/etc/passwd", "rt");

前者の方法が一般的ですが、mei/moeでは、 以下のような理由により、後者の方法を採用しています。

5.3 メッセージカタログ対応支援ツール

最近の商用UNIXシステムでは、メッセージカタログの作成や 既存プログラムのメッセージカタログ対応を支援するための ツールが付属していることがあります。 ここでは、HP-UXとDigital UNIXを例にとり、 そういったツールの機能を概観することによって、 作業の流れを見ていくことにします。

5.3.1 HP-UXの場合

5.3.2 Digital UNIXの場合


[目次][前節][次節]

6. MS-DOS上のメッセージカタログの実装

MS-DOSアプリケーション(とくにCUIアプリケーション)の多言語化は、 一般に、以下のようなハードコーディングによって実現されています。

筆者の知る限り、MS-DOS上でメッセージカタログなどの国際化の手法を用いて多言語化したアプリケーションの例はありません。 そもそも、メッセージカタログを実装した例すらありません。

mei/moeの多言語化にあたって、 UNIX版ではメッセージカタログを使用しました。 MS-DOS版もソースコードは共通ですので、 UNIX版と同じ手法で国際化するのが正当な方法といえます。 そのためには、メッセージカタログを実装する必要があります。 また、他人がやっていないことをやるのはそれ自体において愉快なことです:-)

そんなわけで、国際化サポートの基礎となるsetlocale(3)や、 XPG仕様メッセージカタログのサブセットをMS-DOS上に実装しました。 以下に実装上の特徴を述べます。


[目次][前節][次節]

7. おまけ

本稿では出力メッセージの国際化という高尚なテーマについて解説してきました。 重要な点は、プログラムコードを修正することなく、 メッセージの表記を切り替えることができ、 さらにユーザーがメッセージカタログを追加・修正することができるというところです。

しかし、勘の鋭い人はお気づきの通り、 この手法は異なる方面への応用が考えられます。 すなわち、メッセージを特定の人物の口調に変更することが容易になるということです(笑)。 もはや、バイナリパッチをあてたり、ソースを書き換えたりする必要はありません。 メッセージカタログを用意するだけでいいのです。 場合によってはlocaleを新設する必要がありますが、 それもたいていは新規ディレクトリを作る程度で済みます。

実際にそのような応用を行っている例として、 tcshの日本語メッセージカタログがあります。


[目次][前節][次節]

付録

付録1. locale関連機能のサポート状況

マルチバイト文字・ワイド文字関連は除く。

機能名FreeBSD 2.1.5SunOS 4.1SunOS 5.3GNUHP-UX 9.0Digital UNIX 3.2AIX 3.2備考
locale基本機能
setlocale(3)○(3V)
localeconv(3)
nl_langinfo(3)×
XPGメッセージカタログライブラリ
catopen(3)×
catgets(3)×
catgetmsg(3)×××××
catclose(3)×
printf(3) %n$××
scanf(3) %n$××
perror(3) NLS××
strerror(3) NLS×
XPGメッセージカタログ関連コマンド
gencat(1)×
dspcat(1)×××××.catからメッセージを取り出す
dspmsg(1)×××××シェルスクリプト用
mkcatdefs(1)×××××.catの記号定数をメッセージ番号に変換
runcat(1)×××××mkcatdefs|gencat
findmsg(1)××××××Cソース中のマークされた文字列から.catを生成
dumpmsg(1)××××××gencatの逆
findstr(1)××××××Cソース中の文字列定数を抜き出す
insertmsg(1)××××××findstrの出力を元にCソースにcatgets()呼び出しを埋め込む
extract(1)××××××Cソース中の文字列定数をcatgets()呼び出しに変換
strextract(1)××××××Cソース中の文字列定数を抜き出す
strmerge(1)××××××strextractの出力を元にCソースにcatgets()呼び出しを埋め込む
trans(1)××××××.msgの翻訳用スクリーンエディタ
patterns(4)××××××extract(1)等の変換パターンを定義
Sun/GNUメッセージカタログライブラリ
gettext(3)××××
dgettext(3)×××××
dcgettext(3)××××××
textdomain(3)××××
bindtextdomain(3)×××××
Sun/GNUメッセージカタログ関連コマンド
xgettext(1)×××××Cソース中の文字列定数を抜き出し.poを生成
msgfmt(1)××××××.poから.moを生成
msgmerge(1)××××××ソースの変更を.poに反映
installtxt(8)××××××
SVR4 MNLS
setcat(3)×××××××
gettxt(3)×××××
gettxt(1)××××××gettxt(3)のコマンド版
exstr(1)××××××Cソース中の文字列定数を抜き出しgettxt(3)呼び出しに変換
mkmsgs(1)××××××gettxt(3)用のメッセージデータベースを生成
srchtxt(1)××××××メッセージデータベースを検索
その他
LC_MESSAGES×
locale.h
nl_types.h××
langinfo.h×
msgcat.h××××××
libintl.h×××××
locale(1)×××
localedef(1)×××○(1M)
rpmatch(3)×××××
strftime(3)
strptime(3)×××
strfmon(3)×××××
locale(4)×○(5)××
charmap(4)×××
langinfo(5)××××
environ(5)×
ベンダー固有機能
機能名FreeBSDSunOS 4.xSunOS 5.xGNUHP-UXDigital UNIXAIX備考
mklocale(1)××××××
colldef(1)××××××
nl_init(3)×××××
chrtbl(1M)××××××
nl_types(5)××××××
nlsinfo(1)××××××
buildlang(1M)××××××
langinfo(3)××××××
nl_tools_16(3)××××××
printmsg(3)××××××
localedef(4)××××××
hpnls(5)××××××
lang(5)××××××

付録2. メッセージカタログのディレクトリ

FreeBSD /usr/share/nls/%L/%N.cat
SunOS 4 /usr/lib/locale/%L/LC_MESSAGES/%N.cat
SunOS 5 /usr/lib/locale/%L/LC_MESSAGES/%N.cat
/usr/lib/locale/%L/LC_MESSAGES/%N.mo
SVR4 MNLS /usr/lib/locale/%L/LC_MESSAGES/%N
GNU /usr/share/%L/LC_MESSAGES/%N.po
HP-UX /usr/lib/nls/%L/%N.cat
Digital UNIX /usr/lib/nls/msg/%L/%N.cat
AIX /usr/lib/nls/msg/%L/%N.cat

付録3. SunOS 4.xでのXPGメッセージカタログの使用法

SunOS 4.xは現在でも広く使われていますが、古いBSD系のOSであるため、 XPGメッセージカタログのサポートが弱く使用には注意が必要です。 基本的には、/usr/xpg2include/nl_types.hをインクルードし、 /usr/xpg2lib/libxpg.aをリンクします。

簡単な方法は、コンパイラとして/usr/xpg2bin/ccを使うことです (これは/usr/5bin/cc-I/usr/xpg2include -L/usr/xpg2lib -lxpgで呼ぶのと等価です)。 しかし、これではソースをK&Rスタイルで書かなければならず、 またSystem V仕様のライブラリが使われるなど不都合な場合があります。

gccで使う場合、 単に-I/usr/xpg2include#include <nl_types.h>としたのでは、 他のヘッダファイルも/usr/xpg2includeからインクルードされてしまい不都合なので、 nl_types.hをフルパスでインクルード (#include </usr/xpg2include/nl_types.h>)するか、 -idirafter /usr/xpg2includeとします。 さらに、catopen/catclose/catgetsのプロトタイプ宣言がないので、 明示的に補って使用します。 リンクも、libxpg.a/usr/5libのライブラリを前提としているため、 単に-L/usr/xpg2lib -lxpgとだけすると不都合が生じる (libxpg.amalloc()/usr/5lib/libc.a_assert()を要求するなど)ので、 -L/usr/xpg2lib -lc -lxpgとします。

なお、JLE(Japanese Language Extensions)のマニュアルページによれば、 JLEではXPGメッセージカタログはサポートされていません。 具体的には、libxpg.agettext.oが必要とする関数や変数が、 libcsetlocale.oから削られているため、 リンクすることができません。 ただし非JLE環境でリンクしたバイナリの運用は可能なようです。


[目次][前節][次節]

参考文献


[目次][前節][次節]

リンク集


[目次]

Copyright (C) 1998 ITO Takayuki, All rights reserved.