1996年9月 Locales mini-HOWTO Peeter Joot, joot@ecf.toronto.edu 著 松田 員幸 訳 v1.3, 6 June 1996. このドキュメントでは、Linux マシンで locale を使用するための設定方法に ついて説明します。 [ 訳注:locale は「ロケール」とも「ロカール」とも表 記されることがあります。どちらでも間違いではないのですが、ここでは locale と英語のままで表記します。] 1. はじめに これは、私が localedef をインストールし、locale をコンパイルして試して みるためにしなければならなかったことを説明してるだけです。私はただ楽し みとしてやってみましたが、おそらくちゃんと試すことに興味がある人もいる でしょう。一度設定すれば、自分が選択した locale で、NLS を利用できるア プリケーションを使えるようになるでしょう。しばらくすれば locale サポー トは標準配布の一部となり、この mini-HOWTO のほとんどは無用の長物となる でしょう。[ 訳注:現時点では Linux のライブラリは日本語の扱える locale をサポートしていないようです。だからこのドキュメントの翻訳を読む人に とって、この情報はきっと役に立たないでしょう。] 2. とりあえず "locale" とは何でしょう? locale は、プログラムにハードコーディングすべきでない、言語や文化に特 有のいくつかのものを隠蔽します。 自分のコンピュータに複数の locale がインストールされているなら、下記の 環境変数によって locale を考慮するプログラムのふるまいを選択できます。 デフォルトの locale は C あるいは POSIX で、これは libc の中にハードコ ーディングされています。 LANG これは locale を設定しますが、他の LC_xxxx という環境変数によっ て上書きされます。 LC_COLLATE 並べかえ(ソート)の順番です。 LC_CTYPE 文字定義、大文字、小文字など。これらは toupper、tolower、 islower、isdigit のような関数で用いられます。 [訳注:man 3 isalpha 参照のこと。] LC_MONETARY 期待される形式で貨幣単位をフォーマットするのに必要な情報を含みま す。それは千の区切り文字、小数点区切り文字、通貨記号を意味するも のやその位置を定義します。 LC_NUMERIC 期待される千、小数点区切り文字、数字集合です。 LC_TIME 時刻、日付を指定する方法です。これは曜日、短縮形/非短縮形での月 のようなものです。 LC_MESSAGES 特に言うことはありません。 LC_ALL これは locale を設定し、他の LC_xxxx 環境変数に上書きされます。 いくつかの他の locale を示します。他にもたくさんあります。 en_CA English Canadian. en_US US English. de_DE Germany's German. fr_FR France's French. [訳注:日本語関係は ja,ja_JP,ja_JP.eucJP,ja_JP.SJIS,ja_JP.JIS7 等] あなたがプログラムを書いていて、国際的に利用されることを望むなら、 locale を使うべきです。そのもっとも大きな理由は、誰もがあなたと同じ文 字セットやコードページを使おうとしているわけではないということです。 プログラムの中で以下のようなことをしないように。 /* check for alphabetic characters */ if ( (( c >= 'a') && ( c <= 'z' )) || (( c >= 'A') && ( c <= 'Z' )) ) { ... } もしこんなプログラムを書くなら、そのプログラムは、/user/file/... は ASCII で、ASCII 以外のなにものでもないことを仮定しており、ユーザの locale のコードページ定義を尊重していません。例えば、ドイツ語環境では a-ウムラウトのような文字で始まります。代わりに、isalpha() のような locale 依存関数を用いるべきです。もしプログラムがはっきりと US-ASCII アルファベットだけを使うことを要求している場合も、isalpha() 関数を用い ますが、その場合は、setlocale(LC_CTYPE,"C") を実行し、LANG、 LC_CTYPE、LC_ALL 環境変数を "C" に設定しなければなりません。 locale を使えば非常に融通が効き、プログラマは ASCII ベースの C プログ ラムを書くときにしていたかもしれないある種の仮定ができなくなります。 たとえば、文字のコード位置を仮定することはできません。'A' のコード位置 を 0x41 ではなく 0xC1 に定義する charmap ファイルを作ることを何ものも 止めることはできません。これは実際にメインフレームで用いられる IBM コ ードページ 37 で、'A' のコード位置マッピングです。一方前者は、 US- ASCII、iso8859-x などで用いられています。 基本的な考えは、異なる人々が異なる言語を話し、異なる並べかえ順を想定 し、異なるコードページを用い、異なる国に住んでいることです。locale と locale に依存するプログラムはそれを尊重し、それに応じた扱いをするよう に意図されています。そうするのに格別の努力はいりませんし、プログラムを 書くときにちょっと気分を変えるだけでよいのです。 3. ノート o 自分のマシンで locale を設定するためには、いくつかのものをアップグ レードする必要があります。ftp.tu-clausthal.de:/pub/linux/SLT/nls に locale と localedef の a.out 版が(nlsutils-0.5.tar.gzという名前で) あるようです。で、ELF システムを持っていないか、ELF が欲しくないな ら、これを使うことができます。たぶんどこか他のところで nlsutils パッケージのコピーがあるでしょう。しかし、私はそれを見つけていませ ん [ 訳注:国内にはないようですが、debian パッケージには .deb の形 で入っているようです ] 。私は locale と localedef のスタンドアロン 版を聞いたことがありませんが、対応する libc をインストールしなけれ ばならないことは考慮にいれておいて下さい。ですからこの HOWTO の大部 分は 私が libc とそのファミリーをアップグレードするためにしなければ ならなかったことの記録でしかありません。もしあなたが libc をインス トールするなら、私がしたように ELF システムを走らせ、locale をセッ トアップするときに ELF に移行する必要があります。 o 私が行なったシステム移行の内容は、a.out から ELF への移行ですべきこ とと同じです。ELF に移行していないか、Linux の再インストールで ELF に移行しているなら、sunsite のミラーから最新の ELF HOWTO をもってき てください。これはすばらしいガイドで、libc、ld.so、などの ELF シス テムへの移行をインストールするためのガイダンスでもあります。 o 何をインストールするにしても、適当なリリースノートや README などの ファイルを読んでください。もし、ここで私が書いたことを誤解したり、 (そうでないことを願うけど)私がここで書いたことを実行することであな たのシステムをぐちゃぐちゃにしてしまっても、どうか私を責めないで下 さい。 [ 訳注:そして、できれば翻訳者も責めないでください。 ] o 新しい libc や ld.so のインストールを間違えると、ブートできないシス テムにしてしまうことがあります。ブードディスクをつくっておくべき で、消えてしまうと取り返しのつかない重要なデータは必ずバックアップ しておくように。 4. 必要なもの 2、3のものをいろいろな場所からダウンロードする必要があります。ここに ある locale ソースファイルを除くすべてのものは sunsite.unc.edu、 tsx-11.mit.edu、なるべくならこれらのサイトのミラーから得ることができま す。 [ 訳注:国内では sunsite.sut.ac.jp,ftp.sra.co.jp など。 locale 関 係以外では ftp.kuis.kyoto-u.ac.jp も使えます。どうせなら kernel を 2.0.x にしてしまってもっと新しいライブラリを使ったほうがよいでしょ う。linux-2.0.x/Documentation/Changes を参照のこと。 ] o locale と charmap のソース --- localedef を使ってコンパイルするもの です。 o libc-5.2.18.bin.tar.gz --- c と math ライブラリに対する ELF 共有ラ イブラリです。 o libc-5.2.18.tar.gz --- ELF 共有ライブラリのソースコードです。 localedef コンパイルするのにこれが必要です。 o make-3.74.tar.gz --- dirent のバグを修正するためのパッチを合体する ためにコンパイルする必要があります。 o release.libc-5.2.18 --- これらのリリースノートには make を作成する ためのパッチがあります。 o ld.so-1.7.12+ --- ダイナミック・リンカです。 o ELF gcc-2.7.2+ --- コンパイルに必要です。 o ELF kernel 1.1.92+, or ELF kernel 1.3.40+ --- コンパイルに必要で す。 o binutils 2.6.0.2+ --- コンパイルに必要です。 locale のソースを入手できるサイトはたぶんたくさんあります。私が知って いる範囲では次のサイトで locale と charmap のソースを入手できます。 dkuug.dk:/i18n/WG15-collection/locales dkuug.dk:/i18n/WG15-collection/charmaps -- [ 訳注:日本語の locale は XFree86 にも入っています。 ] -- 5. 全てのものをインストールする これは全てをインストールするためのものです。私はすでにこれを行なう前に インストールした ELF システム(コンパイラ、カーネルなど...)を持っていま す。 1. まず、binutils パッケージをインストールしました。 tar xzf binutils-2.6.0.2.bin.tar.gz -C / 2. 次にダイナミック・リンカをインストールしました: tar zxf ld.so-1.7.12.tar.gz -C /usr/src cd /usr/src/ld.so-1.7.12 sh instldso.sh 3. 次に libc バイナリをインストールしました。詳しい手順は libc-5.2.18 のリリースノートを参照してください。 rm -f /usr/lib/libc.so /usr/lib/libm.so rm -f /usr/include/iolibio.h /usr/include/iostdio.h rm -f /usr/include/ld_so_config.h /usr/include/localeinfo.h rm -rf /usr/include/netinet /usr/include/net /usr/include/pthread tar -xzf libc-5.2.18.bin.tar.gz -C / 4. 新しい共有ライブラリを認識させるために ldconfig を実行する必 要があります。 ldconfig -v 5. libc には make やいくつかのプログラムを壊すバグがあります。私 は次のように make を再構築し、インストールしました: [ 訳注: 新しい libc で使える make-3.74 のバイナリもあります ] tar zxf make-3.74.tar.gz -C /usr/src cd /usr/src/make-3.74 patch < /whereever_you_put_it/release.libc-5.2.18 configure --prefix=/usr sh build.sh ../make install cd .. rm -rf make-3.74 6. さあ、これで localedef をコンパイル、インストールできます。 mkdir /usr/src/libc tar zxf libc-5.2.18.tar.gz -C /usr/src/libc cd /usr/src/libc cd include ln -s /usr/src/linux/include/asm . ln -s /usr/src/linux/include/linux . cd ../libc ../configure # 私はこの2回の make が必要なことかどうかは自信がありませ # んが、安全のためにやっているだけです。 make clean ; make depend cd locale make programs mv localedef /usr/local/bin mv locale /usr/local/bin 7. localedef がそれらを見つけるところに charmap を置いて下さい。 これは charmap.tar として dkuug.dk ftp サイトからダウンロード できる、 charmap と locale ソースを用います。 tar xf charmaps.tar -C /tmp mkdir /usr/share/nls mkdir /usr/share/nls/charmap mkdir /usr/share/locale mv /tmp/charmaps/* /usr/share/nls/charmap rm -rf /tmp/charmaps tar xf locales.tar -C /usr/share # 好きなところに置いてください # # locale ソースのいくつかは `copy' を使い、これは他の # locale に依存します。私は以下のコマンドを作成するための # makefile を grep、cut、sed を使って作成しました。これは # /usr/share/locale ディレクトリにある全ての locale オブ # ジェクトを作成します。 # localedef -ci locales/en_DK -f ISO_8859-1:1987 en_DK localedef -ci locales/sv_SE -f ISO_8859-1:1987 sv_SE localedef -ci locales/fi_FI -f ISO_8859-1:1987 fi_FI localedef -ci locales/sv_FI -f ISO_8859-1:1987 sv_FI localedef -ci locales/ro_RO -f ISO_8859-1:1987 ro_RO localedef -ci locales/pt_PT -f ISO_8859-1:1987 pt_PT localedef -ci locales/no_NO -f ISO_8859-1:1987 no_NO localedef -ci locales/nl_NL -f ISO_8859-1:1987 nl_NL localedef -ci locales/fr_BE -f ISO_8859-1:1987 fr_BE localedef -ci locales/nl_BE -f ISO_8859-1:1987 nl_BE localedef -ci locales/da_DK -f ISO_8859-1:1987 da_DK localedef -ci locales/kl_GL -f ISO_8859-1:1987 kl_GL localedef -ci locales/it_IT -f ISO_8859-1:1987 it_IT localedef -ci locales/is_IS -f ISO_8859-1:1987 is_IS localedef -ci locales/fr_LU -f ISO_8859-1:1987 fr_LU localedef -ci locales/fr_FR -f ISO_8859-1:1987 fr_FR localedef -ci locales/de_DE -f ISO_8859-1:1987 de_DE localedef -ci locales/de_CH -f ISO_8859-1:1987 de_CH localedef -ci locales/fr_CH -f ISO_8859-1:1987 fr_CH localedef -ci locales/en_CA -f ISO_8859-1:1987 en_CA localedef -ci locales/fr_CA -f ISO_8859-1:1987 fr_CA localedef -ci locales/fo_FO -f ISO_8859-1:1987 fo_FO localedef -ci locales/et_EE -f ISO_8859-1:1987 et_EE localedef -ci locales/es_ES -f ISO_8859-1:1987 es_ES localedef -ci locales/en_US -f ISO_8859-1:1987 en_US localedef -ci locales/en_GB -f ISO_8859-1:1987 en_GB localedef -ci locales/en_IE -f ISO_8859-1:1987 en_IE localedef -ci locales/de_LU -f ISO_8859-1:1987 de_LU localedef -ci locales/de_BE -f ISO_8859-1:1987 de_BE localedef -ci locales/de_AT -f ISO_8859-1:1987 de_AT localedef -ci locales/sl_SI -f ISO_8859-2:1987 sl_SI localedef -ci locales/ru_RU -f ISO_8859-5:1988 ru_RU localedef -ci locales/pl_PL -f ISO_8859-2:1987 pl_PL localedef -ci locales/lv_LV -f BALTIC lv_LV localedef -ci locales/lt_LT -f BALTIC lt_LT localedef -ci locales/iw_IL -f ISO_8859-8:1988 iw_IL localedef -ci locales/hu_HU -f ISO_8859-2:1987 hu_HU localedef -ci locales/hr_HR -f ISO_8859-4:1988 hr_HR localedef -ci locales/gr_GR -f ISO_8859-7:1987 gr_GR 6. さあ、どうだ すべて済めば、作成された locale を使うことができるでしょう。以下は単純 な例題プログラムです。 /* test.c : a simple test to see if the locales can be loaded, and * used */ #include #include #include main(){ time_t t; struct tm * _t; char buf[256]; time(&t); _t = gmtime(&t); setlocale(LC_TIME,""); strftime(buf,256,"%c",_t); printf("%s\n",buf); } 現在の locale 環境変数設定がどうなっているかを locale プログラムを使っ て見ることができます。 $ # compile the simple test program above, and run it with $ # some different locale settings $ gcc -s -o Test test.c $ # see what the current locale is : $ locale LANG=POSIX LC_COLLATE="POSIX" LC_CTYPE="POSIX" LC_MONETARY="POSIX" LC_NUMERIC="POSIX" LC_TIME="POSIX" LC_MESSAGES="POSIX" LC_ALL= $ # Ho, hum... we're using the boring C locale $ # let's change to English Canadian: $ export LC_TIME=en_CA $ Test Sat 23 Mar 1996 07:51:49 PM $ # let's try French Canadian: $ export LC_TIME=fr_CA $ Test sam 23 mar 1996 19:55:27 7. catopen のバグ修正 locale をインストールすると、Linux libc の catopen コマンドにあるバグ (仕様か?)が修正されます。メッセージ・カタログを使うプログラムを作成 し、ドイツ語カタログを作り、それを /home/peeter/catalogs/de_DE におく としましょう。 以下のことを de_DE locale をインストールしないで行なってみてください: export LC_MESSAGES=de_DE export NLSPATH=/home/peeter/catalogs/%L/%N.cat:$NLSPATH ドイツ語のメッセージ・カタログがオープンできず、catgets コールのデフォ ルトのメッセージが使われます。 これは catopen が正しいメッセージ・カテゴリを得るために setlocale コー ルを実行し、環境変数が設定されていても setlocale が失敗する理由です。 それで catopen は NLSPATH の全ての "%L" に "C" を代入してメッセージ・ カタログをロードしようとします。 locale をインストールしなくてもメッセージ・カタログを用いることはでき ますが、以下のように NLSPATH の "%L" 部分をはっきりと設定する必要があ るでしょう: export NLSPATH=/home/peeter/catalogs/de_DE/%N.cat:$NLSPATH しかし、これは locale カテゴリ環境変数の全ての目的をくじけさせてしまい ます。 8. Q & A このセクションは FAQ に成長するかもしれませんが、本当はまだそうではあ りません。 8.1. msgcat の質問 私は LINUX のユーザで、以下のテストプログラムを書きました: -------------------------------------------------------------------- #include #include #include #include main(int argc, char ** argv) { nl_catd catd; setlocale(LC_MESSAGES, ""); catd = catopen("msg", MCLoadBySet); fprintf(stderr,catgets(catd, 1, 1, "locale message fail\n")); catclose(catd); } -------------------------------------------------------------------- $ msg.m $set 1 1 locale message pass\n -------------------------------------------------------------------- もし catopen("/etc/locale/msg.cat",MCLoadBySet); のように catopen で絶 対パスを使えば、正しい結果が得られます。しかし、上の例のようにすると catopen は -1 を返します(失敗します)。 8.2. msgcat の答え この質問については前のセクションがある程度答になっていますが、もう少し 付け加えておきます。 メッセージをカタログに置くのに適切な場所はたくさんあります。(メッセー ジ・カタログの場所を設定する) NLSPATH 環境変数が明示的に設定されていな くても、libc の中で次のように定義されてます: $ strings /lib/libc.so.5.2.18 | grep locale | grep %L /etc/locale/%L/%N.cat:/usr/lib/locale/%L/%N.cat:/usr /lib/locale/%N/%L:/usr/share/locale/%L/%N.cat:/usr/ local/share/locale/%L/%N.cat これができたら次のうちの1つをやってみてください: $ export LC_MESSAGES=en_CA $ export LC_ALL=en_CA $ export LANG=en_CA メッセージ・カタログが次のどれかにコピーされているなら、上記の NLSPATH と指定された環境で、catopen("msg", MCLoadBySet); はうまく動くでしょ う。 /etc/locale/en_CA/msg.cat /usr/lib/locale/en_CA/msg.cat /usr/lib/locale/msg/en_CA /usr/share/locale/en_CA/msg.cat /usr/local/share/locale/en_CA/msg.cat しかし、もし en_CA locale がインストールされていなければ、setlocale は 失敗するためにうまくいかず、catopen ルーチンで (en_CAではなく) "C" が "%L" に代入されるでしょう。 9. フィナーレ 以上です。願わくばこのガイドがあなたの助けとなって欲しいと思います。 locale 依存のプログラムを書くために、さらなる情報を探すことができる場 所はおそらくたくさんあるでしょう。libc の info ページに情報がいくつか ありますし、man ページはいつでも見ることができます。ちょっとWWWページ を漁れば、たくさんの情報を見つけることができるでしょう。国際化プログラ ミングに対する良い情報源を見つけたら、お知らせ下さい。そうすればそれら をこの HOWTO に反映することができます。