# idnkitの設定

idnkitをインストールした後で行う設定作業について、記します。

- 設定ファイルについて
- 設定ファイルの内容
- 設定の必要性
- ローカルエンコーディング
- エンコーディング別名定義ファイル
- 言語別名定義ファイル
- マップファイル
- セットファイル
- 環境変数

## 設定ファイルについて

idnkitライブラリやidnkitliteライブラリ (以下単に「idnkitライブラリ」 と表記) には設定ファイルがあり、設定値を変えると国際化ドメイン名の 変換処理の挙動が変わります。

idnkitライブラリを利用したアプリケーションも、この設定ファイルを 容易に読み込むことができます。 idnkitに付属するidnconv2, idncmp, idncheckコマンドも、 「設定ファイルは読み込まない」ことを指示する`-noconf` オプションを指定しない限り、自動で設定ファイルを読み込むように なっています。

ただし、設定ファイルは必ず存在しなくてはならないわけではありません。 実際の使用時に設定ファイルが必要かどうかや、設定の変更が必要かどうかの 判断については、「設定の必要性」に 記してあります。 特にidnkitを使い始めたばかりで、必要性について判断が難しければ、 インストール直後の状態のまま使うことをお薦めします。

設定ファイルのパスは、標準では次の通りになります。

種別 | 設定ファイル
--- | ---
ユーザの設定ファイル | ユーザのホームディレクトリの`.idn2rc`
システムの設定ファイル | `SYSCONFDIR`ディレクトリ*1 の `idn2.conf`

*1: `SYSCONFDIR`は、idnkitをインストールする際に `configure`の --prefixオプションや --sysconfdirオプション で決定されます。

ただし、ユーザの設定ファイルが存在した場合、システムの設定ファイルは 読み込まれません。

> idnkitバージョン1とは、設定ファイル名が異なる点に注意して下さい。 バージョン1ではそれぞれ`.idnrc`、`idn.conf` になっています。

ソースコードからidnkitをインストールした場合、システムの設定ファイル が存在しなければ、サンプルの設定ファイルと同内容のものが自動的に インストールされます。

## 設定ファイルの内容

idnkitの設定ファイルはテキストファイルで、ファイルの各行は、次の ような単純な形式で構成されます。

> キーワード 値 ...

キーワードや値は、1個以上の空白もしくはタブで区切る必要があります。 ただし、空行と「`#`」で始まるコメント行はすべて無視されます。

> 特に断らない限り、キーワードや値の大文字と小文字 は厳密に区別されますので、ご注意下さい。

以下、個々の設定項目について説明します。

### `language`

`language`エントリでは、「現在の言語」を指定します。 「現在の言語」は、idnkitライブラリが言語固有の小文字変換 (`map`の`loewercase`) および言語別ローカルマップ (`map`の`language-local`) を行う際に使用されます。 本エントリは、一回だけしか記述できません。 本エントリを記述しなかったときは、実行時のロケール情報から「現在の言語」 が決定されます。

[構文]

> `language` 言語名

言語名には、 ISO639言語コード を指定します。 ISO639-1 (例: en) とISO639-2 (例: eng) のどちらも認識します。 大文字、小文字は区別しません。

[設定例]

> `language tr`

### `map`

`map`エントリでは、マッピング処理を指定します。 IDNA2003のNameprepとは異なり、IDNA2008ではマッピング処理 (エンコード、デコード処理の際、入力されたドメイン名に対して前処理 として行う変換) が厳密に規定されていません。 idnkitライブラリは、本エントリの記述にしたがってマッピング処理を 行います。

[構文]

> `map` 処理名 ...

処理名には以下のものが指定できます。

処理名 | 説明
--- | ---
`lowercase` | ラテン語系文字の大文字を、対応する小文字に変換*1
`width` | 全角文字および半角文字を、対応する通常文字へ変換
`nfc` | Unicodeの正規化形式C (NFC; Unicode Normalization Form C)
`nfkc` | Unicodeの正規化形式KC (NFKC; Unicode Normalization Form KC)
`delimitermap` | 特定のUnicodeコードポイントを "." (U+002E; FULL STOP) に変換
`tr46-map` | UTS (Unicode Technical Standard) #46 のnon-transitional mapping (非移行期用マッピング)
`tr46-map-deviation` | UTS (Unicode Technical Standard) #46 のtransitional mapping (移行期用マッピング)
`tr46-check` | UTS (Unicode Technical Standard) #46 のnon-transitional validation (非移行期用チェック)
`tr46-check-deviation` | UTS (Unicode Technical Standard) #46 のtransitional validation (移行期用チェック)
`language-local` | 言語別ローカルマッピング
`tld-local` | TLD別ローカルマッピング
`rfc5895` | `lowercase`, `width`, `nfc`, `delimitermap`をこの順序で実行
`resman-idna2008-mappings-01` | `rfc5895`と同じ
`tr46-processing` | `tr46-map`, `nfc`, `tr46-check` をこの順序で実行
`tr46-processing-deviation` | `tr46-map-deviation`, `nfc`, `tr46-check-deviation`をこの順序で実行 |

*1: Unicode文字データベース (Unicode Character Database)の `SpecialCasing.txt`, `UnicodeData.txt`で 定義された変換則に従って変換を行います。 「現在の言語」の設定に応じて、変換結果が変わります。

[設定例]

> map lowercase width nfkc delimitermap

各処理は、エントリに記述された順序の通りに実行されます。 同じ処理を、二度以上指定することも可能です。たとえば、

> map nfc language-local nfc

とした場合、idnkitライブラリはNFC、言語別ローカルマップ、そして再度 NFCという順番で変換を行います。

本エントリは、一回だけしか記述できません。 本エントリを記述しなかったときは、

> map rfc5895 language-local nfc

が指定されたものと見なされます。

### `delimiters`

`delimiters`エントリでは、マッピング処理`delimitermap` の際にどのコードポイントを「.」(U+002E; FULL STOP) に変換するのかを 指定します。 このマッピング処理は、`map`エントリに`delimitermap` を指定した場合にだけ行われます。 `map`エントリに`delimitermap`を指定していなくても、 `delimiters`エントリを記述することは可能ですが、効果はまったく ありません。

[構文]

> `delimiters` コードポイント ...

コードポイントには、Unicodeのコードポイント値を16進数で 表したもの (例: 3002) を記述します。 頭に「`U+`」を付けても構いません (例: `U+3002`)。

[設定例]

> delimiters 3002

本エントリは、一回だけしか記述できません。 本エントリを記述しなかったときは、「3002」が指定されたものとみなします。

### `language-local`

`language-local`エントリでは、「現在の言語」に応じて行う、 言語固有のマッピングを指定します。 このマッピング処理は、`map`エントリに`language-local` を指定した場合にだけ行われます。 `map`エントリに`language-local`を指定していなくても、 `language-local`エントリを記述することは可能ですが、効果は まったくありません。

[構文]

> `language-local` 言語名 マップファイル

[設定例]

>     language-local tr /some/where/tr.map
>     language-local ja /some/where/ja.map
>     language-local *  /some/where/default.map

「現在の言語」が言語名に一致した場合、 マップファイルで指定されたマッピングが適用されます。 一致していない場合は、マッピングは行われません。 言語名には、 ISO639言語コード を指定します。 ISO639-1 (例: en) とISO639-2 (例: eng) のどちらも認識します。 大文字、小文字は区別しません。

言語名に「`*`」を指定すると、デフォルトの マッピングとして扱われます。 「現在の言語」が他の`language-local`エントリ内で指定されて いる言語名のいずれにも一致しない場合、このデフォルトのマッピングが 適用されます。

マップファイルの書式については、 「マップファイル」を参照して下さい。

### `tld-local`

`tld-local`エントリでは、エンコード/デコード対象となるドメイン名 のTLD (トップレベルドメイン) に応じて行うマッピングを指定します。 このマッピング処理は、`map`エントリに`tld-local` を指定した場合にだけ行われます。 `map`エントリに`tld-local`を指定していなくても、 `tld-local`エントリを記述することは可能ですが、効果は まったくありません。

[構文]

> `tld-local` TLD マップファイル

[設定例]

>     local-map tr /some/where/tr.map
>     local-map jp /some/where/jp.map
>     local-map -  /some/where/notld.map
>     local-map .  /some/where/default.map

TLDの大文字、小文字は区別されません。 ただし`tld-local`は、TLD自身が国際化ドメイン名で表現 されているケース (国際化TLD) を正しく扱えません。 国際化TLDを扱う場合は、`tld-local`の代わりに、 `language-local`を使用する ことをお薦めします。

TLDに「`*`」を指定すると、デフォルトのマッピング として扱われます。 「現在の言語」が、他の`tld-local`エントリ内で指定されて いる言語名のいずれにも一致しない場合、このデフォルトのマッピングが 適用されます。 TLDに「`-`」を指定すると、「.」を含まない ドメイン名に対してそのマッピングが適用されます。

マッピングファイルの書式については 「マップファイル」を 参照して下さい。

## 設定ファイルの必要性

idnkitライブラリを用いたアプリケーションでは、設定ファイルを読み込む に当たり、2つの選択肢があります。

- 標準パスにある設定ファイルを読み込む
- 任意のパスにある設定ファイルを指定して読み込む

後者は通常、ユーザが指定した設定ファイルを読み込むよう指示された際に 生じます。 idnconv2, idncmp, idncheckコマンドの`-conf`オプションが ちょうどこれに該当します。 それ以外は、ほぼ前者のケースといって差し支えないでしょう。

アプリケーションが標準パスの設定ファイルを読み込む場合は、 たとえファイルが存在しなくてもエラーにはならず、代わりに標準的な 設定が自動的に行われます。 したがって標準的な設定で支障がない場合は、設定ファイルを用意する 必要はありません。

設定ファイルでセットできるエントリのデフォルト値は、まとめると 次のようになっています。

エントリ | デフォルト値
--- | ---
`language` | 実行時にロケールから決定
`map` | `rfc5895 language-local nfc`
`delimiters` | 3002
`language-local` | なし
`tld-local` | なし

上記の設定のままで構わなければ、標準パスの設定ファイルは用意しなく ても構いません。 ただし、特定のパスにある設定ファイルを読み込ませる場合は、その ファイルが存在しなければエラーになりますので、ご注意下さい。

## ローカルエンコーディング

idnkitライブラリは、ローカルエンコーディングをロケールや環境変数から 自動判定するため、設定ファイルにはローカルエンコーディングを指定する エントリはありません。 ただし以下のような場合、自動判定は正しく行われません。

1. ロケールから推定したローカルエンコーディングが間違っている
2. ロケールから推定したローカルエンコーディングを`iconv()` が認識できない
3. Cロケールのままアプリケーションを実行した

1番目は、たとえばロケールに "japanese" のような、具体的なエンコーディング の名称を含まないものを設定していると起きる可能性があります。 2番目は、たとえばロケールに "ja_JP.eucJP" を設定していた場合、 `iconv()`は "EUC-JP" を認識できても "eucJP" は指定できなかった という場合に起こり得ます。 3番目は、アプリケーションが`setlocale()`によるロケール設定 の初期化を行わないまま、idnkitライブラリの使用を開始した場合などに 起こります。

この問題を根本的に解決するためには、原因に応じて対策を講じる必要が あります。 しかし3番目の場合などは、アプリケーション側で`setlocale()` を呼び出すように改修する以外ありません。 そこで簡単な回避策として、idnkitライブラリでは環境変数 `IDN_LOCAL_CODESET`を指定する方法を用意しています。

`IDN_LOCAL_CODESET`をがセットされていると、ロケールの設定に かかわらず、この環境変数の値がローカルエンコーディング名とみなされます。 たとえばローカルエンコーディングをEUC-JPに設定する場合には、 あらかじめ次のような設定をしておきます。

[設定例]

> sh系のシェルの場合:
> `$ IDN_LOCAL_CODESET=EUC-JP
> $ export IDN_LOCAL_CODESET
> `

> csh系のシェルの場合:
> `% setenv IDN_LOCAL_CODESET EUC-JP`

もしあなたが単一のローカルエンコーディングしか使用していないのであれば、 環境変数`IDN_LOCAL_CODESET`の設定を、シェルが起動した際に 自動的に読み込むファイル (`.profile`や`.cshrc` など) に入れておくことをお薦めします。

なお、idnkit付属のidnconv2, idncmp, idncheckコマンドを使用する場合は、 コマンド行オプションでローカルエンコーディングを指定する方法もあります。 (詳しくは、各コマンドのドキュメントを参照して下さい。) コマンド行オプションによる指定は、環境変数`IDN_LOCAL_CODESET` やロケールの設定よりもさらに優先されます。

## エンコーディング別名定義ファイル

設定ファイルとは別に、idnkitには「エンコーディング別名定義ファイル」 というファイルがあります。 このファイルには、エンコーディング名称を「別名」から「正式名」への変換 する規則を定義します。

エンコーディング別名定義ファイルは、`SYSCONFDIR`ディレクトリ の下の`idnalias.conf`になります。 (`SYSCONFDIR`は、idnkitをインストールする際に `configure`の --prefixオプションや --sysconfdirオプション で決定されます。)

idnkitライブラリがエンコーディング名にしたがって処理を行う際は、常に この別名定義ファイルの記述にしたがって、暗黙的に正式名へ変換してから 処理を行います。 具体的には、次のような箇所で指定されたエンコーディング名に対して、 変換が行われます。

- idnconv2, idncmp, idncheckコマンドの`-in`オプション
- idnconv2コマンドの`-out`オプション
- 環境変数`IDN_LOCAL_CODESET`
- 実行時、ロケール設定から推測したローカルエンコーディング名
- 高レベルAPIの`idn_setlocalencoding()`関数で指定した ローカルエンコーディング名
- resconfモジュールの`idn_resconf_setlocalencoding()`関数 で指定したローカルエンコーディング名

コマンドのオプションとして渡されたエンコーディング名については、 コマンド自身が正式名に変換するのではなく、あくまでコマンドが呼び出した idnkitライブラリのAPIによって自動的に変換が行われます。 したがって、idnkitライブラリを使ったアプリケーションにおいても、 同様の変換が自動的に行われることになります。

なぜこのような処理が必要なのかというと、`iconv()`は実装に よって認識できるエンコーディング名が異なるためです。 たとえば、ある実装では "eucJP" を認識するけれども "EUC-JP" は認識しない、 といったことが実際にあります。 別名定義ファイルを使うことで、`iconv()`が認識できない別名 を認識できる正式名に変換することによって、`iconv()`の実装 による差異を吸収することができます。

ソースコードからidnkitをインストールした場合、エンコーディング 別名定義ファイルがシステム上に存在しなければ、サンプルの定義ファイル と同内容のものが自動的にインストールされます。 通常はこれを使えば問題ないでしょう。 ファイルの内容を変更したい場合は、以下の要領で行って下さい。

別名定義ファイルは単純なテキストファイルです。 「`#`」で始まる行および空行は、無視されます。 それ以外の行は、次のような形式でなくてはなりません。

> 別名 正式名

別名と正式名の間には、1個以上の 1個以上の空白もしくはタブを置く必要があります。 別名には、正式名に変換したいエンコーディング名 を記述します。 別名に「`*`」を含んでいる場合は、その部分は 任意の文字列 (空文字列を含む) に一致します。

[設定例]

>     *.ISO_8859-1 ISO-8859-1
>     *.ISO_8859-2 ISO-8859-2
>     *.SJIS Shift_JIS
>     ko_KR.EUC EUC-KR
>     *.GB2312 GB2312
>     ja EUC-JP

別名がファイル内の複数の行にマッチする場合は、ファイルの先頭に最も 近い行が選ばれます。 また、別名がどの行にもマッチしなければ、そのエンコーディング名を そのまま正式名として採用します。

## 言語別名定義ファイル

idnkitバージョン2から、「言語別名定義ファイル」というファイルが 設けられました。 このファイルには、言語の名称について「別名」から「正式名」への 変換規則を定義します。

言語別名定義ファイルのパスは`SYSCONFDIR` ディレクトリの下の`idnlang.conf`になります。 (`SYSCONFDIR`は、idnkitをインストールする際に `configure`の --prefixオプションや --sysconfdirオプション で決定されます。)

idnkitライブラリは、次の箇所で言語名を取得します。

- 設定ファイルの`language`エントリの値
- 設定ファイルの`language-local`エントリの値
- 実行時、ロケール設定をもとに決定した「現在の言語」
- 高レベルAPIの`idn_setlanguage()`関数で指定した言語名
- resconfモジュールの`idn_resconf_setlanguage()`関数 で指定した言語名

idnkitライブラリ側で、取得した言語名を別名から正式名へ暗黙的に変換 します。 設定ファイルに記述する際は別名定義ファイルに頼ることなく、 ISO639言語コード を直接指定することをお薦めします。 しかしながら、ロケール情報から「現在の言語」を取得する場面では、 `setlocale()`の実装によってはISO639言語コードとは異なる ものしか取得できないことがあります。 そのような場合は、言語別名定義ファイルを用意する必要があります。 (言語別名定義ファイルは、idnkitをソースコードからインストールしても、 標準の定義ファイルやサンプルはインストールされません。)

別名定義ファイルは単純なテキストファイルです。 「`#`」で始まる行および空行は、無視されます。 それ以外の行は、次のような形式でなくてはなりません。

> 別名 正式名

別名と正式名の間には、1個以上の空白もしくは タブを置く必要があります。 別名には、正式名に変換したい言語名を記述します。 通常、正式名にはISO639言語コードを指定します。 ただし、ISO639-1コード (2文字コード) とISO639-2コード (3文字コード) の両方が定義されている言語では、ISO639-1コード (2文字コード) を指定 して下さい。 idnkitライブラリでは暗黙的に3文字コードから2文字コードへの変換を していますが、別名による変換が行われた場合は暗黙的な変換は省略する ようになっているためです。

なお、「エンコーディング別名定義ファイル」と異なり、別名 中の「`*`」は、特別な意味を持ちません。

[設定例]

>     Chinese zh
>     English en
>     French fr
>     German de
>     Japanese ja

別名がファイル内の複数の行にマッチする場合は、ファイルの先頭に最も 近い行が選ばれます。 別名がどの行にもマッチしなければ、前述のようにISO639-2コード (3文字コード) からISO639-1コード (2文字コード) への変換が暗黙的に 試みられます。 この暗黙の変換も行われなかったときは、その言語名をそのまま正式名と します。

## マップファイル

マップファイルは、 `language-local`エントリおよび `tld-local`エントリ向けに、 文字のマッピング規則を定義したファイルです。 マップ元として文字1個、マップ先として0文字以上の文字の並びを指定 できます。 前後の文字でマッピング規則を変えるような、文脈に依存したマッピングは できません。

マップファイルは単純なテキストファイルで、一行に一つのマッピング 規則を書くようになっています。マッピング規則は、次の書式で記述します。 「`#`」で始まる行および空行は、無視されます。

> マップ元のコードポイント; マップ先のコードポイント列;

マップ元のコードポイントには、マップ元の文字の Unicodeコードポイントを16進数で記述します。 マップ先のコードポイント列には、マップ先の各文字の Unicodeコードポイント値を16進数で記述します。 頭に「`U+`」を付けても構いません (例: `U+3002`)。 先頭の文字から順番に1個以上の空白もしくはタブで区切って並べていきます。 マップ先が空の場合、マップ元のコードポイントはマッピングの実行によって 削除されます。

[設定例]

>     # "A" を "a" にマップ
>     0041; 0061;
>     # "#" は何にもマップしない
>     0023; ;
>     # "@" を "at" にマップ
>     0040; 0061 0074;

## セットファイル

idnkitバージョン2から、「ローカルチェック」という機能が追加されました。 これは各レジストリが定めている、国際化ドメイン名として登録可能な文字 の範囲内でドメイン名が表現されているか否かをチェックするための機能です。

ただしドメイン名に対する通常のエンコード/デコード処理では、ローカルチェック は行われません。 idnconv2, idncmp, idncheckコマンドでは、`-localcheck`オプション で登録可能な文字の範囲を記述したファイルを指定すると、ローカルチェック を行うようになっています。 この「登録可能な文字の範囲を記述したファイル」を「セットファイル」と 呼びます。

セットファイルは単純なテキストファイルで、一行に一つのコードポイント、 もしくはコードポイントの範囲を記述します。書式は次の通りです。

> コードポイント
> 開始コードポイント..終了コードポイント

それぞれ、コードポイントにはUnicodeコードポイントを16進数で記述します。 頭に「`U+`」を付けても構いません (例: `U+3002`)。 「`#`」で始まる行および空行は、無視されます。

[設定例]

>     # "0".."9"
>     0030..0039
>     # "a".."z"
>     0061..007A
>     # "-"
>     002D

## 環境変数

idnkitライブラリに関連する環境変数には、以下のものがあります。

変数名 | 意味
--- | ---
`IDN_LOCAL_CODESET` | ローカルエンコーディングを明示的に設定するために使用します。 詳しくは 「ローカルエンコーディング」 をご覧下さい。
`LC_ALL` | ロケールの設定を行う環境変数です。 idnkit固有の環境変数ではありませんが、これらが定義 されていると、ローカルエンコーディングの判定に影響を与えます。 詳しくは 「ローカルエンコーディング」 をご覧下さい。
`LC_CTYPE`
`LANG`
`IDN_LOG_LEVEL` | ログ出力のレベルを設定します。設定できる値は0から5までの 数値で、大きな数字を設定すると、それ以下の数字の設定時に出力される ログも同時に出力されます。 0 - 致命的なエラーの場合のみログの表示を行います。(デフォルト) 1 - 一般的なエラーが起こった場合にログの表示を行います。 2 - 警告ログを表示します。 3 - 情報ログを表示します。 4 - トレースログを表示します。 5 - ダンプログを表示します。