# 正規化および地域化

Zend_Locale_Format は、Zend_Locale が内部で使用しているコンポーネントです。 ロケール対応のクラスは、Zend_Locale_Format を用いて数値や日付の正規化および地域化を行います。 正規化とは、さまざまな形式で表されるデータ (日付など) を取り込んで解析し、 標準化された構造化表現 (year、month、day の各要素からなる配列など) に変換することです。

まったく同じ文字列からなる数値や日付でも、 異なる習慣や規約を使用している人が見ると異なる意味にとられることがあります。 数値や日付を、あいまいさをなくして正確に解釈するには、 これらの文字列を正規化し、標準化されたデータ構造に変換する必要があります。 したがって、Zend_Locale_Format のすべてのメソッドは、 入力データを処理するためにロケール情報を必要とします。

デフォルトの "root" ロケール

ロケールを省略した場合は、正規化や地域化の際に 標準の "root" ロケールを使用します。 これは予期せぬ動作を引き起こす可能性があります。 さまざまなロケールの入力を扱ったり、特定のロケールで出力したい場合などに注意が必要です。

## 数値の正規化: getNumber($input, Array $options)

標準の 十進法 (例: "3.14") とは異なる 記数法 には、さまざまなものがあります。 数値を正規化するには getNumber() 関数を使用します。これは、標準の十進法を返します。 このマニュアルにおける数値関連の説明はすべて、特にことわりがない限り アラビア数字 (0,1,2,3,4,5,6,7,8,9) を想定したものです。オプションの配列で 'locale' を指定し、桁区切り文字および小数点を定義できます。 また、配列に 'precision' を指定すると、 あふれた桁を結果から取り除きます。

数値の正規化

    $locale = new Zend_Locale('de_AT');
    $number = Zend_Locale_Format::getNumber('13.524,678',
                                            array('locale' => $locale,
                                                  'precision' => 3)
                                           );

    print $number; // 13524.678 を返します

### 計算の精度

getNumber($value, array $options = array()) では非常に大きな数値も正規化できるので、 PHP の通常の数値計算のように精度が限られている計算をする前には注意しましょう。 たとえば `if ((string)int_val($number) != $number) {` BCMath あるいは GMP を使用するなど。 実際にインストールされている PHP のほとんどは、 BCMath 拡張モジュールをサポートしています。

また、結果の十進表現の精度も、getNumber() のオプション 'precision' で指定した長さに丸められます。 精度を指定しなかった場合は、丸め処理は行われません。 精度を指定するには、PHP の整数のみを使用します。

十進表現で表した結果を丸めるのではなく指定した桁数で切り詰めたい場合は、 オプション 'number_format' を代わりに使用します。 十進表現の精度を定義するには、必要な桁数ぶんのゼロを指定します。 結果の丸めは行われません。つまり、もし number_format で定義した精度がゼロなら、 "1.6" は "1" であり、"2" とはなりません。 例を参照ください。

精度を指定した数値の正規化

    $locale = new Zend_Locale('de_AT');
    $number = Zend_Locale_Format::getNumber('13.524,678',
                                            array('precision' => 1,
                                                  'locale' => $locale)
                                           );
    print $number; // 13524.7 を返します

    $number = Zend_Locale_Format::getNumber('13.524,678',
                                            array('number_format' => '#.00',
                                                  'locale' => $locale)
                                           );
    print $number; // 13524.67 を返します

## 数値の地域化

toNumber($value, array $options = array()) は、 サポートするロケール にあわせて数値を正規化します。 この関数は、指定した数値を、特定のロケールにあわせて書式化した文字列を返します。 オプション 'number_format' を使用すると、 toNumber() で用いるデフォルト以外の数値書式を設定できます。

数値の地域化

    $locale = new Zend_Locale('de_AT');
    $number = Zend_Locale_Format::toNumber(13547.36,
                                           array('locale' => $locale));

    // 13.547,36 を返します
    print $number;

長さは無制限

toNumber() が地域化できる数値の長さには制限がありません。 整数や浮動小数点数の範囲の制限を受けることはありません。

getNumber() と同様の方法で、 toNumber() も精度を扱います。 精度を指定しなかった場合は、地域化した数値を完全な状態で返します。

精度を指定した数値の地域化

    $locale = new Zend_Locale('de_AT');
    $number = Zend_Locale_Format::toNumber(13547.3678,
                                           array('precision' => 2,
                                                 'locale' => $locale));

    // 13.547,37 を返します
    print $number;

オプション 'number_format' を使用すると、 独自の数値書式を定義できます。 書式を指定するには、以下の CLDR 書式を使用します。 ロケールを元に、桁区切りや小数点、その他の数値記号を取得します。 たとえば、ドイツ語では小数点として ',' を用いますが、英語では小数点に '.' を使用します。

自分で作成する数値書式用の書式トークン

トークン | 説明 | 書式の例 | 出力結果
--- | --- | --- | ---
#0 | 桁区切りや小数点のない数値を生成します。 | #0 | 1234567
, | 指定した桁数ごとに区切り文字を生成します。 | #,##0 | 1,234,567
#,##,##0 | 最初は標準の 3 桁で区切り、それ以降は 2 桁ごとに区切ります。 | #,##,##0 | 12,34,567
. | 小数点を生成します。 | #0.# | 1234567.1234
0 | 小数点以下を指定した桁数にします。 | #0.00 | 1234567.12

自分で定義した数値書式の使用

    $locale = new Zend_Locale('de_AT');
    $number = Zend_Locale_Format::toNumber(13547.3678,
                                           array('number_format' => '#,#0.00',
                                                 'locale' => 'de')
                                          );

    // 1.35.47,36 を返します
    print $number;

    $number = Zend_Locale_Format::toNumber(13547.3,
                                           array('number_format' => '#,##0.00',
                                                 'locale' => 'de')
                                           );

    // 13.547,30 を返します
    print $number;

## 数値かどうかの確認

isNumber($value, array $options = array()) は、指定した文字列が数値であるかどうかを `TRUE` あるいは `FALSE` で返します。

数値かどうかの確認

    $locale = new Zend_Locale();
    if (Zend_Locale_Format::isNumber('13.445,36', array('locale' => 'de_AT'))) {
        print "数値です";
    } else {
        print "数値ではありません";
    }

## 浮動小数点値の正規化

浮動小数点値のパースには getFloat($value, array $options = array()) 関数を使用します。これは、浮動小数点値を返します。

浮動小数点値の正規化

    $locale = new Zend_Locale('de_AT');
    $number = Zend_Locale_Format::getFloat('13.524,678',
                                           array('precision' => 2,
                                                 'locale' => $locale)
                                          );

    // 13524.68 を返します
    print $number;

## 浮動小数点値の地域化

toFloat() は、浮動小数点値の地域化を行います。 この関数は、指定した数値を地域化した文字列を返します。

浮動小数点値の地域化

    $locale = new Zend_Locale('de_AT');
    $number = Zend_Locale_Format::toFloat(13547.3655,
                                          array('precision' => 1,
                                                'locale' => $locale)
                                         );

    // 13.547,4 を返します
    print $number;

## 浮動小数点値かどうかの確認

isFloat($value, array $options = array()) は、 指定した文字列が浮動小数点値であるかどうかを `TRUE` あるいは `FALSE` で返します。

浮動小数点値かどうかの確認

    $locale = new Zend_Locale('de_AT');
    if (Zend_Locale_Format::isFloat('13.445,36', array('locale' => $locale))) {
        print "float です";
    } else {
        print "float ではありません";
    }

## 整数値の正規化

整数値のパースには getInteger() 関数を使用します。これは、整数値を返します。

整数値の正規化

    $locale = new Zend_Locale('de_AT');
    $number = Zend_Locale_Format::getInteger('13.524,678',
                                             array('locale' => $locale));

    // 13524 を返します
    print $number;

## 整数値の地域化

toInteger($value, array $options = array()) は、整数値の地域化を行います。 この関数は、指定した数値を地域化した文字列を返します。

整数値の地域化

    $locale = new Zend_Locale('de_AT');
    $number = Zend_Locale_Format::toInteger(13547.3655,
                                            array('locale' => $locale));

    // 13.547 を返します
    print $number;

## 整数値かどうかの確認

isInteger($value, array $options = array()) は、 指定した文字列が整数値であるかどうかを `TRUE` あるいは `FALSE` で返します。

整数値かどうかの確認

    $locale = new Zend_Locale('de_AT');
    if (Zend_Locale_Format::isInteger('13.445', array('locale' => $locale))) {
        print "integer です";
    } else {
        print "integer ではありません";
    }

## 数値系の変換

Zend_Locale_Format::convertNumerals() は、 さまざまな 数値系 の間での数値の変換を行います。その中には、標準のアラビア数字 (0,1,2,3,4,5,6,7,8,9) も含まれます。これは、 インド数字 とは異なることに注意しましょう。 インド数字は、アラビア語で数字を表す際に用いられることがあります。 サポートしていない数値系を使用すると、例外が発生します。 これは、不正確な変換によってエラーが発生するのを防ぐためです。 指定された数値系で数値として扱われない文字は、 そのまま出力に渡されます。つまり、単位の区切り文字などは変換されないということです。 Zend_Locale* コンポーネントは、CLDR が提供するデータに依存しています ( 言語ごとの文字の一覧 を参照ください)。

CLDR では今後、Europena/Latin 数値のことを "Latin" と呼ぶようになります。4 文字に略した形式は "Latn" です。 また、CLDR ではこの数値系のことを "scripts" と呼ぶようになります。

あるウェブフォームから、東アラビア文字 "١‎٠٠" が入力されたとしましょう。 大半のソフトウェアや PHP の関数は、アラビア数字にしか対応していません。 幸いなことに、この入力をそれと同等のラテン数字 "100" に変換するのは簡単で、convertNumerals($inputNumeralString, $sourceNumeralSystem, $destNumeralSystem) を使用するだけです。 これは、数値 `$input` の script を `$sourceNumeralSystem` から `$destNumeralSystem` に変換したものを返します。

東アラビア文字から European/Latin 文字への変換

    $arabicScript = "١‎٠٠";   // アラビア文字で "100" を表します
    $latinScript = Zend_Locale_Format::convertNumerals($arabicScript,
                                                       'Arab',
                                                       'Latn');

    print "\n元の内容:   " . $arabicScript;
    print "\n正規化したもの: " . $latinScript;

同様にして、任意の数値系をその他サポートしている数値系に変換できます。

ラテン文字から東アラビア文字への変換

    $latinScript = '123';
    $arabicScript = Zend_Locale_Format::convertNumerals($latinScript,
                                                        'Latn',
                                                        'Arab');

    print "\n元の内容: ".$latinScript;
    print "\n地域化したもの: " . $arabicScript;

各国語での文字名を使用した、4 文字の CLDR 文字コードの取得

    function getScriptCode($scriptName, $locale)
    {
        $scripts2names = Zend_Locale_Data::getList($locale, 'script');
        $names2scripts = array_flip($scripts2names);
        return $names2scripts[$scriptName];
    }
    echo getScriptCode('Latin', 'en'); // 出力は "Latn" となります
    echo getScriptCode('Tamil', 'en'); // 出力は "Taml" となります
    echo getScriptCode('tamoul', 'fr'); // 出力は "Taml" となります

サポートする数値系の一覧は Zend_Locale::getTranslationList('numberingsystem', 'en') をコールすれば取得できます。