<!doctype linuxdoctr system>
<article>
<title>Locales mini-HOWTO</title>
<author>Peeter Joot, joot@ecf.toronto.edu</author>
<date>v1.3, 6 June 1996</date>
<trans>松田員幸, kazm@ca2.so-net.or.jp</trans>
<tdate>v1.3j, 22 October 1996</tdate>

<![IGNORE[
  1996年9月 Locales mini-HOWTO
  Peeter Joot, joot@ecf.toronto.edu 著
  松田 員幸 &lt;kazm@ca2.so-net.or.jp&gt; 訳
  v1.3, 6 June 1996.
]]>

<abstract>
このドキュメントでは、Linux マシンで locale を使用するための設定方法に
ついて説明します。 &lsqb; 訳注：locale は「ロケール」とも「ロカール」とも表
記されることがあります。どちらでも間違いではないのですが、ここでは 
locale と英語のままで表記します。&rsqb;
</abstract>

<p>
JF より：この文書の内容は、最終更新日 1996年10月22日でのものです。
現在とは異なる場合があるので、ご注意ください。
</p>

<sect>はじめに
<p>
これは、私が localedef をインストールし、locale をコンパイルして試して
みるためにしなければならなかったことを説明してるだけです。私はただ楽し
みとしてやってみましたが、おそらくちゃんと試すことに興味がある人もいる
でしょう。一度設定すれば、自分が選択した locale で、NLS を利用できるア
プリケーションを使えるようになるでしょう。しばらくすれば locale サポー
トは標準配布の一部となり、この mini-HOWTO のほとんどは無用の長物となる
でしょう。

&lsqb; 訳注：現時点では Linux のライブラリは日本語の扱える locale
をサポートしていないようです。だからこのドキュメントの翻訳を読む人に
とって、この情報はきっと役に立たないでしょう。&rsqb;
</sect>

<sect>とりあえず "locale" とは何でしょう？
<p>
locale は、プログラムにハードコーディングすべきでない、言語や文化に特
有のいくつかのものを隠蔽します。

自分のコンピュータに複数の locale がインストールされているなら、下記の
環境変数によって locale を考慮するプログラムのふるまいを選択できます。
デフォルトの locale は C あるいは POSIX で、これは libc の中にハードコ
ーディングされています。

<tscreen><verb>
LANG
   これは locale を設定しますが、他の LC_xxxx という環境変数によっ
   て上書きされます。

LC_COLLATE
   並べかえ(ソート)の順番です。

LC_CTYPE
   文字定義、大文字、小文字など。これらは toupper、tolower、
   islower、isdigit のような関数で用いられます。 &lsqb;訳注：man 3
   isalpha 参照のこと。&rsqb;

LC_MONETARY
   期待される形式で貨幣単位をフォーマットするのに必要な情報を含みま
   す。それは千の区切り文字、小数点区切り文字、通貨記号を意味するも
   のやその位置を定義します。

LC_NUMERIC
   期待される千、小数点区切り文字、数字集合です。

LC_TIME
   時刻、日付を指定する方法です。これは曜日、短縮形／非短縮形での月
   のようなものです。

LC_MESSAGES
   特に言うことはありません。

LC_ALL
   これは locale を設定し、他の LC_xxxx 環境変数に上書きされます。
</verb></tscreen>

  いくつかの他の locale を示します。他にもたくさんあります。

<tscreen><verb>
en_CA
   English Canadian.

en_US
   US English.

de_DE
   Germany's German.

fr_FR
   France's French.
</verb></tscreen>

&lsqb;訳注:日本語関係は <tt>ja,ja_JP,ja_JP.eucJP,ja_JP.SJIS,ja_JP.JIS7</tt> 
等&rsqb;

あなたがプログラムを書いていて、国際的に利用されることを望むなら、
locale を使うべきです。そのもっとも大きな理由は、誰もがあなたと同じ文
字セットやコードページを使おうとしているわけではないということです。

プログラムの中で以下のようなことをしないように。

<tscreen><verb>
/* check for alphabetic characters */
if ( (( c &gt;= 'a') &amp;&amp; ( c &lt;= 'z' )) ||
     (( c &gt;= 'A') &amp;&amp; ( c &lt;= 'Z' )) ) { ... }
</verb></tscreen>

もしこんなプログラムを書くなら、そのプログラムは、<tt>/user/file/...</tt> は
ASCII で、ASCII 以外のなにものでもないことを仮定しており、ユーザの
locale のコードページ定義を尊重していません。例えば、ドイツ語環境では
a-ウムラウトのような文字で始まります。代わりに、<tt>isalpha()</tt> のような
locale 依存関数を用いるべきです。もしプログラムがはっきりと US-ASCII
アルファベットだけを使うことを要求している場合も、<tt>isalpha()</tt> 関数を用い
ますが、その場合は、<tt>setlocale(LC_CTYPE,"C")</tt> を実行し、<tt>LANG</tt>、
<tt>LC_CTYPE</tt>、<tt>LC_ALL</tt> 環境変数を "<tt>C</tt>" に設定しなければ
なりません。

locale を使えば非常に融通が効き、プログラマは ASCII ベースの C プログ
ラムを書くときにしていたかもしれないある種の仮定ができなくなります。

たとえば、文字のコード位置を仮定することはできません。'<tt>A</tt>' のコード位置
を <tt>0x41</tt> ではなく <tt>0xC1</tt> に定義する <tt>charmap</tt> ファイルを
作ることを何ものも止めることはできません。これは実際にメインフレームで用い
られる IBM コードページ <tt>37</tt> で、'<tt>A</tt>' のコード位置マッピング
です。一方前者は、 US-ASCII、iso8859-x などで用いられています。

基本的な考えは、異なる人々が異なる言語を話し、異なる並べかえ順を想定
し、異なるコードページを用い、異なる国に住んでいることです。locale と
locale に依存するプログラムはそれを尊重し、それに応じた扱いをするよう
に意図されています。そうするのに格別の努力はいりませんし、プログラムを
書くときにちょっと気分を変えるだけでよいのです。

</sect>

<sect>ノート
<p>
<itemize>
<item>
自分のマシンで locale を設定するためには、いくつかのものをアップグ
レードする必要があります。ftp.tu-clausthal.de:/pub/linux/SLT/nls に
locale と localedef の a.out 版が(<tt>nlsutils-0.5.tar.gz</tt> という名前で)
あるようです。で、ELF システムを持っていないか、ELF が欲しくないな
ら、これを使うことができます。たぶんどこか他のところで <tt>nlsutils</tt> 
パッケージのコピーがあるでしょう。しかし、私はそれを見つけていませ
ん &lsqb; 訳注：国内にはないようですが、debian パッケージには <tt>.deb</tt> 
の形で入っているようです &rsqb; 。私は locale と localedef のスタンドアロン
版を聞いたことがありませんが、対応する libc をインストールしなけれ
ばならないことは考慮にいれておいて下さい。ですからこの HOWTO の大部
分は 私が libc とそのファミリーをアップグレードするためにしなければ
ならなかったことの記録でしかありません。もしあなたが libc をインス
トールするなら、私がしたように ELF システムを走らせ、locale をセッ
トアップするときに ELF に移行する必要があります。
<item>
私が行なったシステム移行の内容は、a.out から ELF への移行ですべきこ
とと同じです。ELF に移行していないか、Linux の再インストールで ELF
に移行しているなら、sunsite のミラーから最新の ELF HOWTO をもってき
てください。これはすばらしいガイドで、libc、ld.so、などの ELF シス
テムへの移行をインストールするためのガイダンスでもあります。
<item>
何をインストールするにしても、適当なリリースノートや README などの
ファイルを読んでください。もし、ここで私が書いたことを誤解したり、
(そうでないことを願うけど)私がここで書いたことを実行することであな
たのシステムをぐちゃぐちゃにしてしまっても、どうか私を責めないで下
さい。 &lsqb; 訳注：そして、できれば翻訳者も責めないでください。 &rsqb;
<item>
新しい libc や ld.so のインストールを間違えると、ブートできないシス
テムにしてしまうことがあります。ブードディスクをつくっておくべき
で、消えてしまうと取り返しのつかない重要なデータは必ずバックアップ
しておくように。
</itemize>

</sect>

<sect>必要なもの
<p>
２、３のものをいろいろな場所からダウンロードする必要があります。ここに
ある locale ソースファイルを除くすべてのものは sunsite.unc.edu、
tsx-11.mit.edu、なるべくならこれらのサイトのミラーから得ることができま
す。 <newline>
&lsqb; 訳注：国内では sunsite.sut.ac.jp,ftp.sra.co.jp など。 locale 関
係以外では ftp.kuis.kyoto-u.ac.jp も使えます。どうせなら kernel を
2.0.x にしてしまってもっと新しいライブラリを使ったほうがよいでしょ
う。<tt>linux-2.0.x/Documentation/Changes</tt> を参照のこと。 &rsqb;

<itemize>
<item>locale と charmap のソース --- localedef を使ってコンパイルするもの
です。

<item><tt>libc-5.2.18.bin.tar.gz</tt> --- c と math ライブラリに対する ELF 
共有ライブラリです。

<item><tt>libc-5.2.18.tar.gz</tt> --- ELF 共有ライブラリのソースコードです。
localedef コンパイルするのにこれが必要です。

<item><tt>make-3.74.tar.gz</tt> --- dirent のバグを修正するためのパッチを
合体するためにコンパイルする必要があります。

<item><tt>release.libc-5.2.18</tt> --- これらのリリースノートには make を
作成するためのパッチがあります。

<item><tt>ld.so-1.7.12+</tt> --- ダイナミック・リンカです。

<item>ELF <tt>gcc-2.7.2+</tt> --- コンパイルに必要です。

<item>ELF kernel 1.1.92+, or ELF kernel 1.3.40+ --- コンパイルに必要で
す。

<item><tt>binutils 2.6.0.2+</tt> --- コンパイルに必要です。
</itemize>

locale のソースを入手できるサイトはたぶんたくさんあります。私が知って
いる範囲では次のサイトで locale と charmap のソースを入手できます。

<tscreen><verb>
dkuug.dk:/i18n/WG15-collection/locales
&lt;ftp://dkuug.dk/i18n/WG15-collection/locales&gt;
dkuug.dk:/i18n/WG15-collection/charmaps
&lt;ftp://dkuug.dk/i18n/WG15-collection/charmaps&gt;
</verb></tscreen>

  -&#045; &lsqb; 訳注：日本語の locale は XFree86 にも入っています。 &rsqb; 
-&#045;

</sect>

<sect>全てのものをインストールする
<p>
これは全てをインストールするためのものです。私はすでにこれを行なう前に
インストールした ELF システム(コンパイラ、カーネルなど...)を持っていま
す。

<enum>
<item>まず、<tt>binutils</tt> パッケージをインストールしました。
<tscreen><verb>
tar xzf binutils-2.6.0.2.bin.tar.gz -C /
</verb></tscreen>

<item>次にダイナミック・リンカをインストールしました：
<tscreen><verb>
tar zxf ld.so-1.7.12.tar.gz -C /usr/src
cd /usr/src/ld.so-1.7.12
sh instldso.sh
</verb></tscreen>

<item>次に libc バイナリをインストールしました。詳しい手順は
<tt>libc-5.2.18</tt> のリリースノートを参照してください。
<tscreen><verb>
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 /
</verb></tscreen>

<item>新しい共有ライブラリを認識させるために <tt>ldconfig</tt> を実行する必
要があります。
<tscreen><verb>
ldconfig -v
</verb></tscreen>

<item>libc には make やいくつかのプログラムを壊すバグがあります。私
は次のように make を再構築し、インストールしました： &lsqb; 訳注：
新しい libc で使える <tt>make-3.74</tt> のバイナリもあります &rsqb;
<tscreen><verb>
tar zxf make-3.74.tar.gz -C /usr/src
cd /usr/src/make-3.74
patch &lt; /whereever_you_put_it/release.libc-5.2.18
configure --prefix=/usr
sh build.sh
../make install
cd ..
rm -rf make-3.74
</verb></tscreen>

<item>さあ、これで localedef をコンパイル、インストールできます。
<tscreen><verb>
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

# 私はこの２回の make が必要なことかどうかは自信がありませ
# んが、安全のためにやっているだけです。

make clean ; make depend
cd locale
make programs
mv localedef /usr/local/bin
mv locale /usr/local/bin
</verb></tscreen>

<item>localedef がそれらを見つけるところに charmap を置いて下さい。
これは charmap.tar として dkuug.dk ftp サイトからダウンロード
できる、 charmap と locale ソースを用います。
<tscreen><verb>
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
</verb></tscreen>
</enum>
</sect>

<sect>さあ、どうだ
<p>
すべて済めば、作成された locale を使うことができるでしょう。以下は単純
な例題プログラムです。

<tscreen><verb>
/* test.c : a simple test to see if the locales can be loaded, and
 * used */
#include &lt;locale.h&gt;
#include &lt;stdio.h&gt;
#include &lt;time.h&gt;

main(){
        time_t t;
        struct tm * _t;
        char buf&lsqb;256&rsqb;;

        time(&amp;t);
        _t = gmtime(&amp;t);

        setlocale(LC_TIME,"");
        strftime(buf,256,"%c",_t);

        printf("%s\n",buf);
}
</verb></tscreen>

現在の locale 環境変数設定がどうなっているかを locale プログラムを使っ
て見ることができます。

<tscreen><verb>
$ # 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
</verb></tscreen>
</sect>

<sect>catopen のバグ修正
<p>
locale をインストールすると、Linux libc の <tt>catopen</tt> コマンドにあるバグ
(仕様か？)が修正されます。メッセージ・カタログを使うプログラムを作成
し、ドイツ語カタログを作り、それを <tt>/home/peeter/catalogs/de_DE</tt> におく
としましょう。

以下のことを <tt>de_DE locale</tt> をインストールしないで行なってみてください：

<tscreen><verb>
export LC_MESSAGES=de_DE
export NLSPATH=/home/peeter/catalogs/%L/%N.cat:$NLSPATH
</verb></tscreen>

ドイツ語のメッセージ・カタログがオープンできず、<tt>catgets</tt> コールのデフォ
ルトのメッセージが使われます。

これは <tt>catopen</tt> が正しいメッセージ・カテゴリを得るために 
<tt>setlocale</tt> コールを実行し、環境変数が設定されていても <tt>
setlocale</tt> が失敗する理由です。それで <tt>catopen</tt> は <tt>
NLSPATH</tt> の全ての "<tt>%L</tt>" に "<tt>C</tt>" を代入してメッセージ・
カタログをロードしようとします。

locale をインストールしなくてもメッセージ・カタログを用いることはでき
ますが、以下のように <tt>NLSPATH</tt> の "<tt>%L</tt>" 部分をはっきりと
設定する必要があるでしょう：

<tscreen><verb>
export NLSPATH=/home/peeter/catalogs/de_DE/%N.cat:$NLSPATH
</verb></tscreen>

しかし、これは locale カテゴリ環境変数の全ての目的をくじけさせてしまい
ます。
</sect>

<sect>Q &amp; A
<p>
このセクションは FAQ に成長するかもしれませんが、本当はまだそうではあ
りません。

<sect1>msgcat の質問
<p>
私は LINUX のユーザで、以下のテストプログラムを書きました：

<tscreen><verb>
--------------------------------------------------------------------
#include &lt;stdio.h&gt;
#include &lt;locale.h&gt;
#include &lt;features.h&gt;
#include &lt;nl_types.h&gt;

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
--------------------------------------------------------------------
</verb></tscreen>

もし <tt>catopen("/etc/locale/msg.cat",MCLoadBySet);</tt> のように 
<tt>catopen</tt> で絶対パスを使えば、正しい結果が得られます。しかし、
上の例のようにすると <tt>catopen</tt> は -1 を返します(失敗します)。

</sect1>
<sect1>msgcat の答え
<p>
この質問については前のセクションがある程度答になっていますが、もう少し
付け加えておきます。

メッセージをカタログに置くのに適切な場所はたくさんあります。(メッセー
ジ・カタログの場所を設定する) <tt>NLSPATH</tt> 環境変数が明示的に設定
されていなくても、libc の中で次のように定義されてます：

<tscreen><verb>
$ 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
</verb></tscreen>

これができたら次のうちの１つをやってみてください：

<tscreen><verb>
$ export LC_MESSAGES=en_CA
$ export LC_ALL=en_CA
$ export LANG=en_CA
</verb></tscreen>

メッセージ・カタログが次のどれかにコピーされているなら、上記の <tt>NLSPATH
</tt> と指定された環境で、<tt>catopen("msg", MCLoadBySet);</tt> はうまく動く
でしょう。

<tscreen><verb>
/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
</verb></tscreen>

しかし、もし <tt>en_CA locale</tt> がインストールされていなければ、
<tt>setlocale</tt> は失敗するためにうまくいかず、<tt>catopen</tt> 
ルーチンで (<tt>en_CA</tt> ではなく) "<tt>C</tt>" が "<tt>%L</tt>" 
に代入されるでしょう。

</sect1>
</sect>

<sect>フィナーレ
<p>
以上です。願わくばこのガイドがあなたの助けとなって欲しいと思います。
locale 依存のプログラムを書くために、さらなる情報を探すことができる場
所はおそらくたくさんあるでしょう。libc の info ページに情報がいくつか
ありますし、man ページはいつでも見ることができます。ちょっと WWW ページ
を漁れば、たくさんの情報を見つけることができるでしょう。国際化プログラ
ミングに対する良い情報源を見つけたら、お知らせ下さい。そうすればそれら
をこの HOWTO に反映することができます。

</sect>
</article>
