国際化対応言語環境の利用ガイド

第 2 章 一般的な国際化機能

この章では、Solaris OS に含まれているいくつかの国際化機能について説明します。この章の内容は次のとおりです。

コードセットの独立性のサポート

EUC は Extended UNIX® Code の省略形です。Solaris OS は、日本の PC-Kanji (Shift_JIS)、台湾の Big5、中華人民共和国の GBK のような非 EUC エンコーディングをサポートしています。コンピュータ市場の大半では EUC 以外のコードセットのサポートが要求されるため、最新の Solaris 環境では EUC と非 EUC コードセットのサポートを可能にするフレームワークを提供します。このサポートをコードセットの独立性 (CSI) と呼びます。

CSI の目標は、Solaris OS のライブラリやコマンドから、特定のコードセットやエンコーディング方法への依存性を除去することです。CSI アーキテクチャにより、Solaris OS において UNIX ファイルシステムに安全なエンコーディングをサポートできます。CSI は UTF-8、PC-Kanji、Big5 など、多くの非 EUC コードセットをサポートします。

CSI のアプローチ

CSI により、アプリケーションおよびプラットフォームソフトウェア開発者は、UTF-8 など、エンコーディングからコードを独立させたり、ソースコードを変更せずに新しいエンコーディングを採用したりすることができます。アプリケーションは UTF-16 に依存する必要がないので、このアーキテクチャのアプローチは JavaTM の国際化とも異なります。

既存の多くの国際化アプリケーション (たとえば Motif など) は、基礎となるシステムから自動的に CSI のサポートを継承します。これらのアプリケーションは、変更しなくても新しいロケールで動作します。

CSI は本来どのコードセットにも依存しませんが、最新の Solaris システムではファイルコードのエンコーディング (コードセット) には、次のような前提条件があります。

CSI 対応のコマンド

この節では、最新の Solaris 環境で使用できる CSI 対応のコマンドを示します。各コマンドのマニュアルページでは、属性の節で、そのコマンドが CSI 対応かどうかを説明しています。

特に断りがない限り、これらのコマンドは /usr/bin ディレクトリに格納されています。

CSI 対応のライブラリ

libc (/usr/lib/libc.so) のほとんどすべての関数は CSI に対応しています。ただし、libc の以下の関数は EUC 依存の関数であるため、CSI に対応していません。

最新の Solaris 環境の libgen (/usr/ccs/lib/libgen.a) と libcurses (/usr/ccs/lib/libcurses.a) は国際化されていますが、CSI に対応していません。

ロケールデータベース

ロケールデータベースの形式および構造は非公開であり、将来のリリースで変更される可能性があります。国際化アプリケーションを作成するときには、libc の国際化 API を使用します。この API については、ロケールデータベースとのリンクに関連してではなく libc の国際化 API」で説明されています。


注 –

Solaris 環境を使用する場合は、Solaris の最新リリースに含まれているロケールデータベースを使用してください。以前のバージョンの Solaris のロケールデータベースを使用しないでください。


プロセスコードの書式 (ワイド文字表現)

プロセスコードの書式 (Solaris OS ではワイド文字コード形式ともいう) は公開されていません。そのため、将来のリリースで変更されることがあります。したがって、国際化アプリケーションを作成するときには、このワイド文字の形式が将来変更される可能性があることに注意してください。その代わりに libc の国際化 API を使用することをお勧めします (libc の国際化 API」を参照)。


注 –

Unicode ロケールのプロセスコードは UTF 32 で表現されています。UTF 32 の詳細については、Unicode Consortium (http://www.unicode.org/) の「Unicode Standard Annex #19: UTF 32」と「Unicode Standard Annex #27: Unicode 3.1」を参照してください。


複数バイトサポート環境

複数バイト文字はシングルバイトとして保存できない文字の総称で、中国語、日本語、韓国語などの文字を含みます。複数バイト文字を格納するには、2、3、または 4 バイトが必要です。より詳細な定義については、ISO/IECC 9899:1990 サブクラス 3.13 の項目を参照してください。

ANSI C の Amendment 1 (ISO/IEC 9899:1990) では、Multibyte Support Environment (MSE) と呼ぶ新しい国際化機能が追加されました。Amendment 1 には、状態属性を持つ複数バイトコードセットやワイド文字の処理サポートを強化するための新しい国際化 API が定義されています。

プログラミングモデルでは、これらの複数バイト文字を論理ユニットとして読み込み、ワイド文字として内部的に保持できます。プログラム内において、ワイド文字は論理エン ティティとして取り扱うことができます。また、適切な変換処理を行なったのち、これらワイド文字を論理ユニットとして出力できます。

この手順は、シングルバイト文字を読み込んで加工したのち出力する場合と似ています。このため MSE によって、シングルバイト文字の場合と同じプログラミングモデルを用いて複数バイト文字をプログラムで取り扱うことができます。

動的にリンクされたアプリケーション

アプリケーションを libc などのシステムライブラリにリンクする方法として、動的リンクと静的リンクを選択できます。システムライブラリの国際化機能を必要とするアプリケーションは動的にリンクしなければなりません。このようなアプリケーションが静的にリンクされている場合は、setlocale 関数を使用してロケールを C または POSIX 以外のものに設定する操作は失敗します。静的にリンクされたアプリケーションは、C および POSIX ロケールでのみ動作します。

デフォルトでは、リンカープログラムはアプリケーションを動的にリンクしようとします。リンカーやコンパイラのコマンド行のオプションとして、-Bstatic-dn を指定すると、アプリケーションは静的にリンクされる場合があります。既存のアプリケーションが動的にリンクされているかどうかを調べるには、/usr/bin/ldd コマンドを使用します。

たとえば、次のコマンドに対する応答によって、/sbin/sh コマンドが動的にリンクされたプログラムではないことがわかります。


% /usr/bin/ldd /sbin/sh
ldd: /sbin/sh: file is not a dynamic executable or shared object

次のコマンドに対する応答は、/usr/bin/ls コマンドは 2 つのライブラリ libc.solibdl.so.l に動的にリンクされていることを示します。


% /usr/bin/ldd /usr/bin/ls
libc.so.1 => 	/usr/lib/libc.so.1
libdl.so.1 => /usr/lib/libdl.so.1

変更されたインタフェースについて

libwlibintllibc に移動されました。したがって、libwlibintl はありません。

共有オブジェクトは、既存のアプリケーションの実行の互換性を保証し、アーカイブとともにアプリケーションのビルド (コンパイル) 環境の互換性を提供します。ただし、libwlibintl 付きでアプリケーションをビルドする必要はなくなりました。

次のリストは、libw のスタブ (Stub) エントリポイントを示しています。

次のリストは、libintl のスタブ (Stub) エントリポイントを示しています。

ctype マクロ

文字の分類や文字の変換マクロは、/usr/include/ctype.h で定義されています。最新の Solaris 環境では、XPG4 で定義されている文字の分類および変換セマンティクスをサポートする一連の ctype マクロが提供されています。XPG4XPG4.2 アプリケーションから新しいマクロに自動的にアクセスするためには、次の条件のどれかが満たされていなければなりません。

_XOPEN_SOURCE_XOPEN_VERSION_XOPEN_SOURCE_ECTENDED は、新しい ctype マクロのほかに XPG4 関連機能をもたらすので、XPG4 または XPG4.2 以外のアプリケーションは _XPG4_CHAR_CLASS_ を使用しなければなりません。

これに対応する ctype 関数もあります。最新の Solaris 環境は XPG4 セマンティクスもサポートします。

libc の国際化 API

最新の Solaris 環境は 2 種類の API を提供します。

ワイド文字コードは、一定の幅を持つ論理エンティティです。したがって、複数バイトを使用する時のように適切な文字境界を管理する必要はありません。

プログラムでファイルから入力を受け取る際には、fscanffwscanf などの入力関数を使ってファイルの複数バイトデータを直接ワイド文字のプロセスコードに変換できます。あるいは、データの入力後に mbtowcmbsrtowcs などの変換関数を使ってデータを変換することもできます。出力データのワイド文字形式を複数バイト文字形式に変換する場合は、fwprintffprintf などの出力関数を使って直接変換するか、出力前に wctombwcsrtombs などの変換関数を使って変換します。

以下の各表に、最新の Solaris 製品の国際化 API を示します。

次の表は libc のメッセージング関数 API です。

表 2–1 libc のメッセージング関数

ライブラリルーチン 

説明 

bindtextdomain()

メッセージドメインパスをバインドする 

catclose()

メッセージカタログを閉じる 

catgets()

プログラムメッセージを読み取る 

catopen()

メッセージカタログを開く 

dcgettext()

指定したドメインとカテゴリのメッセージカタログからメッセージを取得する 

dgettext()

指定したドメインのメッセージカタログからメッセージを取得する 

gettext()

メッセージデータベースからテキスト文字列を取得する 

textdomain()

現在のドメインを設定および照会する 

次の表に libc のコード変換関数 API を示します。

表 2–2 libc のコード変換関数

ライブラリルーチン 

説明 

iconv()

コードを変換する 

iconv_close()

変換記述子の割り当てを解除する 

iconv_open()

変換記述子を割り当てる 

次の表に libc の正規表現 API を示します。

表 2–3 libc の正規表現関数

ライブラリルーチン 

説明 

fnmatch()

ファイル名またはパス名を照合する 

regcomp()

正規表現をコンパイルする 

regerror()

エラーコードとエラーメッセージのマッピングを行う 

regexec()

正規表現の照合を実行する 

regfree()

regcomp() により割り当てられたメモリーを解放する

次の表に libc のワイド文字関数 API を示します。

表 2–4 libc のワイド文字クラス

ライブラリルーチン 

説明 

wctrans()

文字のマッピングを定義する 

wctype()

文字クラスを定義する 

次の表に libc のロケールの変更および照会を行う API を示します。

表 2–5 libc のロケールの変更および照会関数

ライブラリルーチン 

説明 

setlocale()

プログラムのロケールを変更および照会を行う 

次の表に libc のロケールデータを照会する API を示します。

表 2–6 libc のロケールデータ照会関数

ライブラリルーチン 

説明 

localeconv()

現在のロケールの通貨および数値形式の情報を取得する 

nl_langinfo()

現在のロケールの言語および文化情報を取得する 

次の表に libc の文字分類関数 API を示します。

表 2–7 libc の文字分類および変換関数

ライブラリルーチン 

説明 

isalnum()

文字は英数字か 

isalpha()

文字はアルファベットか 

isascii()

文字は ASCII 文字か 

iscntrl()

文字は制御文字か 

isdigit()

文字は数か 

isenglish()

ワイド文字は補助コードセットの英語のアルファベットか 

isgraph()

文字は表示可能な文字か 

isideogram()

ワイド文字は表意文字か 

islower()

文字は小文字か 

isnumber()

ワイド文字は補助コードセットの数か 

isphonogram()

ワイド文字は表音文字か 

isprint()

文字は印刷可能か 

ispunct()

文字は句読点か 

isspace()

文字は空白か 

isspecial()

ワイド文字は補助コードセットの文字か 

isupper()

文字は大文字か 

iswalnum()

ワイド文字は英数字か 

iswalpha()

ワイド文字はアルファベットか 

iswascii()

ワイド文字は ASCII 文字か 

iswcntrl()

ワイド文字は制御文字か 

iswdigit()

ワイド文字は数か 

iswgraph()

ワイド文字は表示可能な文字か 

iswlower()

ワイド文字は小文字か 

iswprint()

ワイド文字は印刷可能な文字か 

iswpunct()

ワイド文字は句読点か 

iswspace()

ワイド文字は空白か 

iswupper()

ワイド文字は大文字か 

iswxdigit()

ワイド文字は 16 進数か 

isxdigit()

文字は 16 進数か 

tolower()

大文字を小文字に変換する 

toupper()

小文字を大文字に変換する 

towctrans()

ワイド文字のマッピング 

towlower()

ワイド文字の大文字を小文字に変換する 

towupper()

ワイド文字の小文字を大文字に変換する 

次の表に libc の文字照合関数 API を示します。

表 2–8 libc の文字照合関数

ライブラリルーチン 

説明 

strcoll()

文字列を照合する 

strxfrm()

文字列を照合用に変換する 

wcscoll()

ワイド文字の文字列を照合する 

wcsxfrm()

ワイド文字の文字列を照合用に変換する 

次の表に libc の通貨処理関数 API を示します。

表 2–9 libc の通貨処理関数

ライブラリルーチン 

説明 

localeconv()

現在のロケールの通貨形式情報を取得する 

strfmon()

通貨の値を文字列表現に変換する 

次の表に libc の日付と時間の処理関数を示します。

表 2–10 libc の日付と時間の処理関数

ライブラリルーチン 

説明 

getdate()

ユーザー形式の日付と時間を変換する 

strftime()

日付と時間を文字列表現に変換する。%u の変換機能は、X/Open CAE 仕様、System Interfaces and Headers, Issue 4, Version 2 に準拠しています。この機能は、10 進法の 1 から 7 で週日を表しており、現在では 1 が月曜日を表します。

strptime()

日付と時間の変換 

次の表に libc の複数バイト処理関数 API を示します。

表 2–11 libc の複数バイト処理関数

ライブラリルーチン 

説明 

btowc()

シングルバイトからワイド文字に変換する 

mblen()

文字のバイト数を取得する 

mbrlen()

1 つの文字に含まれるバイト数を取得する (再起動可能) 

mbrtowc()

1 つの文字を 1 つのワイド文字に変換する (再起動可能) 

mbsinit()

変換オブジェクトの状態を決定する 

mbsrtowcs()

文字列をワイド文字の文字列に変換する (再起動可能) 

mbstowcs()

文字列をワイド文字の文字列に変換する 

mbtowc()

1 つの文字を 1 つのワイド文字に変換する 

次の表に libc のワイド文字および文字列処理関数を示します。

表 2–12 libc のワイド文字および文字処理

ライブラリルーチン 

説明 

wcrtomb()

ワイド文字から文字に変換する (再起動可能) 

wcscat()

ワイド文字の文字列を照合する 

wcschr()

ワイド文字の文字列内の文字を検索する 

wcscmp()

ワイド文字の文字列を比較する 

wcscpy()

ワイド文字の文字列をコピーする 

wcscspn()

ワイド文字の文字列が別のワイド文字の文字列に現れない長さを返す 

wcslen()

ワイド文字の文字列の長さを取得する 

wcsncat()

ワイド文字の文字列を長さ n に連結する

wcsncmp()

ワイド文字の文字列を長さ n 分比較する

wcsncpy()

ワイド文字の文字列を長さ n 分コピーする

wcspbrk()

別のワイド文字の文字列に含まれている、ワイド文字の文字列の先頭のポインタを返す 

wcsrchr()

ワイド文字の文字列を右から検索する 

wcsrtombs()

文字列をワイド文字の文字列に変換する (再起動可能) 

wcsspn()

ワイド文字の文字列が別のワイド文字の文字列に現れる長さを返す 

wcstod()

ワイド文字の文字列を倍精度に変換する 

wcstok()

ワイド文字の文字列の中でトークンを移動する 

wcstol()

ワイド文字の文字列をロング整数に変換する 

wcstombs()

ワイド文字の文字列を複数バイトの文字列に変換する 

wcstoul()

ワイド文字の文字列を符号なしロング整数に変換する 

wscwcs()

ワイド文字の文字列内の文字列を検索する 

wcswidth()

ワイド文字の文字列のカラム数を調べる 

wctob()

ワイド文字からシングルバイト文字に変換する 

wctomb()

ワイド文字を複数バイト文字に変換する 

wcwidth()

ワイド文字のカラム数を調べる 

wscol()

ワイド文字の文字列の表示幅を返す 

wsdup()

ワイド文字の文字列を重複させる 

次の表に libc のワイド文字入力および出力の書式化関数を示します。

表 2–13 libc のワイド文字入力および出力の書式化関数

ライブラリルーチン 

説明 

fwprintf()

ワイド文字書式付き出力を印刷する 

fwscanf()

ワイド文字書式付き入力を変換する 

swprintf()

ワイド文字書式付き出力を印刷する 

swscanf()

ワイド文字書式付き入力を変換する 

vfwprintf()

stdarg 引数リストをワイド文字書式で出力する

vswprintf()

stdarg 引数リストをワイド文字書式で出力する

wprintf()

ワイド文字書式付き出力を印刷する 

wscanf()

ワイド文字書式付き入力を変換する 

wsprintf()

書式に従ってワイド文字の文字列を生成する 

wsscanf()

書式付き入力規約 

次の表に libc のワイド文字列関数 API を示します。

表 2–14 libc のワイド文字列関数

ライブラリルーチン 

説明 

wcsstr()

ワイド文字の部分文字列を検索する 

wmemchr()

ワイド文字をメモリー内で検索する 

wmemcmp()

メモリー内のワイド文字を比較する 

wmemcpy()

メモリー内のワイド文字をコピーする 

wmemmove()

領域がオーバーラップする状態でメモリー内のワイド文字をコピーする 

wmemset()

メモリ内のワイド文字を設定する 

wscasecmp()

大文字と小文字を区別せずにワイド文字の文字列を比較する 

wsncasecmp()

コード文字列動作を処理する 

次の表に libc のワイド文字入力および出力関数を示します。

表 2–15 libc のワイド文字入力および出力関数

ライブラリルーチン 

説明 

fgetwc()

ストリームから複数バイト文字を取り出し、ワイド文字に変換する 

fgetws()

ストリームから複数バイトの文字列を取り出し、ワイド文字に変換する 

fputwc()

ワイド文字を複数バイト文字に変換し、ストリームに送る 

fputws()

ワイド文字を複数バイトの文字列に変換し、ストリームに送る 

fwide()

ストリームの方向を設定する 

getwchar()

標準入力から複数バイト文字を取り出し、ワイド文字に変換する

getws()

標準入力から複数バイト文字列を取り出し、ワイド文字に変換する

putwchar()

ワイド文字を複数バイト文字に変換し、標準入力に送る

putws()

ワイド文字を複数バイト文字列に変換し、標準入力に送る

ungetwc()

ワイド文字を入力ストリームに戻す 

genmsg ユーティリティ

新しい genmsg ユーティリティは、国際化されたソースメッセージカタログを作成するために、catgets() ファミリの関数で使用されます。このユーティリティは、ソースプログラムファイルの catgets での関数の呼び出しを調べ、見つかった情報からソースメッセージカタログを作成します。たとえば、次のようにします。

% cat example.c
	...
	/* NOTE: %s is a file name */
	printf(catgets(catd, 5, 1, "%s cannot be opened."));
	/* NOTE: "Read" is a past participle, not a present
 
			tense verb */
	printf(catgets(catd, 5, 1, "Read"));
	...
% genmsg -c NOTE example.c
The following file(s) have been created.
			new msg file = "example.c.msg"
% cat example.c.msg
$quote "
$set 5
1			"%s cannot be opened"
	/* NOTE: %s is a file name */
2			"Read"
	/* NOTE: "Read" is a past participle, not a present
			tense verb */

上記の例では、ソースファイル example.c について genmsg が実行され、example.c.msg という名前のソースメッセージカタログが作成されています。-c オプションの引数 NOTE により、genmsg はカタログにコメントを含めます。ソースプログラムのコメントに指定された文字列が含まれている場合、コメントはメッセージカタログの catgets の呼び出しから抽出された次の文字列の後に表示されます。

genmsg を使用して、メッセージセット内のメッセージの番号を自動的に付けることができます。

詳細については、genmsg(1) のマニュアルページを参照してください。

フォーマットされたメッセージカタログファイルを生成する場合は、gencat(1) ユーティリティを使用します。

ポータブルメッセージファイル (.po ファイル) に対するメッセージ抽出ユーティリティ、および .po ファイルからメッセージオブジェクトファイル (.mo ファイル) を生成する方法については、それぞれ xgettext(1)msgfmt(1) のマニュアルページを参照してください。

ユーザーによるコード変換の定義と拡張

geniconvtbl ユーティリティを使ってコードセットコンバータを定義できます。

このユーティリティを使用すると、ユーザー定義の、またユーザーによるカスタマイズが可能なコードセットの変換を iconv(1)iconv(3C) などの標準システムユーティリティやインタフェースによって行えます。そのため、互換性のないデータ形式 (特にメーカー独自のアプリケーションや従来のアプリケーションのデータ) をアプリケーションで処理することが容易になります。既存の Solaris コードセット変換を変更することもできます。

このユーティリティで使用する入力ソースファイルの例は /usr/lib/iconv/geniconvtbl/srcs/ ディレクトリにあります。

ユーザーが定義して適切に配置したコード変換は、32 ビットおよび 64 ビット Solaris OS の iconv(1) ユーティリティや iconv(3C) 関数から使用できます。

国際化ドメイン名 (IDN) のサポート

国際化ドメイン名 (IDN) によって、ホスト名およびドメイン名に英語以外の言語を使用できます。英語以外のホスト名およびドメイン名を使用するには、RFC 3490 で指定されるリゾルバルーチンに名前を送信する前に、ASCII 互換エンコーディング (ACE) 名に変換します。システム管理アプリケーションが IDN をサポートしない場合、システム管理者はシステムのファイルおよびアプリケーションにも ACE 名を使用する必要があります。

RFC 3490「アプリケーションにおける国際化ドメイン名 (IDNA)」を参照してください。

libidnkit(3EXT) の国際化ドメイン名の API は、UTF-8 またはアプリケーションロケールのコードセットと ACE の便利な変換機能を提供します。idn_decodename2(3EXT) を使用する場合、入力引数のコードセットとして任意のコードセット名を指定することもできます。

図 2–1 IDN から ACE への変換

図は、非英語名の ASCII 互換エンコード文字列への変換を示します

図 2–2 ACE から IDN への変換

図は、ASCII 互換エンコード文字列の非英語名への変換を示します

次の表は、使用可能な双方向の iconv コード変換です。

表 2–16 iconv コード変換

元のコード 

変換後のコード 

ACE 

ACE-ALLOW-UNASSIGNED 

UTF-8 

UTF-8 

UTF-8 

UTF-8 

ACE 

ACE-ALLOW-UNASSIGNED 

ACE と ACE-ALLOW-UNASSIGNED の iconv コード変換名には次の意味があります。

次の例は、hostnames.txt ファイルからの入力による ACE から UTF-8 への変換です。出力は標準出力に送られます。

system% iconv -f ACE -t UTF-8 hostnames.txt

専用の IDN 変換ユーティリティ idnconv(1) では、さまざまなオプションとともに IDN 変換が可能です。オプションによって変換の詳細を制御できます。

IDN、変換ルーチン、および iconv コード変換については、libidnkit(3LIB)idn_decodename(3EXT)idn_decodename2(3EXT)idn_encodename(3EXT)、および iconv_en_US.UTF-8(5) のマニュアルページを参照してください。