この章では,地域化の要件 (言語,コードセット,および文化習慣の違い) によって,基本的なコーディング作業がどのように変わるかを説明します。
この章で説明するプログラム開発技術を適用するサンプル・アプリケーションが,ディレクトリ
/usr/examples/i18n/xpg4demo
にあります。
このディレクトリにある
README
ファイルには,アプリケーションの紹介と,さまざまなロケールでこのアプリケーションをコンパイルして実行する方法についての説明が記載されています。
本書では,アプリケーション・プログラム
xpg4demo
の一部を例として使用します。
多くのコンピュータ・プログラムの主要な機能の 1 つとして,データの操作が挙げられます。 データ操作には,プログラムとコンピュータ・ユーザ間のやり取りが伴うことがあります。 商用アプリケーションでは,このようなやり取りを各ユーザの母国語で行うことが重要です。 文化的データも,適切な慣習に従っていなければなりません。
各国語でのデータ操作をサポートするプログラムを作成する場合,コンピュータ・システム内では,言語は 1 つまたは複数のコードセットで表現されることがある点を考慮しておかなければなりません。 言語ごとにその要件が違うため,コードセットの文字は,サイズ (8 ビット,16 ビットなど) とバイナリ表現の両方で異なることがあります。
言語や,文化的データ,文字のエンコーディングにまったく依存しないプログラムを作成することにより,上記のコードセットとデータの要件を満たすことができます。 そのようなプログラムは,国際化されてたプログラムと呼ばれます。 サポートされている言語,地域,およびコードセットの組み合わせに固有のデータは,プログラム・コードとは別に保持され,言語初期化関数を使用して実行時環境にバインドできます。
Tru64 UNIX は,国際化ソフトウェアの開発,地域化データの定義,および特定の言語要件の宣言に使用する,次の機能を備えています。
各言語の言語,コードセット,および文化的データの定義を含むロケール (2.1 節)
拡張文字コードを処理し,言語とコードセットに依存しない文字分類,大文字/小文字変換,数値書式の変換,および文字列照合を行うライブラリ関数 (2.2 節)
プログラムが文化的データや言語固有のデータを動的に判別できるようにするライブラリ関数 (2.3 節)
プログラム・メッセージをプログラム・コードとは別に保持し,異なる言語に翻訳して,実行時にプログラムから取り出せるようにするメッセージ・システム (2.4 節)
各ユーザの言語および文化的要件を満たすように,プログラムを実行時にバインドする初期化関数 (2.5 節)
この章の説明と例では,標準 C ライブラリに含まれる関数に焦点を当てます。
curses
ライブラリの関数の使用方法については,第 4 章を参照してください。
X および Motif ライブラリの関数の使用方法については,第 5 章を参照してください。
2.1 ロケールの使用
本オペレーティング・システムでは,Unicode
ロケールと
dense コード・ロケールがサポートされています。
Unicode ロケールは,/usr/i18n/lib/nls/ucsloc/
にインストールされます。
dense コード・ロケールは,/usr/i18n/lib/nls/loc
にインストールされます。
省略時のロケールは,シンボリック・リンク
/usr/i18n/lib/nls/dloc
によって決まります。
たとえば,日本語のロケール・ファイル名
/usr/lib/nls/loc/ja_JP.eucJP
は,/usr/i18n/lib/nls/dloc/ja_JP.eucJP
へのシンボリック・リンクです。
ここで,/dloc
は,日本語ロケールの Unicode バージョン用の
/ucsloc
と,dense コード・バージョン用の
/loc
のいずれかです。
スーパユーザの場合,シンボリック・リンクの設定を変えることで,Unicode ロケールと dense コード・ロケールの間で切り替えることができます。
l10n_intro
(5)
Unicode ロケールは,Unicode と ISO/IEC 10646 標準に適合しており,UTF-32 をワイド文字エンコーディングとして使用します。
UTF-32 ワイド文字エンコーディングでは,wchar_t
の値はロケールに関係なく同じ文字を表します。
これは,Unicode 標準では,プラットフォームが異なっても実装の一貫性が保たれるためです。
名前が
.UTF-8
で終わるロケールでは,ファイル・コードと,ISO 10646
および Unicode 標準で規定された UTF-32 内部処理コード (wchar_t
エンコーディング) を使用します。
その他の非 UTF-8 Unicode ロケールでは,内部処理コードとして UTF-32 を使用する一方,従来の UNIX コードセットや独自のコードセットをファイル・コード用に使用します。
これらの Unicode ロケールのサブセットには,@ucs4
という修飾子が付きます。
ただし,これらのサブセットは,@ucs4
修飾子が付かないロケールと同じです。
@ucs4
サブセットは,旧製品との互換性を保つために用意されており,将来は削除される可能性があります。
@ucs4
ロケールは,CDE のログイン・メニューから選択することはできません。
ロケール名を
LANG
環境変数で指定しなければなりません。
universal.UTF-8
ロケールを利用することもできます (エンド・ユーザ用ではなく,アプリケーション用)。
このロケールは,UCS (Universal Character Set) の文字を完全にサポートしています。
エンコーディング・フォーマットについての詳細は,
Unicode
(5)
.UTF-8
ロケールでは,1 バイトを超えるコードの文字がファイル・コードに含まれることがあります。
このため,これらのロケールは,マルチバイト・データを処理できるアプリケーションで使用してください。
新しいアプリケーションは,マルチバイトの
.UTF-8
ロケールをベースにして設計してください。
このロケールには多くの種類の文字が盛り込まれているため,将来,アプリケーションは文字セットを変更することなく文字サポートを拡張することができます。
dense コード・ロケールでは,テーブル・サイズを最小にするために,ワイド文字のエンコーディングに dense コードを使用します (つまり,コードポイントが連続して割り当てられ,空になる位置はありません)。
dense コード・ロケールでは,1 つのロケールの
wchar_t
値は,他のロケールで同じ文字を表しているとは限らず,ロケールに固有です。
dense コード・ロケールは,内部処理コードに依存しないアプリケーションや,性能を上げることに重点を置いているアプリケーション (dense コード・ロケールは Unicode ロケールよりも多少効率的であるため) に適しています。
マルチバイト文字セットの有効なすべてのコードポイントは,Unicode のプライベート用領域のコードポイントにマッピングされる対応先なしのコードポイントも含め,Unicode 内の有効なコードポイントにマッピングされます。
このため,dense コード・ロケールは,Unicode ロケールと等価です。
一般的に,Unicode ロケールと dense コード・ロケールで,同じ文字マップとロケール・ソースを使用することができます。
ただし,LC_COLLATE
セクションで定義されていない Unicode 文字と dense コード文字は,異なる方法でソートされることがあります。
各 dense コード・ロケールに対して,Unicode ロケールが 1 つ存在します (ただし,すべての Unicode ロケールに dense コード・バージョンが存在するわけではありません)。 Latin-1 ロケール (ISO8859-1) では,Latin-1 の文字が Unicode の最初の 256 文字と同じであるため,dense コード・ロケールと Unicode ロケールは全く同じです。 シンボリック・リンクの設定に従って,同じロケール名で Unicode ロケールを参照する場合と,dense コード・ロケールを参照する場合があることに注意してください。 このため,あるロケールでのアプリケーションの実行に問題がある場合,シンボリック・リンクをチェックしてください。
Unicode ロケールでは
wchar_t
フォームの文字に一貫した値を使用するため,Unicode ロケールにリンクすると,ロケールやプラットフォームの間で一貫性が増します。
ただし,ユーザによっては文字を
wchar_t
フォームに変換する独自のアルゴリズムを使用する古い dense コード・ロケールを好む場合や,アプリケーションが dense コードの
wchar_t
エンコーディングに依存している場合があります。
2.2 コードセットの使用
以前は,大半の UNIX システムが 7 ビットの ASCII コードセットに基づいていました。 しかし,英語以外のほとんどの言語は,ASCII コードセット以外の文字も含んでいます。
X/Open の UNIX 標準では,オペレーティング・システムが ASCII コードセットに加え,特定のコードセットもサポートすることは規定していません。 ただし,この仕様は,システム上で利用可能なコードセットが何であれ,プログラムがそのコードセットの文字を処理できるようにするための,文字操作用のインタフェースを必須要件として規定しています。
ISO (国際標準化機構) コードセットの 1 番目のグループは,主要なヨーロッパ言語だけをカバーしています。 このグループ内のいくつかのコードセットでは,主要な言語を単一のコードセットに統合することができます。 これらのコードセットはすべて,ASCII コードセットのスーパセットであるため,既存の国際化されていないソフトウェアで問題を生じることはなく,英語以外の言語もサポートできます。 Tru64 UNIX オペレーティング・システムは,ISO 8859-1 (ISO Latin-1) を使用する,米国英語ロケールを常にサポートします。
WLS (ワールドワイド言語サポート) の一部としてインストールされているサブセットは,地域化に対応しているオペレーティング・システムをサポートし,上記以外の ISO コードセットに基づくロケールを含むことがあります。 たとえば,チェコ語,ハンガリー語,ポーランド語,ロシア語,スロバキア語,およびスロベニア語をサポートする,Tru64 UNIX のオプションの言語別サブセットには,ISO 8859-2 (Latin-2) に基づくロケールが含まれています。
以下に,WLS が提供する ISO コードセットの全リスト,それらがサポートする言語,詳しい説明の記載されているリファレンス・ページを示します。
ISO 8859-1,Latin-1
カタロニア語,デンマーク語,オランダ語,英語/イギリス,英語/アメリカ合衆国,フィンランド語,フラマン語/ベルギー,フランス語/ベルギー,フランス語/カナダ,フランス語/スイス,フランス語,ドイツ語/スイス,ドイツ語/ドイツ,アイスランド語,イタリア語,ノルウェー語,ポルトガル語,スペイン語,およびスエーデン語を含む,西ヨーロッパおよび北アメリカの言語
iso8859-1
(5)
ISO 8859-2,Latin-2
チェコ語,ハンガリー語,ポーランド語,スロバキア語,およびスロベニア語を含む,東ヨーロッパの言語
iso8859-2
(5)
ISO 8859-4,Latin-4
iso8859-4
(5)
ISO 8859-5,Latin/Cyrillic
iso8859-5
(5)
ISO 8859-7,Latin/Greek
iso8859-7
(5)
ISO 8859-8,Latin/Hebrew
ヘブライ語/イスラエル (ISO Hebrew コードセットを使用)
iso8859-8
(5)
ISO 8859-9,Latin-5
iso8859-9
(5)
ISO 8859-15,Latin-9
カタロニア語/スペイン,デンマーク語,オランダ語,英語/イギリス,英語/アメリカ合衆国,フィンランド語,フラマン語/ベルギー,フランス語/ベルギー,フランス語/カナダ,フランス語/スイス,フランス語,ドイツ語/スイス,ドイツ語/ドイツ,アイスランド語,イタリア語,ノルウェー語,ボルトガル語,スペイン語/スペイン,およびスウェーデン語。 ISO 8859-15 (および UTF-8) は,ユーロ通貨文字をサポートしています。
iso8859-15
(5)
本オペレーティング・システムは,ISO 8859-3 (Latin-3) コードセットと ISO 8859-6 (Latin-6) コードセットはサポートしていません。
標準のオペレーティング・システム上のユーティリティがサポートする ISO コードセットには,他に ISO 6937: 1983 があります。 このコードセットは,7 ビットと 8 ビットの両方の文字に対応しており,通信ネットワークや交換メディア (磁気テープやディスクなど) 上でのテキスト通信に使用されます。
ここまでで説明したコードセットには,文字が 1 バイトに格納されるという要件があります。 このようなコードセットは,文字が複数バイトに格納されるアジア系言語の要件は満たしません。 本オペレーティング・システムでは,アジア系の言語および国をサポートするサブセットをインストールすることによって,次のコードセットが使用できます。
日本語
日本語拡張 UNIX コード (省略時のコード)
eucJP
(5)
シフトJIS
shiftjis
(5)
DEC Kanji
deckanji
(5)
Super DEC Kanji
sdeckanji
(5)
韓国語
DEC Korean
deckorean
(5)
韓国語拡張 UNIX コード
eucKR
(5)
タイ
タイ API コンソーシアム/タイ工業規格
TACTIS
(5)
簡体字中国語
DEC Hanzi
dechanzi
(5)
GBK および GB18030
GBK
(5)GB18030
(5)
繁体字中国語
DEC Hanyu
dechanyu
(5)
台湾拡張 UNIX コード
eucTW
(5)
BIG-5 (および改良版の Shift BIG-5)
big5
(5)sbig5
(5)
Telecode
telecode
(5)
これらのコードセットは,オペレーティング・システム・ソフトウェアのアジア言語サブセットをインストールすると,使用できるようになります。 また,アジア言語文字の入力や表示に必要な専用の端末ドライバと関連ユーティリティも使用できるようになります。
PC システム用に開発されたコードセットは,一般にコード・ページと呼ばれます。
UNIX システム用に開発された大半の言語固有のコードセットには,対応する PC コード・ページがあります。
ほとんどの場合,Tru64 UNIX はファイル・データをあるエンコード方式から別のエンコード方式に変換するコンバータを介して,PC コードセットをサポートします。
CP850 コードセットは,英語/アメリカ合衆国をサポートします。
そして,文字のエンコーディングに CP850 コード・ページを使用して PC 上で生成されるアクセント付き文字を含むデータで使用されます。
ヨーロッパの MS-DOS および Windows オペレーティング・システムでは,特に指定しなければ,通常この文字エンコーディングが使用されます。
code_page
(5)
Unicode と ISO/IEC 10646 標準は,ユニバーサル文字セット (UCS) を規定します。 UCS はアジア系言語も含め,すべての言語に同じ規則を適用することにより,文字ユニットを扱えるようにする文字セットです。 オペレーティング・システムは,この文字の UCS-4 (32 ビット) エンコーディングを処理コードでサポートします。
Unicode あるいは ISO/IEC 10646 標準 (または両方) で定義されている他のエンコーディング・フォーマットには,次のものがあります。
UCS-4 の 16 ビット版である UCS-2
UCS エンコーディングを,バイト指向プロトコルで取り扱うバイトのシーケンスに変換する各種の Universal Transformation Format (UTF-8,UTF-16,および UTF-32)
オペレーティング・システムでは,ロケールやコードセット・コンバータ (またはその両方) によって,これらの異なるフォーマットをサポートしています。 UCS-2 は UTF-16 のサブセットであるため,本オペレーティング・システムは,UCS-2 を UTF-16 コードセット・コンバータでサポートします。 本オペレーティング・システムは,コードセット変換とロケールの両方で UCS-4 をサポートします。
以下のロケールでは,UTF-32 を内部処理コードとして使用します。
universal.UTF-8
このロケールはアプリケーションで使用し,UTF-8 ファイル・フォーマットのデータを UCS-4 処理コードに変換したり,UCS-4 文字をテストして
LC-CTYPE
クラス (alnum
,alpha
,blank
,cntrl
,digit
,graph
,lower
,print
,punct
,space
,upper
,または
xdigit
) に含まれているか調べます。
このロケールでは,LC_MESSAGES
,LC_MONETARY
,LC_NUMERIC
,および
LC_TIME
の定義が,POSIX (C) ロケールでの定義と一致します。
アプリケーションでは,このロケールを
fold_string_w()
関数とともに使用して,Unicode および ISO/IEC 10646 標準で定義されている文字をすべて処理することができます。
このロケールは,ローカルな文化的慣習にアクセスできないため,他の大半のロケールとは異なります。
language_territory.UTF-8
これらのロケールは,分類情報を特定の言語の文字に制限し,アプリケーションで国ごとに異なるデータを利用できるようにします。 また,ファイル・データが UTF-8 エンコーディング規則に従っていることを前提とします。 ユーロ通貨記号をサポートする,本オペレーティング・システムのロケールは,UTF-8 コードセットまたは ISO8859-15 コードセットを使用します。
Unicode UTF-8 コードセットは,カタロニア語/スペイン,チェコ語,デンマーク語,オランダ語,英語/イギリス,英語/アメリカ合衆国,フィンランド語,フラマン語,フランス語/ベルギー,フランス語/カナダ,フランス語/スイス,ドイツ語/スイス,ドイツ語,ギリシャ語,ハンガリー語,アイスランド語,イタリア語,日本語,韓国語,リトアニア語,ノルウェー語,ポーランド語,ポルトガル語,ロシア語,スロバキア語,スロベニア語,スペイン語,スウェーデン語,トルコ語,簡体字中国語 (Hanzi),繁体字中国語 (Hanyu)
をサポートしています。
Unicode
(5)
native_locale_name
これらのロケールは,UTF-32 を内部処理コードとして使用します。
native_locale_name
のコードセット部分 (たとえば,ISO8859-1) は,ファイル・コードを指定します。
また,ロケールには各国の言語の文字の分類情報が用意されていますが,UTF-32 のすべての文字の分類情報が用意されているわけではありません。
アプリケーションでは,国固有の情報を利用できます。
LC_COLLATE
,LC_MESSAGES
,LC_MONETARY
,LC_NUMERIC
,および
LC_TIME
のカテゴリ定義は,native_language_name
の定義と一致します。
native_language_name@ucs4
これらのロケールは,@ucs4
ロケールを使用する既存のアプリケーションとの互換性を保つために用意されています。
これらのロケールは,native_locale_name
ロケールと同様に機能しますが,用意されているロケールのリストは,native_language_name
ロケールほど完全ではありません。
LC_TIME
などのロケール・カテゴリについては,2.5 節を参照してください。
データ処理でのロケールと比較については,
Unicode
(5)euro
(5)
UCS-2,UCS-4,UTF-8,UTF-16,および UTF-32
のサポートについての詳細は,
Unicode
(5)
これ以降の項では,複数のコードセットの文字を処理するプログラムを作成する際に,ソース・コードの記述方法に影響する事柄について説明します。
データの透過性の確保 (2.2.1 項)
コード内リテラルの使用 (2.2.2 項)
マルチバイト文字の操作 (2.2.3 項)
マルチバイト文字データとワイド文字データ間の変換 (2.2.4 項)
ソースおよび実行コードセットにおけるマルチバイト文字の規則 (2.2.5 項)
文字の分類 (2.2.6 項)
文字の変換 (2.2.7 項)
文字列の比較 (2.2.8 項)
2.2 節で説明したように,国際化ソフトウェアは,さまざまな文字エンコード方式に対応しなければなりません。 プログラムは,X/Open UNIX CAE Specifications の必須要件に準拠するすべてのシステム上で特定のコードセットがサポートされていることや,個々の文字のビット数が固定されていることを前提にはできません。
UNIX システムでは 7 ビットの ASCII 文字を長年にわたって使用してきたため,バイトの最上位ビット (MSB) を独自の用途に使用するプログラムが存在します。
これは,基本コードセットの文字が常にバイトの下位 7 ビットにマップされている場合には安全な手法ですが,プログラミング手法としては好ましくありません。
国際化コードセットの世界では,バイトの最上位ビットをプログラム独自の用途に使用することは避けなければなりません。
2.2.2 コード内リテラルの使用
国際化ソフトウェアを作成するときは,コード内リテラルを使用しないでください。 例として,次の条件文について考えてみます。
if ((c = getchar()) == \141)
この条件文では,小文字
a
が常に固定の 8 進値で表現されていますが,この前提がすべてのコードセットで正しいわけではありません。
コード内リテラルを使用する代わりに,関数を使用してください。
getchar()
関数を使用する次の文では,8 進値の代わりに文字定数を使用しています。
if ((c = getchar()) == 'a')
ただし,getchar()
関数はバイト単位で操作するため,入力ストリーム中の次の文字が複数バイトに渡っているときは正しく動作しません。
この問題を回避するには,getchar()
関数を
getwchar()
関数に置き換えます。
getwchar()
関数は,例で使用されているように,どのコードセットでも正しく動作します。
これは,a
がポータブル文字セットのメンバで,すべてのロケールで同じワイド文字値に変換されるためです。
if ((c = getwchar()) == L'a')
X/Open の UNIX 標準では,文字定数と文字列リテラル中の,ソース文字セットのすべてのメンバとエスケープ・シーケンスは,すべてのロケールで実行文字セットの同じメンバに変換されると規定しています。 そのため,ポータブル文字セット中の文字は,文字定数として,あるいは文字列リテラルで使用しても安全です。 英語以外の文字はポータブル文字セットに含まれていないため,リテラルとして使用すると正しく変換されないことがあります。 次に例を示します。
if ((c = getwchar()) == L' à ')
アクセント文字
à
は,コードセットのソース文字セットまたは実行文字セットに含まれていない可能性があります。
また,アクセント文字のバイナリ値はコードセット間で変換できないこともあります。
ソース・ファイルで英語以外の文字が定数として使用されている場合,その結果は定義されていません。
このような場合,Unicode ロケールを一貫して使用すると効果があります。
次の例は,何らかの理由で英語以外の文字になる可能性がある定数との比較を行う方法を示します。
この定数は,メッセージ・カタログ中のシンボル識別子
MSG_ID
で定義されています。
例に示されている文は,MSG_ID
の値をメッセージ・カタログから取り出します。
この値は,ロケールに固有で,実行時にプログラムにバインドされます。
.
.
.
char *schar; [1] wchar_t wchar; [2]
.
.
.
schar = catgets(catd,NL_SETD,MSG_ID,"a"); [3] if (mbtowc (&wchar,schar,MB_CUR_MAX) == -1) [4] error(); if ((c = getwchar()) == wchar) [5]
.
.
.
char
を
schar
へのポインタとして宣言します。
[例に戻る]
変数
wchar
を
wchar_t
型として宣言します。
[例に戻る]
catgets()
関数を呼び出して,ユーザのロケールのメッセージ・カタログから
MSG_ID
の値を取り出します。
catgets()
関数は値をバイトの配列として返すため,値は
schar
変数に返されます。
アクセント文字がロケールのコードセットに含まれていない場合,テストはアクセントの付かない基本文字 (a
) に対して行われます。
[例に戻る]
schar
に含まれる値が有効なマルチバイト文字を表しているかどうかをテストします。
値が有効なマルチバイト文字の場合,プログラムはその文字をワイド文字値に変換し,結果を
wchar
に格納します。
schar
が有効なマルチバイト文字を含んでいない場合は,プログラムはエラーを発行します。
[例に戻る]
wchar
の値を定数として含む条件文です。
[例に戻る]
メッセージ・カタログと
catgets()
関数の詳細については,第 3 章を参照してください。
マルチバイト文字とマルチバイト文字列を,プログラムで処理可能なワイド文字データに変換する方法については,2.2.4 項を参照してください。
2.2.3 マルチバイト文字の操作
Tru64 UNIX は,マルチバイト文字を含むコードセットをサポートするのに必要なすべてのインタフェース (putwc()
,getwc()
,fputws()
,fgetws()
など) を備えています。
マルチバイト文字のサポートを可能にするロケールと機能を組み込むためには,オペレーティング・システムに言語別サブセットをインストールしなければなりません。
マルチバイト・ロケールがインストールされていないシステムや,インストールされているが実行時にプログラムにバインドされないシステムでは,*ws*()
と
*wc*()
関数は,単に対応するシングルバイト関数 (putc()
,getc()
,fputs()
,fgets()
など) と同じ動作をします。
2.2.4 マルチバイト文字データとワイド文字データ間の変換
国際化に対応しているシステムでは,データはマルチバイト文字とワイド文字のどちらでもエンコードできます。
一般に,マルチバイト・エンコーディングは,データをファイルに格納するとき,あるいはデータを外部用途やデータ交換のために生成するときに使用します。 マルチバイト・エンコーディングには,次のような欠点があります。
文字は,同じコードセット中でも,1 文字当たりのバイト数が固定した文字として表現されない。 そのため,マルチバイト・データ・レコード内の文字サイズは,文字ごとに異なることがあります。
マルチバイト・データ・レコードから文字コードを読み出すための解析規則はロケールに依存する。
マルチバイト・エンコーディングにはこのような欠点があるため,プログラムの内部処理には,一般に 1 文字当たりのバイト数が固定されているワイド文字エンコーディングが使用されます。 実際,ワイド文字形式のデータを内部処理コードともいいます。 ワイド文字のサイズはシステムの実装よって異なります。 Tru64 UNIX システムでは,ワイド文字のサイズは,HP Alpha プロセッサの性能を最適化する,4 バイト (32 ビット) に設定されています。
テキストのプリントや,スキャン,入出力を行うライブラリ・ルーチンは,操作の種類に適した形でマルチバイト文字からワイド文字へ,あるいはワイド文字からマルチバイト文字へ自動的に変換する機能を備えています。 ただし,ほとんどのアプリケーションには,マルチバイト文字への変換やマルチバイト文字からの変換を明示的に指定する文や条件が含まれています。
次の例は,従業員データのデータベースからレコードを読み取るプログラム・モジュールの一部です。
この例では,プログラマは固定長のデータを扱いたいので,mbstowcs()
関数を使用して,従業員の名前と姓をマルチバイト文字からワイド文字のエンコーディングに変換します。
/* * The employee record is normalized with the following format, which * is locale independent: Badge number, First Name, Surname, * Cost Center, Date of Join in the `yy/mm/dd' format. Each field is * separated by a TAB. The space character is allowed in the First * Name and Surname fields. */ static const char *dbOutFormat = "%ld\t%S\t%S\t%S\t%02d/%02d/%02d\n"; static const char *dbInFormat = "%ld %[^\t] %[^\t] %S %02d/%02d/%02d\n";
.
.
.
sscanf(record, dbInFormat, &emp->badge_num, firstname, surname, emp->cost_center, &emp->date_of_join.tm_year, &emp->date_of_join.tm_mon, &emp->date_of_join.tm_mday); (void) mbstowcs(emp->first_name, firstname, FIRSTNAME_MAX+1); (void) mbstowcs(emp->surname, surname, SURNAME_MAX+1);
.
.
.
マルチバイト・データを直接処理できる関数のリストについては,A.9 節を参照してください。
2.2.5 ソースおよび実行コードセットにおけるマルチバイト文字の規則
同じコードセットのソース文字セットと実行文字セットは,どちらもマルチバイト文字を含むことができます。 エンコーディングが同じである必要はありませんが,ソースと実行のどちらの文字セットも,X/Open の標準 UNIX 仕様を満たすコードセットの規則に従わなければなりません。 PC コードセットと UCS ベースのコードセットは,これらの規則のいくつか,またはほとんどを満たすだけでかまいませんが,X/Open の UNIX 標準に準拠する UNIX システムに固有のコードセットは,これらの規則をすべて満たさなければなりません。
ポータブル文字セットに定義されている文字は,両方のセットに含まれていなければならない。
それ以外のメンバの有無,その意味,およびエンコーディングは,ロケールによって異なる。
文字のエンコーディングは状態に依存することがある。 文字列にはシフト状態文字が含まれることがあり,シフト状態文字は次のシフト状態文字が検出されるまで,システムにおけるバイトの解釈に影響を与えます。
初期シフト状態の間は,基本文字セットのすべての文字は通常どおりに解釈され,シフト状態を変更することはない。
シーケンス中のバイトの解釈は,現在のシフト状態に依存する。
コードセットのソース・バージョンは,次の規則にも従わなければなりません。
コメント,文字列リテラル,文字定数,あるいはヘッダ名は,初期シフト状態で始まり,終了しなければならない。
コメント,文字列リテラル,文字定数,あるいはヘッダ名は,有効なマルチバイト文字の並びで構成されなければならない。
cc
コマンド行で
-std1
または
-std
フラグを指定すると,C 言語コンパイラは 3 文字表記 (trigraph sequence) をサポートします。
ANSI C 仕様で規定されている 3 文字表記を使用することにより,ソース・コードセットのすべての文字をサポートしていないキーボードからでも,すべての基本文字をプログラムに入力できます。
現在定義されている 3 文字表記を以下に示します。
各文字表記は,対応する 1 つの文字に置き換えられます。
3 文字表記 | 対応する文字 |
??= |
# |
??( |
[ |
??/ |
\ |
??' |
^ |
??< |
{ |
??) |
] |
??! |
| |
??> |
} |
??- |
~ |
ロケールに依存するプログラムの動作のもう 1 つの特徴に,文字分類が挙げられます。 つまり,特定の文字コードがアルファベットの大文字,アルファベットの小文字,数字,句読点,制御文字,あるいはスペース文字のいずれを表しているのか判定する処理のことです。
従来,多くのプログラムは,文字の値が特定の数値範囲に収まっているかどうかを基準にして,文字の分類を行ってきました。 たとえば,次の文はすべてのアルファベットの大文字をテストします。
if (c >= 'A' && c <= 'Z')
この文は,すべての大文字が
0x41
から
0x5a
(A から Z) までの範囲に収まっている ASCII コードセットでは有効です。
ただし,大文字が
0x41
から
0x5a
まで,0xc0
から
0xd6
まで,および
0xd8
から
0xdf
までの範囲にある ISO 8859-1 コードセットでは有効ではありません。
EBCDIC コードセットでも文字値は異なっており,英語の大文字のエンコーディングそのものが違います。
国際化プログラムを作成するときは,適切な国際化関数を呼び出して文字分類を行います。 次に例を示します。
if (iswupper (c))
国際化関数は,ユーザのロケールの
ctype
情報に基づいてワイド文字のコード値を分類します。
文字分類関数のリストと説明については,A.2 節を参照してください。
2.2.7 文字の変換
国際化プログラムで行ってはいけないことの例として,次の文について考えてみます。
この文は,a_var
内の文字をまず小文字に変換し,次に大文字に変換することによって,ASCII 文字の変換を行います。
a_var |= 0x20;
.
.
.
a_var &= 0xdf;
ただし,上記の文は,ASCII コードの文字値を前提としていることと,入力が不正な値でも変換してしまうことから,国際化プログラムで使用するのは適切ではありません。
大文字と小文字の変換を正しく行うためには,小文字への変換には
towlower()
関数を,大文字への変換には
towupper()
関数を呼び出します。
a_var = towlower(a_var);
.
.
.
a_var = towupper(a_var);
これらの関数は,ユーザのロケールで指定されている情報を使用するため,文字が定義されているコードセットには依存しません。
また,これらの関数は,入力が無効であれば引数を変更せずに返します。
大文字と小文字の変換関数については,A.3 節を参照してください。
2.2.8 文字列の比較
UNIX システムでは,文字列比較のための関数が提供されています。
たとえば,次の文は文字列
s1
と
s2
を比較し,マシンの照合順序で
s1
の値が
s2
よりも大きいか,等しいか,あるいは小さいかに応じて,それぞれ,ゼロよりも大きい値,等しい値,あるいは小さい値を返します。
.
.
.
int cmp_val; char *s1; char *s2;
.
.
.
cmp_val = strcmp(s1, s2);
.
.
.
ただしほとんどの言語では,単なる数値的なソートではなく,より複雑な照合アルゴリズムが必要になります。 複数回のソート・パスが必要になる理由を次に示します。
言語の特定の文字クラスにおけるアクセント文字の順序付けのため (たとえば,a,á,à など)。
特定の複数文字のシーケンスを 1 つの文字として照合するため (たとえば,ウェールズ語の文字 ch は,c の後,d の前に並べられます)。
特定の 1 文字を 2 文字のシーケンスとして照合するため (たとえば,ドイツ語の文字 sharp s は,ss として照合されます)。
照合の際に特定の文字を無視するため (たとえば,辞書の単語に含まれるハイフンは無視されます)。
国際化環境における文字列比較はコードセットと言語に依存します。 そのため,ユーザのロケールの照合順序情報に従って文字列を比較するためには,別の関数が必要になります。 そのような関数の例を次に示します。
この関数は,strcmp()
のような単純な数値比較ではなく,ユーザのロケールの照合順序情報に従ってワイド文字列を比較します。
この関数は,strcoll()
と同じ動作をしますが,ワイド文字を処理します。
この関数は,ユーザのロケールの照合順序情報に従ってワイド文字列を変換し,結果として得られた文字列が
wcscmp()
関数で比較できるようにします。
2 つの文字列が同じかどうかだけを比較するときは,strcmp()
または
wcscmp()
を使用できます。
これらの関数は,ほとんどの環境で
wcscoll()
よりも高速に実行します。
文化的データとは,言語や地域によって異なる可能性がある情報項目のことです。
次に例を示します。
英国と米国では,ピリオドは小数点を表し,コンマは 10 進数の千単位の区切り文字を表すが,ドイツでは 10 進数でのこの 2 つの文字が逆の意味に使用される。
米国では 1986 年 10 月 7 日 を 10/7/1986 と表記するが,英国では同じ日付を 7/10/1986 と表記する。 この例は,同じ言語を使用していても,文化的データ項目が異なることがあることを示します。
日付の区切り文字と,年,月,および日の順序は,国によって異なる。 たとえばドイツでは,1986 年 10 月 7 日 は 7/10/86 ではなく,7.10.86 と表記されます。
通貨記号は,使用される文字と,それが金額値のどこに置かれるかという 2 点で異なる。 通貨記号は値の前,後,あるいは値の中に置かれることがあります。
欧州経済通貨連合に所属する国で通貨記号として使用されるユーロ文字は,Unicode (*.UTF-8
) または Latin-9 (*.ISO8859-15
) ロケールと,対応するフォントでのみサポートされています。
ユーロ通貨記号のサポートについての詳細は,
euro
(5)
キーボードからユーロ文字を入力するには,Latin-9 または UTF-8 のロケールで作業し,適切なキーマップがアクティブでなければなりません。
ユーロ文字を表示するには,Latin-9 または UTF-8 のロケールで作業し,適切なフォントがアクティブでなければなりません。
必要なロケールと,適切なキーマップおよびフォントをアクティブにするには,Latin-9 または UTF-8 のロケールの環境にログインするか,setenv
を使って
LANG
環境変数を設定し,新たに
dtterm
を起動します。
リファレンス・ページ
locale
(1)dtterm
(1)
国際化プログラムを作成するときは,文化的データについて前提を設けることはできません。
プログラムは,ユーザの地域固有の習慣に従って動作しなければなりません。
X/Open の UNIX 標準では,プログラムが実行時にアクセスできる文化的データ項目のデータベースと,それに関連するインタフェース群を利用して,この要件が満たされるように規定しています。
これ以降の項では,このデータベースと,そのデータ項目の抽出と処理に使用される関数について説明します。
2.3.1 langinfo データベース
langinfo
と呼ばれる言語情報データベースには,システム上でサポートされている各ロケールの文化情報の詳細を表す項目が含まれています。
langinfo
データベースは,X/Open の UNIX 標準の規定に従い,ロケールごとに次の情報を含みます。
コードセット名
日付と時刻の書式
曜日の名前
月の名前
曜日の省略形
月の省略形
小数点 (整数と小数部を区切る文字)
千単位の区切り文字
yes/no の問い合わせに対する肯定と否定の応答
通貨記号と,金額値中での通貨記号の位置
元号の名前と年 (日本語のロケール用)
nl_langinfo()
関数を呼び出すことにより,langinfo
データベースから文化的データ項目を抽出できます。
この関数は,ヘッダ・ファイル
/usr/include/langinfo.h
に定義されている定数の 1 つを
item
引数として取ります。
この関数は,現在のロケールにおける
item
の値を含む文字列へのポインタを返します。
次の例は,日付と時刻情報を書式付けるための文字列を抽出する
nl_langinfo()
の呼び出しです。
この値は,定数
D_T_FMT
に対応します。
nl_langinfo(D_T_FMT);
2.3.3 ローカルな習慣に合った日付および時刻文字列の生成と解釈
プログラムでは日付と時刻の文字列が生成されることがよくあります。
国際化プログラムはユーザのローカルな習慣に合った文字列を生成します。
この場合,要件を満たすには,strftime()
または
wcsftime()
関数を呼び出します。
どちらの関数も
langinfo
データベースを間接的に使用します。
さらに,wcsftime()
関数は,日付と時刻をワイド文字形式に変換します。
次の例では,strftime()
関数は,langinfo
データベースの
D_FMT
項目で定義されている日付文字列を生成します。
.
.
.
setlocale(LC_ALL, ""); [1]
.
.
.
clock = time((time_t*)NULL); [2] tm = localtime(&clock); [3]
.
.
.
strftime(buf, size, "%x", tm); [4] puts(buf); [5]
.
.
.
実行時にプログラムを,システムまたは個々のユーザのロケール・セットにバインドします。 [例に戻る]
time()
サブルーチンを呼び出して,時刻値を
clock
変数に返します。
返される時刻値は,協定世界時からの相対値です。
[例に戻る]
localtime()
関数を呼び出して,clock
に格納されている値を,tm
構造体に格納できる値に変換します。
tm
構造体は,年,月,日,時間,分などの値を表すメンバを含みます。
[例に戻る]
strftime()
関数を呼び出して,tm
構造体に格納されている値から,ユーザのロケールで定義されている書式の日付文字列を生成します。
buf
引数は,日付文字列が返される文字列変数へのポインタです。
size
引数は,buf
の最大サイズを含みます。
"%x"
引数は,printf()
と
scanf()
関数で使用される書式文字列と同様な変換指定を指定します。
"%x"
引数は出力文字列中で,ロケールでの適切な表現に置き換えられます。
[例に戻る]
puts()
関数を呼び出して,buf
に含まれている文字列を標準出力ストリーム (stdout
) にコピーし,改行文字を付加します。
[例に戻る]
strftime()
と
nl_langinfo()
を組み合わせて,日付と時刻の文字列を生成する方法を示す,次の例を考えてみます。
前の例と同様に,setlocale()
,time()
,および
localtime()
インタフェースの呼び出しが,ここでも行われているものとします。
ただし,次の例では,strftime()
の呼び出しで,書式文字列引数が
nl_langinfo()
の呼び出しに置き換えられています。
.
.
.
strftime(buf, size, nl_langinfo(D_T_FMT), tm); puts(buf);
.
.
.
文字列から日付と時刻値への変換 (つまり,strftime()
の逆の動作) には,strptime()
関数を使用します。
strptime()
関数では多数の変換指定子がサポートされていますが,その動作はロケールに依存します。
2.3.4 金額値の書式付け
strfmon()
関数は,実行時にプログラムにバインドされるロケール情報に従って,金額値を書式付けます。
次に例を示します。
strfmon(buf, size, "%n", value);
この文は,value
変数に含まれている倍精度浮動小数点値を書式付けます。
"%n"
引数は,実行時のロケールが定義する書式に置き換えられる書式指定です。
結果は
buf
配列に返されます。
この配列の最大長は,size
変数に格納されています。
money
プログラムは,strfmon()
関数がどのように動作するかを示します。
ワールドワイド言語サポート・サブセットをインストールする場合,このサンプル・プログラムのソース・ファイルは
/usr/i18n/examples/money
ディレクトリにインストールされます。
2.3.5 プログラム独自の形式による数値の書式付け
数値,金額値などの独自の変換を行う場合は,ユーザのロケール内の特定の書式情報を使用できます。
localeconv()
関数は引数を取らない関数であり,ロケールで定義されている数値の書式付けに関するすべての情報を,プログラム中で宣言されている構造体に返します。
次に例を示します。
struct lconv *app_conv;
プログラムで定義されているルーチンは,lconv
構造体に格納されている次の情報を使用できます。
小数点文字
千単位の区切り文字
桁のグループ・サイズ
国際通貨記号
国内通貨記号
金額値の小数点文字
金額値の千単位の区切り文字
金額値の桁のグループ・サイズ
正符号
負符号
表示される小数点以下の桁数
負の金額値に使用するカッコ記号
2.3.6 他の処理における langinfo データベースの使用
これまでに説明した関数以外にも,langinfo
データベースを使用して,特定の文化的データ項目の設定を判定する関数があります。
たとえば,wscanf()
,wprintf()
,および
wcstod()
関数は,langinfo
データベースの情報から適切な小数点文字を決定します。
2.4 テキストの表示と入力の処理
アプリケーションを作成する場合,次の 3 つの事柄に関して,ユーザの言語を考慮しなければなりません。
プログラムは,ユーザが使用する言語でユーザと対話しなければなりません。 そのために,プログラム・メッセージをどのように定義して,またどのようにアクセスするかについては,いくつかの制約が課せられています。 具体的には,メッセージはプログラム・ソース・コードとは別のファイルで定義されており,オブジェクト・ファイルにコンパイルされることはありません。 メッセージは別のファイルに含まれるため,メッセージを別の言語に翻訳し,実行時にプログラムにリンクされる形態で格納できます。 このようにしておけば,プログラムは,ユーザの言語に合わせて翻訳されたメッセージ・テキストを取り出すことができます。
X/Open UNIX 標準では,次のメッセージ関数が規定されています。
ソース・ファイルからメッセージ・カタログを生成する
gencat
コマンド
1 つまたは複数のカタログから個々のメッセージを実行時に取り出すライブラリ関数群
次に,国際化プログラムがカタログからメッセージを取り出す例を示します。
#include <stdio.h> [1] #include <locale.h> [2] #include <nl_types.h> [3] #include "prog_msg.h" [4] main() { nl_catd catd; [5] setlocale(LC_ALL, ""); [6] catd = catopen("prog.cat", NL_CAT_LOCALE); [7] puts(catgets(catd, SETN, HELLO_MSG, "Hello, world!")); [8] catclose(catd); [9] }
.
.
.
標準 C ライブラリ用のヘッダ・ファイルをインクルードします。 [例に戻る]
setlocale()
関数と,関連する定数および変数を宣言するヘッダ・ファイル
/usr/include/locale.h
をインクルードします。
[例に戻る]
catopen()
,catgets()
,および
catclose()
関数を宣言するヘッダ・ファイル
/usr/include/nl_types.h
をインクルードします。
[例に戻る]
プログラム固有のヘッダ・ファイル
prog_msg.h
をインクルードします。
このヘッダ・ファイルには,このプログラム・モジュールが使用するメッセージ・セット (SETN) と,個々のメッセージ (この例の HELLO_MSG) を識別する定数が設定されています。
メッセージ・カタログには,1 つまたは複数のメッセージ・セットを含めることができます。 各セットには,個々のメッセージが配置されています。 [例に戻る]
メッセージ・カタログ記述子
catd
を,nl_catd
型として宣言します。
この記述子は,カタログをオープンする関数によって返されます。 またこの記述子は,カタログをクローズする関数への引数としても渡されます。 [例に戻る]
setlocale()
関数を呼び出して,プログラムのロケール・カテゴリを,ユーザのロケール環境変数の設定にバインドします。
LC_MESSAGES
カテゴリに設定されているロケール名は,この例の
catopen()
と
catgets()
関数によって使用されるロケールです。
一般に,システム管理者やユーザは,LANG
または
LC_ALL
環境変数だけを特定のロケール名に設定します。
これにより,LC_MESSAGES
変数も暗黙的に設定されます。
[例に戻る]
catopen()
関数を呼び出して,このプログラムが使用する
prog.cat
というメッセージ・カタログをオープンします。
NL_CAT_LOCALE
引数は,LC_MESSAGES
に設定されているロケール名をプログラムで使用することを指定します。
catopen()
関数は,NLSPATH
環境変数に設定されている値を使用して,メッセージ・カタログの位置を判別します。
この呼び出しは,catd
変数にメッセージ・カタログ記述子を返します。
[例に戻る]
puts()
関数を呼び出して,メッセージを表示します。
この呼び出しの第 1 引数は,catgets()
関数の呼び出しです。
この関数は,HELLO_MSG
識別子を持つメッセージのテキストを取り出します。
このメッセージは,SETN
定数によって識別されるメッセージ・セットに含まれています。
catgets()
の最後の引数は,メッセージ呼び出しがカタログから翻訳テキストを取り出せなかった場合に使用される,省略時のテキストです。
一般に,省略時のテキストは英語です。
[例に戻る]
catclose()
関数を呼び出して,記述子が
catd
変数に格納されているメッセージ・カタログをクローズします。
[例に戻る]
メッセージ・カタログの作成と使用については,第 3 章を参照してください。
2.4.2 出力テキストの書式付け
メッセージをさまざまな言語に翻訳するためには,メッセージをプログラム・ソースから分離するだけでなく,プログラム中のメッセージ文字列を注意深く作成しなければなりません。
printf(catgets(catd, set_id, WRONG_OWNER_MSG, "%s is owned by %s\n"), folder_name, user_name);
上記の文はメッセージ・カタログを使用していますが,特定の言語構造 (名詞の後に受動態の動詞があり,その後に名詞が続く) を想定しています。
動詞の受動態は,すべての言語にあるわけではありません。
そのため,翻訳されたメッセージでは,folder_name
の前に
user_name
がプリントされる可能性があります。
つまり,表示されるメッセージが,"JULY_REVENUE is owned by John_Smith." ではなく,"John_Smith owns JULY_REVENUE" となるように,翻訳者がメッセージの語順を変更しなければならないことがあります。
メッセージ要素の順序が固定されていることから生じる問題を回避するために,printf()
ルーチンの書式指定子では,次の未使用の引数に対して書式変換を行うだけでなく,引数リスト内の
n
番目の引数に対して書式変換を行えるようになりました。
拡張された書式変換を利用するには,変換文字の
%
を,%digit
$
というシーケンスに置き換えます。
digit
は,引数リスト中での引数の位置を指定します。
この機能を書式文字列
"%s is owned by %s\n"
に適用した例を,次に示します。
printf(catgets(catd, set_id, WRONG_OWNER_MSG, "%1$s is owned by %2$s\n"), folder_name, user_name);
翻訳者は,プログラムが使用するメッセージ・ファイル内の
WRONG_OWNER_MSG
エントリの省略値,つまり,文字列
"%1$s is owned by %2$s"
を,次の語順を持つ英語以外の言語に置き換えることができます。
WRONG_OWNER_MSG "%2$s owns %1$s\n"
2.4.2 項で説明した,出力テキストの書式付けに関する問題は,入力テキストでも起こります。
たとえば,ユーザが日付の要素を指定する順序や,金額文字列の各部分を区切るために入力する文字は,国によって異なります。
そのため,scanf()
ファミリの関数でも,ユーザが文字列の要素を入力する方法に柔軟性を持たせるために,拡張書式変換指定子がサポートされています。
次の例について考えてみます。
.
.
.
int day; int month; int year;
.
.
.
scanf("%d/%d/%d", &month, &day, &year);
.
.
.
この文の書式文字列は,すべてのユーザが日付の入力に米国英語の書式 (月/日/年) を使用するという前提に基づいています。 国際化プログラムでは,拡張書式指定子を使用して,文字列要素の順序に関する言語固有の要件をサポートするようにします。 次に例を示します。
.
.
.
scanf(catgets(catd, NL_SETD, DATE_STRING, "%1$d/%2$d/%3$d"), &month, &day, &year);
.
.
.
DATE_STRING メッセージの省略値である
"%1$d/%2$d/%3$d"
は,ユーザが日付の入力に月/日/年の書式を使用する国でのみ有効です。
文字列要素の順序や書式が異なる国では,翻訳者はプログラムのメッセージ・ファイルのエントリを変更できます。
次の言語について考えてみます。
イギリス英語 (日/月/年)
DATE_STRING "%2$d/%1$d/%3$d"
ドイツ語 (日.月.年)
DATE_STRING "%2$d.%1$d.%3$d"
国際化プログラムが正しく動作するためには,ユーザの環境に適した地域化されたデータに実行時にバインドしなければなりません。
この作業は
setlocale()
関数が行います。
setlocale()
を呼び出すと,次の処理が実行されます。
ユーザのプロセスですでに有効になっているロケール設定にバインドする。
プログラムが制御するロケール設定にバインドする。
ロケール設定を変更せずに,現在のロケール設定を照会する。
この呼び出しは,category と locale_name の 2 つの引数を取ります。
category 引数は,照会したい,変更したい,あるいは使用したいロケールのすべての,または特定のセクションを指定します。 category の値と,その意味を次に示します。
LC_ALL
この category 引数は,ロケールのすべてのセクションを指定します (各セクションの指定より優先されます)。
LC_CTYPE
この category 引数は,大文字小文字変換などの操作で使用されるクラスと文字属性を定義します。
LC_COLLATE
この category 引数は,ソートや照合の操作での文字や文字列の順序を指定します。
LC_MESSAGES
この category 引数は,肯定および否定応答と,プログラム・メッセージを指定します。
LC_MONETARY
この category 引数は,金額値に使用される規則や特殊記号を指定します。
LC_NUMERIC
この category 引数は,数値の書式付けに使用される規則や特殊記号を指定します。
LC_TIME
この category 引数は,曜日や月の名前と省略形,日付と時刻の表記を決定するその他の文字列と書式変換を指定します。
locale_name 引数は,次の値のいずれかです。
空の文字列 (""
)。
実行時にシステム管理者またはユーザが,category
に設定されたロケール名にプログラムをバインドします。
ロケール名。 category にすでに設定されているロケールを変更します。
NULL
。
category
に現在設定されているロケール名を調べます。
2.5.1 システムまたはユーザのロケール・セットへのバインド
一般に,システム管理者やユーザは,LANG
または
LC_ALL
環境変数にロケール名を設定します。
これらの環境変数のいずれかを設定すると,ロケールのすべてのロケール・カテゴリ変数に同じロケール名が自動的に設定されます。
LC_ALL
を使用してすべてのロケール・カテゴリに同じロケール名を設定した場合以外は,システム管理者やユーザは,個々のロケール・カテゴリ変数に異なるロケール名を設定できます。
一般に国際化プログラムには,プログラム内のすべてのロケール・カテゴリを,そのユーザに対してすでに有効になっている環境変数設定で初期化するための,LC_ALL
呼び出しが含まれています。
例を次に示します。
setlocale(LC_ALL, "");
標準のロケール名は,language_TERRITORY.codeset@modifier
からなります。
たとえば,zh_CN.dechanzi@radical
です。
意味は,次のとおりです。
language
。
ロケールの言語を示します (zh は中国語)。
_TERRITORY
。
ロケールの地理的な国や領域 (_CN は中国,これに対して TW は台湾,HK は香港)。
.codeset
。
ロケールで使用するコード化文字セット (dechanzi)。
@modifier
。
ロケールの地域化データの追加情報 (radical による照合)
ロケールには通常,複数のバリエーションがあります。
各バリエーションの名前はベースのロケールと同じですが,アット記号 (@) で始まるファイル名サフィックスが付いています。
本来 UNIX にないコードセット (UCS-4 や CP850 など) をサポートするロケール・バリエーションは,LANG
や
LC_ALL
に設定できます。
ただし,1 つのロケール・カテゴリだけベース・ロケールと異なっているロケール・バリエーションは,適切なロケール・カテゴリにのみ割り当ててください。
たとえば,@radical
などの特定の照合シーケンスをサポートするためのロケール・バリエーションは,LC_COLLATE
に設定します。
ユーロ通貨記号 (@euro
) をサポートするためのロケール・バリエーションは,LC_MONETARY
に設定します。
LANG
環境変数の設定には,これらのバリエーションではなく,ベース・ロケール名を使用してください。
さらに,ベース・ロケール名をすべてのロケール・カテゴリに設定するのでなければ,LC_ALL
環境変数は使用しないでください。
この環境変数に値を設定すると,LANG
と,個別のロケール・カテゴリの環境変数の設定が無効になります。
多くのロケール固有ファイルは,ロケール名の言語,地域,およびコードセット部分からなる名前のディレクトリ内に置かれます。
コマンドやその他のシステム・アプリケーションは,ディレクトリ・ノードの 1 つとして
%L
を含む検索パスに,LANG
変数の設定値を挿入します。
これにより,ソフトウェア・プログラムは,現在のロケールで使用されるべき,フォント,リソース・ファイル,ユーザ定義文字ファイル,翻訳済みのリファレンス・ページなどの,正しいセットを見つけることができます。
LANG
変数に設定する値に,照合に関連する
@
サフィックスが含まれていると,ロケール固有のファイルの一部がアプリケーションから見つからなくなることがあります。
2.5.2 プログラム実行時のロケールの変更
国際化プログラムの中には,ユーザからのロケール名の入力を受け付けたり,プログラムの実行中にロケールを変更しなければならないものがあります。
次の例は,setlocale()
を呼び出して,すべてのロケール・カテゴリを同じロケール名で明示的に初期化または再初期化します。
.
.
.
nl_catd catd; [1] char buf[BUFSIZ]; [2]
.
.
.
setlocale(LC_ALL, ""); [3] catd = catopen(CAT_NAME, NL_CAT_LOCALE); [4]
.
.
.
printf(catgets(catd, NL_SETD, LOCALE_PROMPT_MSG, "Enter locale name: ")); [5] gets(buf); [6] setlocale(LC_ALL, buf); [7]
.
.
.
カタログ記述子
catd
を
nl_catd
型 として宣言します。
[例に戻る]
後でロケール名が格納される
buf
変数を宣言します。
プログラムを実行するシステムに関係なく,この変数がロケール名を格納できる十分な大きさになるように,最大サイズを
BUFSIZ
に設定します。
この定数は,システム・ベンダが
/usr/include/stdio.h
で定義しています。
[例に戻る]
setlocale()
を呼び出して,プログラムのロケール設定を,プログラムを実行するユーザに対して有効になっているロケール設定に初期化します。
[例に戻る]
catopen()
を呼び出して,プログラムのメッセージが格納されているメッセージ・カタログをオープンします。
この関数は,カタログ記述子を
catd
変数に返します。
CAT_NAME
定数は,プログラム自体のヘッダ・ファイルで定義されています。
[例に戻る]
ユーザに新しいロケール名の入力を求めます。
NL_SETD
定数は,メッセージ・カタログ中の省略時のメッセージ・セット番号を指定するもので,/usr/include/nl_types.h
で定義されています。
LOCALE_PROMPT_MSG
識別子は,省略時のメッセージ・セット内の翻訳されたプロンプト文字列を指定します。
[例に戻る]
gets()
関数を呼び出して,ユーザが入力したロケール名を読み取り,buf
変数に格納します。
[例に戻る]
locale_name
引数に
buf
を指定して
setlocale()
を呼び出し,ロケール全体を再初期化します。
[例に戻る]
場合によっては,特定のカテゴリのデータについてのみロケールを変更しなければならないことがあります。
たとえば,金額値を含んでいる,いくつかの国固有のファイルを処理するプログラムは,各ファイルのデータを処理する前に,プログラム変数を新しいロケール名で再初期化し,その変数値を使用してロケールの
LC_MONETARY
カテゴリだけを再設定できます。