NAME

perllocale - Perl のロケール操作 (国際化と地域化)

DESCRIPTION

まず最初に、ASCII、つまり "American Standard Code for Information Interchange" がありました; これは、英語アルファベットとドル建て 通貨を使うアメリカ人にとってはうまくいきました。 しかしこれは、ポンド貨(通貨の記号は ASCII にはありません)のような異なった 通貨を使っているかもしれないその他の英語話者に取ってすらあまりうまく いきませんでした; そして世界中の何百ものその他の言語にとっては絶望的に 無力でした。

これらの欠陥に対処するために、ロケールという概念が考案されました (正式には ISO C, XPG4, POSIX 1.c "locale system")。 そしてアプリケーションはロケール機構を使って書かれ、そして 書かれようとしていました。 アプリケーションにそういったユーザーの選択を考慮させるためのプロセスは、 国際化(internationalization)と呼ばれます(これはしばしば i18n と 省略されます); アプリケーションを特定の選択の集合に対応させることは 地域化(localizationl10n)として知られています。

Perl はロケールシステムに対応するように拡張されました。 これは一つのプラグマ、一つの関数呼び出し、いくつかの環境変数を使って、 アプリケーション毎に制御します。

残念ながら、ロケールにはかなりの数の設計上の(そしてしばしば実装上の)欠陥が あります。 Unicode (これに関する紹介については perlunitut を参照してください) は、この設計上の欠陥に部分的に対処するために 発明され、そして最近では、Unicode を基とした 一連の 「UTF-8 ロケール」があります。 これらは文字集合は Unicode で、UTF-8 でエンコードされています。 v5.20 から、Perl は UTF-8 ロケールに完全に対応しています; ただしソートと 文字列比較を除きます。 (これらのためには Unicode::Collate を使ってください。) Perl 古い非 UTF-8 ロケールも対応し続けています。

(Unicode はまた、POSIX ロケールシステムで利用可能なものよりも多くの種類の 情報を含む CLDR, "Common Locale Data Repository", http://cldr.unicode.org/ を作成します。 これを書いている時点で、この XML エンコードされたデータへのアクセスを提供する モジュールはありません。 しかし、ロケールの多くは POSIX のデータを展開したもののみを持ち、 http://unicode.org/Public/cldr/latest/ の UTF-8 ロケールとして 利用可能です。)

ロケールって何?

ロケールとは、世界中の様々なコミュニティがその世界をどのように カテゴリ化しているかについての様々な側面を記述したデータの集合です。 これらのカテゴリは以下の型に分解されます(一部は概略の説明もあります):

カテゴリ LC_NUMERIC: 数値フォーマット

これは人間に対する可読性のために数値をどのようにフォーマットするかを示します; たとえば小数点として使われる文字です。

カテゴリ LC_MONETARY: 通貨量のフォーマット
カテゴリ LC_TIME: 日付/時刻のフォーマット
カテゴリ LC_MESSAGES: エラーとそのほかのメッセージ

これは Perl 自身によって、$!$^E 経由でオペレーティングシステムの エラーメッセージにアクセスするためだけに使われています。

カテゴリ LC_COLLATE: 照合

これは比較とソートのための文字の順序を示します。 例えば、ラテンアルファベットなら、"b" は一般的に "a" の次です。

カテゴリ LC_CTYPE: 文字型

これは、例えば、文字が大文字かどうかを示します。

Other categories

一部のプラットフォームでは、長さの単位や紙のサイズといったものを扱う その他のカテゴリを持っています。 これらはどれも Perl が直接使うことはありませんが、Perl が相互作用する 外側の操作ではこれらを使うかもしれません。 後述する "Not within the scope of any "use locale" variant" を 参照してください。

Perl で使われるカテゴリに関するさらなる詳細については後述する "LOCALE CATEGORIES" を参照してください。

全体として、これらのカテゴリは単一のプログラムが複数の異なった場所で 実行するようにカスタマイズするために役立ちます。 しかし欠陥があるので、読み進めてください。

ロケールの使う前の準備

Perl 自身は、特に要求されない限りロケールを使いません (しかし再び、Perl は これらを使うコードと相互作用するかもしれません)。 たとえそのような要求があっても、正しく動作するには 以下の すべて が真になっていなければなりません:

Perl アプリケーションをあなたの使うデータを特定のロケールで処理したり するようにしたいのであれば、そのアプリケーションコードはプラグマ use locale を適切な場所に、そして以下に挙げる項目の 少なくとも一つ が真でなければなりません。

  1. あなた自身でやるにしろ、あなたの使うシステムの管理者がするにしろ、 アプリケーションの実行開始時には ロケールを決定する環境変数 ("ENVIRONMENT" を参照)が正しく設定されていなければなりません; または

  2. アプリケーションは、"The setlocale function" に記述されている メソッドを使う、自分用のロケールを設定しておかねばなりません

ロケールを使う

use locale プラグマ

デフォルトでは、Perl 自身は現在のロケールを無視します。 use locale プラグマは Perl に、幾つかの操作においてカレントのロケールを 使うよう指示します。 v5.16 から、このプラグマにはオプションの引数があります:

    use locale ':not_characters';

(v5.20 以降ではそれほど有用ではなくなりましたが)この引数により、ロケールと Unicode をよりよく混ぜられるようになり、(完全な記述は "Unicode and UTF-8" に ありますが)簡単に言うと、ロケール定義のうち文字に関する部分、つまり LC_CTYPELC_COLLATE カテゴリを使わないように指示します。 代わりにこれは(Unicode によって拡張された)ネイティブな文字集合を使います。 この引数を使うとき、外部文字集合をネイティブ / Unicode のものに変換するのは あなたの責任です(それが徐々に有名になっている UTF-8 ロケールならこれは すでに行われています)。 "Unicode and UTF-8" に記述されているように、これを行うための便利な方法が あります。

現在のロケールは、後述する setlocale() 関数によって実行時に設定されます。 プログラム実行の過程でこの関数がまだ呼び出されていないとき、現在の ロケールはプログラムの開始時に有効な "ENVIRONMENT" によって 決定されます。 有効な環境がない場合、現在のロケールはシステムデフォルトとして 設定されたものとなります。 POSIX システムでは、これは、おそらく "C" ロケールになりますが、かならず そうとは限りません。 Windows ではデフォルトはコンピュータの コントロールパネル->地域と言語 (または現在の等価物)経由で 設定されます。

ロケールによって影響を受ける処理は:

Not within the scope of any "use locale" variant

次のように、Perl の外側を元とする操作のみが影響を受けます:

Lingering effects of use locale

use locale 系のスコープ内で設定される一部の Perl 操作は、 スコープの外側でも影響を受けたままになります。 これには以下のようなものがあります:

Under "use locale ':not_characters';"
Under just plain "use locale";

no locale に出会うか、(use locale を囲む)ブロックの終端に 達するとデフォルトの動作に戻ります。 use localeuse locale ':not_characters' はネストしているかもしれず、 内側のスコープで有効だったものが内側のスコープの終了によって外側のスコープの 規則に差し戻されることに注意してください。

ロケール情報を使っている操作の結果である文字列は、ロケールが信頼できない 可能性があるかのように、汚染されていることに注意してください。 "SECURITY" を参照してください。

setlocale 関数

POSIX::setlocale() 関数を使って、実行時に好きな回数だけロケールを 切り替えることができます。

        # Import locale-handling tool set from POSIX module.
        # This example uses: setlocale -- the function call
        #                    LC_CTYPE -- explained below
        # (Showing the testing for success/failure of operations is
        # omitted in these examples to avoid distracting from the main
        # point)

        use POSIX qw(locale_h);
        use locale;
        my $old_locale;

        # query and save the old locale
        $old_locale = setlocale(LC_CTYPE);

        setlocale(LC_CTYPE, "fr_CA.ISO8859-1");
        # LC_CTYPE now in locale "French, Canada, codeset ISO 8859-1"

        setlocale(LC_CTYPE, "");
        # LC_CTYPE now reset to the default defined by the
        # LC_ALL/LC_CTYPE/LANG environment variables, or to the system
        # default.  See below for documentation.

        # restore the old locale
        setlocale(LC_CTYPE, $old_locale);

setlocale() の第一引数には カテゴリ を、第二引数には ロケール を与えます。 カテゴリはロケール特有の規則を適用したいデータ処理の状況を指示します。 カテゴリ名は "LOCALE CATEGORIES""ENVIRONMENT" に記述されています。 ロケールはカスタマイズを行うための、特定の言語の組み合わせ、国や地域、 コードセットに関する情報の集合の名前です。 ヒントとしてロケールの名前付けに注目してください: すべてのシステムが この例のようにロケールに名前を付けているわけではありません。

第二引数が省略されていて、さらにカテゴリが LC_ALL 以外の場合、この関数は カテゴリに対するカレントロケールの名前からなる文字列を返します。 この値を、後で行う setlocale() の呼び出しでの第二引数として 使うこともできます 一部のプラットフォームでは文字列は不明瞭で、 ほとんどの人にとってどのロケールのことか解読できるようなものではありません。

カテゴリが LC_ALL で、第二引数が与えられなかった場合には その結果は処理系に依存するものとなります。 ロケールの名前を連結したものか(セパレーターはこれまた処理系依存のもの)、 単一のロケール名となります。 詳しくは setlocale(3) man ページをあたってください。

第二引数が与えられていて、かつそれが正当なものであれば、カテゴリの ロケールが設定され、この関数は現在のロケール値を返します。 この値は次の setlocale() に呼び出しで使えます。 (一部の実装では、この返り値は第二引数を与えたときと異なる場合があります -- これは与えた引数のエイリアスと考えられます。)

例に示したように、第二引数が空文字列であった場合にはカテゴリの、 対応する環境変数によりデフォルト指定されるロケールが返されます。 一般的にはこの結果は、Perl が起動したときに強制的にデフォルトとして 設定された値です: アプリケーションが起動した後での環境変数の変更が 認識される/されないは、使用している C ライブラリに依存します。

Perl は use locale ':not_characters' のスコープの内側では現在の LC_CTYPE ロケールと LC_COLLATE ロケールを無視することに 注意してください。

何らかの理由 (例えばシステムが知らないロケールを設定しようとした) で set_locale() が失敗した場合、カテゴリに対するロケールは変更されず、関数は undef を返します。

カテゴリに対する詳細な情報は、setlocale(3) を参照してください。

ロケールを見つける

ロケールが使えるシステムであれば、使用可能なロケールがどういったもので あるかどうかを setlocale(3) で調べてみてください (SEE ALSO の章を探してください)。 それがダメだったら、以下のコマンドを試してみてください。

        locale -a

        nlsinfo

        ls /usr/lib/nls/loc

        ls /usr/lib/locale

        ls /usr/lib/nls

        ls /usr/share/locale

そして、そこに以下に挙げたものと似たものがあるかどうかを 確かめてください。

        en_US.ISO8859-1     de_DE.ISO8859-1     ru_RU.ISO8859-5
        en_US.iso88591      de_DE.iso88591      ru_RU.iso88595
        en_US               de_DE               ru_RU
        en                  de                  ru
        english             german              russian
        english.iso88591    german.iso88591     russian.iso88595
        english.roman8                          russian.koi8r

残念ながら、setlocale() を呼び出すインターフェースが既に 標準化されているのにも関らず、ロケールの名前や、それが設定される ディレクトリはまだなのです。 名前の基本形式は language_territory.codeset ですが、末尾の部分は 常にある訳ではありません。 languagecountry は通常は ISO 3166ISO 639 という 標準による、言語や国を二文字に略したものになります。 codeset の部分はしばしば文字集合 ISO 8859 の バリエーションとなります。 たとえば、"Western codeset" と呼ばれる ISO 8859-1 は西欧における エンコーディングとして用いることができます。 繰り返しますが、一つの標準の名前であってさえ、記述するには複数の方法が 存在するのです。 嘆かわしいことです。

"C" と "POSIX" という二つの特殊なロケールがあります。 現時点では、これら二つは同じロケールとなります。 その違いは主に、前者が C の標準により決められたものであるのに対して、 後者が POSIX の標準で決められているものであるという点にあります。 これらの規格が決めていることは、環境変数にあるロケール情報がない状態での プログラム起動時の デフォルトのロケール です (デフォルトの デフォルトロケールです)。 その言語は (アメリカ)英語であり、その文字集合は ASCII か、稀に ("DEC Multinational Character Set (DEC-MCS)" のような)その上位集合になります。 警告。 一部のベンダによって提供されている C ロケールは実際には C 標準が要求している ものに正確に一致していないかもしれません。 注意してください。

注意:すべてのシステムが "POSIX" ロケールを持っているわけでは ありません(すべてのシステムが POSIX に準拠しているわけではありません)ので、 明示的にこのデフォルトロケールを指定するのが必要なときには "C" を使います。

ロケールの問題

Perl を実行したときに以下のようなメッセージを見たことがあるかもしれません:

        perl: warning: Setting locale failed.
        perl: warning: Please check that your locale settings:
                LC_ALL = "En_US",
                LANG = (unset)
            are supported and installed on your system.
        perl: warning: Falling back to the standard locale ("C").

これは、あなたのロケールの設定が、LC_ALL が "En_US" であり LANG が 存在しているが値を持っていないということを意味します。 Perlはあなたを信じようとしたのですができなかったのです。 その代わりに、Perl はロケール設定をあきらめて、デフォルトである "C" ロケールに戻ったのです。 (Windows では、まずシステムのデフォルトロケールにフォールバックすることを 試みます。) これは通常はあなたのロケール設定が間違っているせいであり、聞いたことのない ロケールであったり、あるいはあなたのインストールに問題があったのだろう (例えば、一部のシステムファイルが壊れていたとか、なかったとか)と いうことです。 以下で述べるのは、この問題を手っ取り早く一時的に修復するものです。

壊れたロケールのテスト

Perl をソースからビルドする場合、Perl テストスイートファイル lib/locale.t がシステムのロケールのテストに使われます。 環境変数 PERL_DEBUG_FULL_TEST を 1 に設定すると、詳細な結果を出力します。 例えば、Linux では、以下のようにします:

 PERL_DEBUG_FULL_TEST=1 ./perl -T -Ilib lib/locale.t > locale.log 2>&1

その他の多くのテストに加えて、システムで発見された全てのロケールについて POSIX 標準に従っているかどうかをテストします。 エラーがあった場合、どのロケールが全てのテストに成功したかの出力の末尾辺りに、 どのテストがなぜ失敗したかの概要が含まれます。

一時的にロケールの問題を修正する

二つの(一時的な)対応策とは、ロケールに関する矛盾を無視するように するというものと、Perl をデフォルトロケール "C" で実行するというものです。

Perl 起動時の問題は、環境変数 PERL_BADLANG にゼロの値、たとえば "0" を設定することによって回避できます。 この方法は問題をカーペットの下に押し込むだけのことです: つまり、Perl が何か間違ったことを見つけたとしても Perl を 黙らせておくというものです。 もし後でロケールに依存した変な振る舞いがあったとしても 驚かないでください。

環境変数 LC_ALL に "C" を設定することにより、Perl はロケール "C" の下でも 実行することができます。 このやり方は PERL_BADLANG よりは多少まともなものですが、それでも LC_ALL (もしくは他のロケール変数)を設定するということは Perl 以外の プログラムにも影響を及ぼします。 特に、Perl の内側で実行される外部プログラムはこの変更に影響を 受けることになります。 新しい設定を恒久的なものにしたいというのであれば、あなたが実行する プログラム全てがこの変更に影響を受けることになります。 関係する環境変数の完全なリストは "ENVIRONMENT" を参照してください; また、Perl におけるそれらの効果については "USING LOCALES" を 参照してください。 他のプログラムに対する影響は簡単に避けられます。 たとえば、変数 LC_COLLATE はあなたの sort プログラム (もしくは「レコード」をアルファベット順に並べ替えるプログラム)に 影響を及ぼします。

これらの変数に対する変更を一時的に行ってテストすることができます; そして 新しい設定が助けになるものであればその設定をシェルのスタートアップ ファイルに追加するのです。 詳細はあなたの使っているシステムのドキュメントを調べてみてください。 Bourne シェルに似たシェル(sh, ksh, bash, zsh)であれば 以下のようになります:

        LC_ALL=en_US.ISO8859-1
        export LC_ALL

これは、コマンドが参照するロケールを "en_US.ISO8859-1" にしています。 Cシェルライクなもの(csh, tcsh)の場合には以下のようになります:

        setenv LC_ALL en_US.ISO8859-1

あるいは、"env" プログラムがあるなら、どのようなシェルでも、以下のように 書けます:

        env LC_ALL=en_US.ISO8859-1 perl ...

あなたがシェルについて良く知らないというのであれば、 あなたのおそばのヘルプデスク等に訊ねてみてください。

ロケールの問題を恒久的に修正する

時間はかかるけれども優れた修正方法は、あなたの環境の間違っている部分を 正しくするというものです。 システム全体での間違いはあなたの使っているシステムの、フレンドリーな 管理者の助けを必要とするでしょう。

まず最初にこのドキュメントの "Finding locales" を参照してください。 そこにはあなたの使うシステムで実際にサポートされているロケール、 そしてもっと重要なインストールされているロケールを見つけだす方法が 解説されています。 私たちが使ったエラーメッセージの例では、環境変数は重要度の高いものから 低いものへという順になっています。 したがって、LC_ALL を "En_US" に設定することは良くない選択であり、 これはエラーメッセージにも現れています。 まず最初にリストの最初にあるロケール設定を修正します。

次に、もしあなたがリストアップのコマンドを使って得たものが 正確に "En_US" のようなもの(接頭辞の一致は考慮せず、大小文字の違いは 考慮します)であれば、あなたが使っているロケール名に対応するものが システムに正しくインストールされていれば OK です。 この場合、"Permanently fixing your system's locale configuration" を 参照してください。

あなたのシステムのロケール設定を恒久的に修正する

これは以下のようなメッセージが出たけれども:

        perl: warning: Please check that your locale settings:
                LC_ALL = "En_US",
                LANG = (unset)
            are supported and installed on your system.

"En_US" が先に挙げたコマンドによってリスト中になかった場合です。 "en_US.ISO8859-1" のようなものを見たかも知れませんが、まったく 同一のものではなかったのでしょう。 この場合、コマンドで挙げられたもの一致するロケールで 実行してみてください。 ロケール名のマッチングルールは少々はっきりしないものです; それは、この分野に 関する標準が弱いものであるからです。 一般的なルールについては "Finding locales" をもう一度見てください。

システムのロケール設定を修正する

システム管理者にコンタクトをとって、あなたの得たエラーメッセージそのままを レポートして、今ここまで読んできたことを説明してください。 システム管理者はシステムのロケール設定についてどこがどう間違っているかを 理解できるはずです。 標準化がなされていないので、コマンド名などに関して "Finding locales" の 章は残念ながら少々あやふやなものになっています。

localeconv 関数

POSIX::localeconv() 関数は、カレントの LC_NUMERICLC_MONETARY で 指定されるロケール依存の数値書式の情報を取り出します。 (ある特定のカテゴリのカレントロケールを知りたいだけなのなら、 POSIX::setlocale() を引数一つで使います--"The setlocale function" を 参照してください。)

        use POSIX qw(locale_h);

        # Get a reference to a hash of locale-dependent info
        $locale_values = localeconv();

        # Output sorted list of the values
        for (sort keys %$locale_values) {
            printf "%-20s = %s\n", $_, $locale_values->{$_}
        }

localeconv() は引数を取らず、戻り値としてハッシュに対する リファレンス を返します。 このハッシュのキーは decimal_pointthousands_sep のように 整形された変数名です。 格納されている値はそのキーに対応する値です。 ある実装が提供しているであろうすべてのカテゴリをリストアップしている 長いサンプルは "localeconv" in POSIX を参照してください; しかしながら、一部のものが多かったり少なかったするかもしれません。 ロケールを問い合わせるジョブの関数のように use locale する必要が ないことに注意してください; localeconv() は常にカレントのロケールを 監視しています。

以下の例は、コマンドラインで渡されたパラメーターをカレントのロケールにおける 正しい書式に書きなおすというものです。

    use POSIX qw(locale_h);

    # Get some of locale's numeric formatting parameters
    my ($thousands_sep, $grouping) =
            @{localeconv()}{'thousands_sep', 'grouping'};

    # Apply defaults if values are missing
    $thousands_sep = ',' unless $thousands_sep;

    # grouping と mon_grouping は小整数のパック済みリストになって
    # います; これはgrouping (thousand_seps と mon_thousand_seps
    # はグループを分けるものです)の数と金銭に関するものの指定を
    # 行っています。その整数の意味はこうです: 255はグルーピング
    # しないことを意味します; 1から254はカレントのグルーピングで
    # 使用する数値を意味します;。グルーピングは右から左へ(下位桁から
    # 上位桁)と適用されます。下の例では最初のグルーピング以外は
    # (それが何でも)使わないことによってこれを避けています。
    if ($grouping) {
        @grouping = unpack("C*", $grouping);
    } else {
        @grouping = (3);
    }

    # Format command line params for current locale
    for (@ARGV) {
        $_ = int;    # Chop non-integer part
        1 while
        s/(\d)(\d{$grouping[0]}($|$thousands_sep))/$1$thousands_sep$2/;
        print "$_";
    }
    print "\n";

I18N::Langinfo

ロケール依存の情報を問い合わせるその他のインターフェースとしては I18N::Langinfo::langinfo() 関数があり、少なくとも Unix 風のシステムと VMS で利用可能です。

以下の例は langinfo() 関数自身と、langinfo() の引数として使う 3 つの 定数をインポートします: 1 つは現在のロケールでの週の最初の日の省略形 (番号は日曜日=1として振られています)、後の 2 つははい/いいえの質問に 対しての肯定および否定を現在のロケールで表すものです。

    use I18N::Langinfo qw(langinfo ABDAY_1 YESSTR NOSTR);

    my ($abday_1, $yesstr, $nostr)
                = map { langinfo } qw(ABDAY_1 YESSTR NOSTR);

    print "$abday_1? [$yesstr/$nostr] ";

言い換えると、"C" (または English) ロケールでは上記のものはおそらく 以下のようなものが表示されます:

    Sun? [yes/no]

さらなる情報については I18N::Langinfo を参照してください。

ロケールカテゴリ

以下のセクションでは、基本的なロケールカテゴリの説明をします。 先の例のように、複数の基本カテゴリを扱うことができる幾つかの 組み合わせカテゴリ(combination categories)があります。 この事に関する詳細は、"ENVIRONMENT" を参照してください。

カテゴリ LC_COLLATE: 照合

use locale のスコープの内側にある(そして use locale ':not_characters' の内側でない)とき、Perl はアプリケーションで 使用する文字の照合(順番)を決定するために環境変数 LC_COLLATE を 参照します(ラテンアルファベットでは "b" は "a" に続くものですが、 "á" や "å" はどこに置かれるのでしょう?)。 また、英語では "color" は "chocolate" よりも後になりますが、伝統的な スペイン語ではどうでしょう?

以下の照合は全て意味あるものであり、"use locale" をすれば直面することも あるでしょう。

        A B C D E a b c d e
        A a B b C c D d E e
        a A b B c C d D e E
        a b c d e A B C D E

以下のコード片はカレントのロケールにおける英数文字をそのロケールでの 順序で出力するものです。

        use locale;
        print +(sort grep /\w/, map { chr } 0..255), "\n";

これと、陽にロケールを無視するように指示したときの文字とを 比較してみてください。

        no locale;
        print +(sort grep /\w/, map { chr } 0..255), "\n";

この、マシン本来の照合(同じブロックの前のほうで use locale を していない方)は生のバイナリデータのソートに用いるもので、 最初の例で使ったロケール依存の照合は通常のテキストに使うのに便利です。

"USING LOCALES" で述べたように、cmpuse locale が有効なときには カレントの照合ロケールに従って比較を行いますが、 この結果が等しいと出た場合には文字毎の比較に逆戻りします。 この逆戻りが嫌ならば、POSIX::strcoll() を使うことができます。

        use POSIX qw(strcoll);
        $equal_in_locale =
            !strcoll("space and case ignored", "SpaceAndCaseIgnored");

$equal_in_locale は照合ロケールが空白キャラクタを完全に無視し、 大小文字の区別を無視するような辞書に似た順序付けを指定している場合には 真になるでしょう。

Perl は LC_COLLATE に関して単一バイトロケールのみに対応しています。 つまり、UTF-8 ロケールが単にマシンネイティブな順序を 提供するだろうということです。 Unicode 照合アルゴリズムに関する完全な実装については Unicode::Collate を 使ってください。

「ロケールにおける等価性」の検査を他のものに対して行いたい(一つの) 文字列があるときにあなたは、POSIX::strxfrm()eq と一緒に 使うことによって多少の効率アップができると考えるかもしれません:

        use POSIX qw(strxfrm);
        $xfrm_string = strxfrm("Mixed-case string");
        print "locale collation ignores spaces\n"
            if $xfrm_string eq strxfrm("Mixed-casestring");
        print "locale collation ignores hyphens\n"
            if $xfrm_string eq strxfrm("Mixedcase string");
        print "locale collation ignores case\n"
            if $xfrm_string eq strxfrm("mixed-case string");

strxfrm() は文字列を引数にとり、それを同様の変換を加えられた文字列との 文字毎の比較に使えるような文字列に変換します。 「フードの中では」、ロケールに影響された Perl の比較演算子は strxfrm() を両オペランドのために呼び出して、その後で文字毎の比較を、 変換された文字列に対して行います。 strxfrm() を陽に呼び出すこととロケールに影響されない比較を行うことで、 上記の例は変換をセーブするようになります。 実際にはこれは何もセーブしません: Perl の魔法("Magic Variables" in perlguts を 参照)は、比較の際に必要であれば最初に変換された文字列を生成し、それからそれが 再び必要になるまで取っておくのです。 cmp を使って書き直したサンプルは可能な限り早く実行されます。 また、文字列に埋め込まれているヌル文字にも対処します; strxfrm() を 直接呼び出した場合、ナルは終端子としてみなされます。 そして、変換後の文字列がシステムを越えて使えるようなものであると 期待してはいけません; また、あるオペレーティングシステムのバージョンで 作ったものが次の バージョンでも同様であるということも期待してはいけません。 一言でいうと、strxfrm() を直接呼び出してはいけない、ということです: Perl に呼び出しをさせましょう。

注意: 幾つかのサンプルでは、必要がないので use locale がありません: strcoll()strxfrm() は、常に LC_COLLATE ロケールに従う、システムが 供給する標準の libc 関数を使う POSIX 関数です。

カテゴリ LC_CTYPE: 文字タイプ

use locale のスコープにある(そして use locale ':not_characters' の 内側でない)とき、Perl は LC_CTYPE ロケールの設定に従います。 これは、アプリケーションの英字、数字、句読点 など かどうかの扱いを 制御します。 これは、英数字 -- つまり、英字、数字、およびプラットフォームのネイティブな 下線を含みます --に関わる正規表現のメタ表記 \w に影響します。 (正規表現に関するさらなる情報については perlre を参照してください)。 LC_CTYPE のおかげで、ロケール設定に依存した "æ", "ð", "ß", "ø" のような文字が \w 文字として認識できるのです。 これはまた \s, \D および [[:graph:]] のような POSIX 文字クラスにも 影響を与えます。 (これら全てに関するさらなる情報については perlrecharclass を 参照してください。)

LC_CTYPE ロケールはまた、小文字と大文字との間の相互変換に使われる マッピングを提供します。 これは大文字小文字変換関数 fc(), lc(), lcfirst(), uc(), ucfirst() とダブルクォートで囲まれた文字列の中での \F, \l, \L, \u, <\U> による大文字小文字変換、そして s/// による置換、 i 修飾子を使った(大小文字を無視する)正規表現パターンマッチングに 影響を及ぼします。

さらに、LC_CTYPE は (廃止予定の) POSIX のキャラクタクラステスト関数 POSIX::isalpha(), POSIX::islower() などにも影響を及ぼします。 たとえば、"C" ロケールを 7 ビットのスカンジナビアのものにしたとすると、 多分あなたは驚くことになるでしょうが、"|" が POSIX::ispunct() クラスから POSIX::isalpha() クラスに移動するのです。 残念ながら、これは正規表現に関して大きな問題を起こします。 "|" は、たとえ \w にマッチングしても代替を意味したままです。

v5.20 から、Perl は LC_CTYPE に関して LC_CTYPE に対応していますが、 それ以外では Perl は ISO 8859 シリーズのような単一バイトロケールのみに 対応しています。 これはつまり、アジア言語のようなワイド文字ロケールには 対応していないということです。 UTF-8 ロケール対応は実際には POSIX ロケールの上位集合です; ロケールの影響を一切受けない完全な Unicode の振る舞いだからです (例外は汚染です; "SECURITY" を参照してください)。 POSIX ロケールは、例え UTF-8 のものでも、 文字の大文字小文字の変更が複数文字に拡張されるような、 Unicode のいくつかの概念が欠けています。 UTF-8 ロケールでは、Perl は拡張を提供します。 UTF-8 ロケールについて、v5.20 より前の Perl では、 一部のプラットフォームではある種の制限付きの ISO 8859-1 として扱い、 その他のプラットフォームではより "C" ロケールに近いものになります。 リリース v5.16 と v5.18 では、use locale 'not_characters が これの回避策として使われていました ("Unicode and UTF-8" を 参照してください)。

現在のロケールによって影響を受けないものもいくつかあることに注意してください。 例えば \n のような、特定の文字のためのエスケープシーケンス全ては、常に プラットフォームにネイティブなものを意味します。 つまり、例えば、正規表現中の \N (改行以外の全ての文字) はプラットフォームの 文字集合に対して動作します。

注意: 壊れた、あるいは悪意のある LC_CTYPE ロケールの定義は、 不適切な文字を英数字であるとみなしてしまう可能性があります。 (アクセント記号のない)文字や数字の厳密なマッチング、例えばコマンド文字列の ロケールを気にするアプリケーションは /a 正規表現修飾子付きで \w を使うべきです。 "SECURITY" を参照してください。

カテゴリ LC_NUMERIC: 数値形式

適切な POSIX::setlocale() 呼び出しの後、use locale 系の一つのスコープの 内側では、Perl は LC_NUMERIC ロケール情報を参照します; これは アプリケーションが数値をどのように整形するかということを制御するものです。 大部分の実装では、小数点を表わす文字を "." から "," へと 変更するだけの効果しかありません。 この関数は三桁毎の区切りなどについては考慮しません。 (この事について心配があるのなら "The localeconv function" を 参照してください。)

 use POSIX qw(strtod setlocale LC_NUMERIC);
 use locale;

 setlocale LC_NUMERIC, "";

 $n = 5/2;   # Assign numeric 2.5 to $n

 $a = " $n"; # Locale-dependent conversion to string

 print "half five is $n\n";       # Locale-dependent output

 printf "half five is %g\n", $n;  # Locale-dependent output

 print "DECIMAL POINT IS COMMA\n"
          if $n == (strtod("2,5"))[0]; # Locale-dependent conversion

I18N::LanginfoRADIXCHAR も参照してください。

カテゴリ LC_MONETARY: 金銭の書式

標準 C では LC_MONETARY カテゴリを定義していますが、その内容に 影響される関数はありません。 (規格委員会の経験によって、それらはワーキンググループがこの問題を 蹴り出すことに決めたことを認識したのでしょう。) 結果として、Perl は基本的にこれに注意を払いません。 もし本当に LC_MONETARY を使いたければ、自分でその内容を 問い合わせることができます("The localeconv function" を参照してください); そして返ってきた情報をアプリケーションの通貨量の整形に使います。 しかし、この情報を取得することはできるでしょうが、大量かつ複雑で、 要求に対して本当にあったものではないでしょう: 金銭に関する書式は手に おえない代物なのです。

I18N::LanginfoCRNCYSTR も参照してください。

LC_TIME

人が読みやすい、整形された日付/時刻文字列を作り出す POSIX::strftime() によって生成された出力はカレントの LC_TIME ロケールに 影響を受けます。 したがって、フランスのロケールでは、%B 書式指定子(省略のない月の名前)を 一年の最初の月に対して使ったときの結果は、"janvier" となります。 以下の例は、カレントロケールにおける長い月名のリストを得るものです。

        use POSIX qw(strftime);
        for (0..11) {
            $long_month_name[$_] =
                strftime("%B", 0, 0, 0, 1, $_, 96);
        }

注意: use locale はこの例では必要ではありません: strftime() は POSIX 関数で、標準のシステムが供給する libc 関数を使い、常に カレントの LC_TIME ロケールを参照します。

I18N::LanginfoABDAY_1..ABDAY_7, DAY_1..DAY_7ABMON_1..ABMON_12ABMON_1..ABMON_12 も参照してください。

その他のカテゴリ

残ったロケールカテゴリは現在のところ Perl 自身では使われません。 しかし再び、標準の Perl 配布 パッケージにはない拡張モジュールや OS やそのユーティリティなど、Perl が 相互作用するものがこれらを使うかも知れないことに注意してください。 $! の文字列値と、外部のユーティリティから与えられたエラーメッセージは LC_MESSAGES で変更されているかもしれないことに特に注意してください。 移植性のあるエラーコードがほしい場合は、%! を使ってください。 Errno を参照してください。

セキュリティ

Perl のセキュリティに関する事項の主な議論は perlsec にありますが、 Perl のロケールの扱いに関する議論はそれがあなたのロケール依存の セキュリティ事項に対して注意していなければ不完全です。 ロケールは(特に特権のないユーザーが自分のロケールを構築するのを許すような システムでは)信用できないものなのです。 悪意のある(もしくは単に壊れた)ロケールはロケールを使うアプリケーションを 予期できない結果にする可能性があります。 以下に幾つかの可能性を挙げます。

このような危険は、ロケールシステムに特有のものではありません: 意地の悪い 変更を通して同じような攻撃を受けるようなアプリケーション環境の あらゆる状況が対象となります。 同様に、これは Perl に固有なものでもありません: 環境を考慮するような プログラムを書くことのできるあらゆるプログラミング言語で同様の危険性が あるのです。

perlは例示したようなすべての可能性からあなたを守ることはできません-- あなた自身の用心に代り得るものはないのです--しかし、use locale が 有効であるとき、Perl は汚染チェック機構(perlsec を参照)を、ロケールに 依存した結果であり、信用できないかもしれない文字列に注意するために 使用します。 以下は、ロケールにより影響を受ける可能性のある演算子や関数の汚染される 振る舞いのまとめです。

三つの例を使って、ロケール依存の汚染を説明します。 最初のプログラムはそのロケールを無視して、実行されません: 汚染検査が 有効であるときには、コマンドラインから直接とった値を出力ファイル名として 使うことはできません。

        #/usr/local/bin/perl -T
        # Run with taint checking

        # Command line sanity check omitted...
        $tainted_output_file = shift;

        open(F, ">$tainted_output_file")
            or warn "Open of $tainted_output_file failed: $!\n";

このプログラムは、汚染された値を正規表現を通して 「洗浄」(laundering)することにより実行できるようにできます: 以下に挙げる二番目の例は--これもロケール情報を無視しています-- 実行されると、コマンドラインにある名前のファイルを可能であれば作成します。

        #/usr/local/bin/perl -T

        $tainted_output_file = shift;
        $tainted_output_file =~ m%[\w/]+%;
        $untainted_output_file = $&;

        open(F, ">$untainted_output_file")
            or warn "Open of $untainted_output_file failed: $!\n";

これを、非常に良く似てはいますが、ロケールを使ったプログラムと 比較してみてください。

        #/usr/local/bin/perl -T

        $tainted_output_file = shift;
        use locale;
        $tainted_output_file =~ m%[\w/]+%;
        $localized_output_file = $&;

        open(F, ">$localized_output_file")
            or warn "Open of $localized_output_file failed: $!\n";

この三番目のプログラムは、$& が汚染されているので実行に失敗します; これは use locale が有効であるときの \w を含んだマッチングによる 結果です。

環境変数

PERL_SKIP_LOCALE_INIT

この環境変数は Perl v5.20 から利用可能で、これが真の値に評価される場合、 初期化のためのその他の環境変数を使わないように Perl に伝えます。 代わりに、Perl は現在のロケール設定を使います。 これは組み込み環境で特に有用です; "Using embedded Perl with POSIX locales" in perlembed を参照してください。

PERL_BADLANG

Perl が起動時にロケールの設定に失敗した場合に警告を出すのを抑制できる 文字列です。 オペレーティングシステムのロケールサポートがなんらかの理由でなかったり、 壊れていたりするとき、あるいは環境変数に設定したロケールの名前を 間違えていた場合に発生します。 もしこの変数が存在していないとか、あるいはその値が評価すると0に ならないようなもの、つまり "0" や "" でない場合に、Perl はロケールの設定に 失敗するとメッセージを出力します。

注意: PERL_BADLANG は警告メッセージを出さないようにするだけです。 このメッセージはあなたの使うシステムのロケールサポートになにかの問題が あるということを伝えるものですから、あなたは問題が何なのかを 確かめるべきでしょう。

以下の環境変数は Perl に特有のものではなく、アプリケーションのデータの 扱いを制御するための標準的な(ISO C, XPG4, POSIX 1.c) setlocale() メソッドの 一部分です。 Windows は POSIX ではありませんが、Perl はそれでもここで記したとおりに 動作するように用意します。 環境変数で与えられたロケールが正当ではない場合、 優先順位で次のものを使おうとします。 Windows では、正当なものがない場合、システムデフォルトロケールを 使おうとします。 全てに失敗した場合、"C" ロケールが使われます。 これすらも動作しない場合、何かがひどく壊れていますが、 Perl は何かロケール設定があるものとして前に進もうとします。

LC_ALL

LC_ALL は「全て上書き」ロケール環境変数です。 もしこの環境変数が設定されていると、他のすべての環境変数を上書きします。

LANGUAGE

注意: LANGUAGE は GNU の拡張で、GNU libc を使っているときにのみ 効果があります。 Linux を使ったときなどがこれに該当します。 あなたが「商用の」Unix を使っているのであれば GNU libc は 使われていないでしょうし、LANGUAGE は無視することができます。

LANGUAGE を使った場合には、コマンドからの情報、警告、エラーといった メッセージの言語に影響を及ぼします(言い換えると LC_MESSAGES と 似ています)が、LC_ALL よりも優先順位は下です。 さらに、これは単一の値ではなくて言語(ロケールではありません)の、 ":" で連結された「パス」になっています。 より詳しい情報は GNU gettext ライブラリのドキュメントを参照してください。

LC_CTYPE.

LC_ALL がないときに、LC_CTYPE は文字タイプのロケールを選択します。 LC_ALLLC_CTYPE の両方ともない場合、LANG が文字タイプの ロケールを選択します。

LC_COLLATE

LC_ALL がないときに、LC_COLLATE は照合(ソート)ロケールを選択します。 LC_ALLLC_COLLATE の両方ともない場合、LANG が 照合ロケールを選択します。

LC_MONETARY

LC_ALL がないときに、LC_MONETARY は通貨形式ロケールを選択します。 LC_ALLLC_MONETARY の両方ともない場合、 LANG が通貨形式ロケールを選択します。

LC_NUMERIC

LC_ALL がないときに、LC_NUMERIC は数値表記のロケールを選択します。 LC_ALLLC_NUMERIC の両方ともない場合、LANG が数値表記を 選択します。

LC_TIME

LC_ALL がないときに、LC_TIME は日付・時刻表記のロケールを選択します。 LC_ALLLC_TIME の両方ともない場合、LANG が日付・時刻表記の ロケールを選択します。

LANG

LANG は「包括的」なロケール環境変数です。 これに値が設定されている場合、LC_ALL も、各カテゴリの LC_foo も 設定されていないときの最後の参照場所として使われます。

LC_NUMERIC は数値出力を制御します:

   use locale;
   use POSIX qw(locale_h); # Imports setlocale() and the LC_ constants.
   setlocale(LC_NUMERIC, "fr_FR") or die "Pardon";
   printf "%g\n", 1.23; # If the "fr_FR" succeeded, probably shows 1,23.

そして文字列が POSIX::strtod() によってどのように数値としてパースされるかも 制御します:

   use locale;
   use POSIX qw(locale_h strtod);
   setlocale(LC_NUMERIC, "de_DE") or die "Entschuldigung";
   my $x = strtod("2,34") + 5;
   print $x, "\n"; # Probably shows 7,34.

注意

文字列 evalLC_NUMERIC

文字列 eval はその式を標準の Perl としてパースします。 従って小数点がピリオドであることを想定します。 もしこれがカンマであるように LC_NUMERIC が設定されると、パースは (おそらく暗黙の内に)混乱します。

 use locale;
 use POSIX qw(locale_h);
 setlocale(LC_NUMERIC, "fr_FR") or die "Pardon";
 my $a = 1.2;
 print eval "$a + 1.5";
 print "\n";

これは 13,5 を表示します。 これは、このロケールではカンマが小数点文字だからです。 従って eval はこれを次のように展開します:

 eval "1,2 + 1.5"

そして結果はおそらくあなたが想定したものではありません。 警告は出ません。 文字列 evaluse locale スコープ内で行うなら、 eval 行を以下のように変えるべきです:

 print eval "no locale; $a + 1.5";

これは 2.7 を表示します。

過去互換性

5.004 より前のバージョンの Perl では、ほとんど ロケール情報を無視して、 たとえプログラム環境が別のものを指示していたとしても常に "C" ロケール ("The setlocale function" を参照) が強制されているかのように 振る舞っていました。 デフォルトでは、Perl は今でもこのように動作するので、過去互換性があります。 Perl アプリケーションをロケール情報に注目するようにしたいのなら、 use locale プラグマ("The use locale pragma" を参照)あるいは、 あまりなさそうな上京ですが単に正規表現でそうしたいなら、/l 正規表現修飾子 ("Character set modifiers" in perlre 参照) を 使わなければなりません

5.002 から 5.003 の Perl は、使用可能である場合には LC_CTYPE の情報を 使っていました; つまり、\w はロケールの環境変数に従った文字を 理解していたのです。 問題は、C ライブラリがロケールをサポートしている場合には Perl がそれを 使ってしまい、ユーザーがこの機能を制御できないということでした。

I18N:Collate は古いもの

5.004 より前のバージョンの Perl では、ロケール毎の照合は I18N::Collate ライブラリモジュールを使うことで可能でした。 このモジュールは現在、やや時代遅れとなっていて、新しいアプリケーションでは 使用を避けるべきものです。 現在、LC_COLLATE 機能は Perl のコア言語に統合されました: スカラデータのロケール固有の比較は use locale を使うことで完全に 行なわれます; このため、I18N::Collate のスカラリファレンスを使って お手玉する必要はもはやないのです。

ソートの速度とメモリ使用に与える影響

ロケールによる比較とソートは通常、デフォルトのソートに比べ二倍から 四倍遅くなります。 また、メモリの使用量も増大します。 Perl のスカラ変数がロケールの照合規則を使ったなんらかの文字列比較や ソートの中で現れると、それによって以前より三倍から十五倍の時間を 要するようになります(実際のところの乗数は文字列の内容、オペレーティング システム、ロケールに依存します)。 この性能ダウンは、Perl によるものよりもオペレーティングシステムの ロケールシステムの実装によるものが顕著に現れます。

自由に利用可能なロケール定義

Unicode CLDR プロジェクトは多くのロケールの POSIX 部分を展開します; 以下で利用可能です

  http://unicode.org/Public/cldr/latest/

ここにロケール定義の大規模なコレクションがあります:

  http://std.dkuug.dk/i18n/WG15-collection/locales/

これがサポート無しのものであり、どんな目的にも適合するとは 主張していないものであることに注意すべきです。 あなたの使うシステムがロケール機能のインストールを許しているのであれば、 この場所で便利な定義を見つけることができるでしょうし、あるいは自分で ロケールを定義する基礎となるようなものを見つけられるかもしれません。

I18n と l10n

"Internationalization" (国際化)はその最初と最後の文字、そしてその間にある 文字数から i18n としばしば略されます。 (なぜ(英語では) internalin ... internaliti ... i18n が省略されがちか 推測できるかも知れません。) 同様のやり方で、"localization" もしばしば l10n と省略されます。

不完全な標準

標準 C や標準 POSIX に定義されている国際対応は、不完全で、扱いにくく、 粒度が大きすぎると酷評されます。 (ロケールは、単一のスレッドであるとか、ウィンドウグループといったものに対して 適用するのが便利であるときにもプロセス全体に適用されます)。 また、世界が等しく銀行家、バイク乗り、ゲーマーなどに分割できるのを知るとき、 標準化グループに似て、世界を国に分割しようとする傾向があります。

Unicode と UTF-8

Unicode 対応は Perl バージョン 5.6 から始まり、バージョン 5.8 以降でより 完全に実装されました。 perluniintro を参照してください。

Perl v5.20 から、UTF-8 ロケールが Perl で対応されました; ただし LC_COLLATE を除きます (代わりに Unicode::Collate を使ってください)。 Perl v5.16 または v5.18 を使っていてアップグレードできないなら、次のものが 使えます

    use locale ':not_characters';

この形式のプラグマが使われると、ロケールの文字以外の部分、たとえば LC_NUMERIC、のみが Perl によって使われます。 Perl は、あなたが操作する全ての文字を Unicode (実際にはプラットフォームに ネイティブな文字集合 (ASCII または EBCDIC) に加えて Unicode) に変換していると 仮定します。 ファイルのデータについては、これは以下のように指定することでも便利に行えます

    use open ':locale';

このプラグマは、ファイルからの全ての入力について環境変数で指定されている ロケール ("ENVIRONMENT" 参照) から Unicode への変換と、ファイルへの 全ての出力についてそのロケールへ逆変換を行います。 (open 参照)。 ファイルハンドル単位では、どちらも CPAN から利用可能である PerlIO::locale モジュールか Encode::Locale が代わりに使えます。 後者のモジュールは ARGV と環境変数の扱いを簡単にするメソッドも持ち、 個々の文字列で使えます。 最近多い状況として、使うロケールが UTF-8 だけであることが 分かっているなら、-C コマンドラインオプションが使えます。

この形式のプラグマは、本質的にロケールと Unicode の扱いをシームレスにします。 照合順序は Unicode の符号位置順です。 文字列の順序とソートが必要な場合は、古い形式のロケール操作よりも 多くの場合に遙かによい結果を得られる、Unicode::Collate 標準モジュールを 使うことを強く勧めます。

ここで記述されている全てのモジュールとスイッチは、 v5.20 からは単に use locale と書くだけで使えます; 入力が UTF-8 でなく、v5.16 より前の Perl を使うか、 あるいは、v5.16 と v5.18 で :not_characters 引数なしで locale プラグマを使ったとき、 理想とは遠い振る舞いになります。 v5.20 以上で UTF-8 ロケールのみを使う場合は、この章の残りの内容は 適用されません。

マルチバイトロケールと単一バイトロケールの二つの場合があります まずマルチバイトの場合:

Perl が対応していると言える唯一のマルチバイト(ワイド文字)ロケールは UTF-8 です。 これは、実装の難しさ、高品質な UTF-8 ロケールは世界中のあらゆる 分野で使われているという事実、他のロケールと変換するために Encode モジュールを使えるというのが理由です。 従って、Big5 や Shift JIS のようなこれらのロケールの一つを使っている場合、 これらのどれか一つを行う必要があります。 UTF-8 ロケールに関しては、完全な UTF-8 ロケール対応のない (v5.20 より前の) Perl でも十分にうまく動くかもしれません (C ライブラリの実装に依存します); 単にこれらと Perl はマルチバイトになる文字を同じ方法で保管するからです。 しかし、ほとんどではなかったとしても時々、C ライブラリ実装は、LC_CTYPE の 下では Latin-1 の範囲の上半分 (128 - 255) の文字を正しく扱えません。 ロケールの下である文字が特定の型を持っているかどうかを見るために、Perl は isalnum() のような関数を使います。 使っている C ライブラリは UTF-8 ロケールに対してこれらの関数が動作せず、 代わりに iswalnum() のような新しいワイド文字ライブラリ関数のみが 動作するかもしれません。 しかし、これらは単一バイトロケールのように扱われ、後述するような 制限があります。

単一バイトロケールでは、Perl は一般的にシングルバイトに合う符号位置の ロケールルールを使い、それが出来ないときは Unicode のルールを使う方針を とります (しかしこれは一様には適用されません; この節の末尾の注意を 参照してください)。 これは UTF-8 でないロケールでの多くの問題を防ぎます。 ロケールがギリシャ語の ISO8859-7 であると仮定します。 0xD7 の文字は capital Chi です。 しかし Latin1 である ISO8859-1 ロケールでは、これは乗算記号です。 POSIX 正規表現文字クラス [[:alpha:]] はマジカルに、ギリシャ語ロケールでは 0xD7 にマッチングするけれども Latin ロケールではマッチングしません。

しかし、これを分解してみます。 \p{Alpha} のような一部の Perl の構文は Unicode のみです。 これらは 0xD7 は常に Unicode での意味 (あるいは EBCDIC プラットフォームでの 等価物) を持つと仮定します。 Latin1 は Unicode の部分集合でであり、0xD7 は Latin1 と Unicode の両方で 乗算記号なので、ロケールに関わらず \p{Alpha} はマッチングしません。 同じような問題は \N{...} で起こります。 v5.20 以前では、従って生の use locale\p{}\N{} を使うのは 悪い考えです -- ロケールが ISO8859-1 であることを 保証できないかぎり です。 代わりに POSIX 文字クラスを使ってください。

この手法のもう一つの問題は、1 バイト/複数バイトの境界をまたぐ操作は 未定義なので、許可されていません。 (この境界は符号位置 255/256 の間です。) 例えば LATIN CAPITAL LETTER Y WITH DIAERESIS (U+0178) の小文字化は LATIN SMALL LETTER Y WITH DIAERESIS (U+00FF) を返すべきです。 しかし、例えばギリシャ語ロケールでは、0xFF に文字はなく、Perl には 0xFF の 文字が実際に何を表現しているかを知る方法はありません。 従ってこの操作は許可されません。 このモードでは、U+0178 の小文字は自分自身です。

同じ問題は、(-C コマンドラインオプションか PERL_UNICODE 環境変数を 使って (perlrun を参照してください)) ISO-8859-1 でも UTF-8 でもない ロケールの標準ファイルハンドル、デフォルト open() 層、@ARGV の 自動 UTF-8 化を有効にしている場合にも起こります。 これらは UTF-8 として読み込まれ、普通は暗黙に Unicode として 解釈されますが、ロケールの存在によって、代わりにそのロケールとして 解釈されます。 例えば、Unicode 入力での符号位置 0xD7 は、乗算記号を意味するべきですが、 ギリシャ語ロケールでは Perl はそのようには解釈しません。 全てのロケールが常に ISO-8859-1 か、不十分な C ライブラリを持っていないなら UTF-8 ロケール、のどちらかだけであることが 確実なら 問題ではありません。

もう一つの問題は、この手法は同じ文字を意味する二つの符号位置を 持つことになることです。 従ってギリシャ語ロケールでは、U+03A7 と U+00D7 はどちらも GREEK CAPITAL LETTER CHI です。

ベンダロケールはバグ持ちで悪名高く、これは Perl が制御できないコードと 相互作用するので、Perl がロケール操作コードをテストするのは困難です; 従って Perl のロケール操作コードは同様にバグ持ちかもしれません。 (しかし、Unicode が提供しているロケールはより良いはずで、問題を修正するための フィードバック機構があります。 "Freely available locale definitions" を参照してください。)

Perl v5.16 を使っているなら、(非文字部にベンダバグがない限り) locale プラグマに :not_characters 引数を使えば前述した問題はなくなります。 v5.16 がなく、動作するロケールが ある なら、それを使うことは、既に言及した コツを心に留めている限りは、ある種の特定の用途には価値があるかもしれません。 例えば、ロケール下での照合が動作するなら、 Unicode::Collate 下でのロケールよりも高速に実行されます; そしてローカルな通貨記号、月や週の名前のようなものへのアクセスを得ます。 (しかし要点を銘記するために、v5.16 では、プラグマの :not_characters 形式を 使うことでロケールの弱点なしにこれにアクセスできます。)

注意、1 バイトに収まる符号位置に対してロケールの規則を使うポリシーと、 収まらないものに対する Unicode の規則を使うポリシーについては、一律には 適用されません。 v5.12 より前では、これは場当たり的でした; v5.12 では、大かっこ文字クラス以外の 正規表現マッチングではかなり一貫して適用されました; v5.14 では全ての 正規表現マッチングに拡大されました; v5.16 では "\L"uc() のような 大文字小文字操作に拡大されました。 照合については、全てのリリースについて、システムの strxfrm() 関数が 呼び出され、その結果が結果となります。

バグ

壊れているシステム

幾つかのオペレーティングシステムにおける環境でのロケールサポートは、 おかしなもので、Perl がそれに対処したり使ったりできないようなものです。 そういった不完全なものは、use locale が有効になったときに Perl を 不可思議なハングアップに導いたり、コアダンプをさせたりします。 このようなシステムに直面した場合、詳しい状況を <perlbug@perl.org> に レポートし、そして使用しているシステムのベンダーに連絡してください: 問題の幾つかに対するバグフィックスがされているかもしれません。 そういったバグ修正は、オペレーティングシステムのアップグレードと 呼ばれることがあります。 Perl のソースがあるなら、前述の "Testing for broken locales" で 記述されているテストの出力を perlbug のメールに含めてください。

SEE ALSO

I18N::Langinfo, perluniintro, perlunicode, open, "isalnum" in POSIX, "isalpha" in POSIX, "isdigit" in POSIX, "isgraph" in POSIX, "islower" in POSIX, "isprint" in POSIX, "ispunct" in POSIX, "isspace" in POSIX, "isupper" in POSIX, "isxdigit" in POSIX, "localeconv" in POSIX, "setlocale" in POSIX, "strcoll" in POSIX, "strftime" in POSIX, "strtod" in POSIX, "strxfrm" in POSIX.

Perl が C プログラムに組み込まれているときに特に考慮することについては "Using embedded Perl with POSIX locales" in perlembed を参照してください。

HISTORY

Jarkko Hietaniemi の原文書 perli18n.pod は perl5-porters の助けの元、 Dominic Dunlop によって大きく変更されました。 表現に関しては Tom Christiansen が少し作業をし、Perl 5 porters によって 更新されました。