<?xml version="1.0" encoding="UTF-8"?>
<!-- Reviewed: no -->
<!-- EN-Revision: 24249 -->
<sect1 id="zend.locale.parsing">

    <title>正規化および地域化</title>

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

    <para>
        まったく同じ文字列からなる数値や日付でも、
        異なる習慣や規約を使用している人が見ると異なる意味にとられることがあります。
        数値や日付を、あいまいさをなくして正確に解釈するには、
        これらの文字列を正規化し、標準化されたデータ構造に変換する必要があります。
        したがって、<classname>Zend_Locale_Format</classname> のすべてのメソッドは、
        入力データを処理するためにロケール情報を必要とします。
        <note>
            <title>デフォルトの "root" ロケール</title>
            <para>
                ロケールを省略した場合は、正規化や地域化の際に
                標準の "root" ロケールを使用します。
                これは予期せぬ動作を引き起こす可能性があります。
                さまざまなロケールの入力を扱ったり、特定のロケールで出力したい場合などに注意が必要です。
            </para>
        </note>
    </para>

    <sect2 id="zend.locale.number.normalize">

        <title>数値の正規化: getNumber($input, Array $options)</title>

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

        <example id="zend.locale.number.normalize.example-1">
            <title>数値の正規化</title>
            <programlisting language="php"><![CDATA[
$locale = new Zend_Locale('de_AT');
$number = Zend_Locale_Format::getNumber('13.524,678',
                                        array('locale' => $locale,
                                              'precision' => 3)
                                       );

print $number; // 13524.678 を返します
]]></programlisting>
        </example>

        <sect3 id="zend.locale.number.normalize.precision">

            <title>計算の精度</title>

            <para>
                <methodname>getNumber($value, array $options = array())</methodname> では非常に大きな数値も正規化できるので、
                <acronym>PHP</acronym> の通常の数値計算のように精度が限られている計算をする前には注意しましょう。
                たとえば <command>if ((string)int_val($number) != $number) {</command>
                <ulink url="http://www.php.net/manual/ja/book.bc.php">BCMath</ulink> あるいは
                <ulink url="http://www.php.net/manual/ja/book.gmp.php">GMP</ulink> を使用するなど。
                実際にインストールされている <acronym>PHP</acronym> のほとんどは、
                BCMath 拡張モジュールをサポートしています。
            </para>

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

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

            <example id="zend.locale.number.normalize.precision.example-1">
                <title>精度を指定した数値の正規化</title>
                <programlisting language="php"><![CDATA[
$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 を返します
]]></programlisting>
            </example>

        </sect3>

    </sect2>

    <sect2 id="zend.locale.number.localize">

        <title>数値の地域化</title>

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

        <example id="zend.locale.number.localize.example-1">
            <title>数値の地域化</title>
            <programlisting language="php"><![CDATA[
$locale = new Zend_Locale('de_AT');
$number = Zend_Locale_Format::toNumber(13547.36,
                                       array('locale' => $locale));

// 13.547,36 を返します
print $number;
]]></programlisting>
        </example>

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

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

        <example id="zend.locale.number.localize.example-2">
            <title>精度を指定した数値の地域化</title>
            <programlisting language="php"><![CDATA[
$locale = new Zend_Locale('de_AT');
$number = Zend_Locale_Format::toNumber(13547.3678,
                                       array('precision' => 2,
                                             'locale' => $locale));

// 13.547,37 を返します
print $number;
]]></programlisting>
        </example>

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

        <table id="zend.locale.number.localize.table-1">
            <title>自分で作成する数値書式用の書式トークン
            </title>
            <tgroup cols="4">
                <thead>
                    <row>
                        <entry>トークン</entry>
                        <entry>説明</entry>
                        <entry>書式の例</entry>
                        <entry>出力結果</entry>
                    </row>
                </thead>
                <tbody>
                    <row>
                        <entry>#0</entry>
                        <entry>桁区切りや小数点のない数値を生成します。</entry>
                        <entry>#0</entry>
                        <entry>1234567</entry>
                    </row>
                    <row>
                        <entry>,</entry>
                        <entry>指定した桁数ごとに区切り文字を生成します。</entry>
                        <entry>#,##0</entry>
                        <entry>1,234,567</entry>
                    </row>
                    <row>
                        <entry>#,##,##0</entry>
                        <entry>最初は標準の 3 桁で区切り、それ以降は 2 桁ごとに区切ります。</entry>
                        <entry>#,##,##0</entry>
                        <entry>12,34,567</entry>
                    </row>
                    <row>
                        <entry>.</entry>
                        <entry>小数点を生成します。</entry>
                        <entry>#0.#</entry>
                        <entry>1234567.1234</entry>
                    </row>
                    <row>
                        <entry>0</entry>
                        <entry>小数点以下を指定した桁数にします。</entry>
                        <entry>#0.00</entry>
                        <entry>1234567.12</entry>
                    </row>
                </tbody>
            </tgroup>
        </table>

        <example id="zend.locale.number.localize.example-3">
            <title>自分で定義した数値書式の使用</title>
            <programlisting language="php"><![CDATA[
$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;
]]></programlisting>
        </example>

    </sect2>

    <sect2 id="zend.locale.number.test">

        <title>数値かどうかの確認</title>

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

        <example id="zend.locale.number.test.example-1">
            <title>数値かどうかの確認</title>
            <programlisting language="php"><![CDATA[
$locale = new Zend_Locale();
if (Zend_Locale_Format::isNumber('13.445,36', array('locale' => 'de_AT'))) {
    print "数値です";
} else {
    print "数値ではありません";
}
]]></programlisting>
        </example>

    </sect2>

    <sect2 id="zend.locale.float.normalize">

        <title>浮動小数点値の正規化</title>

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

        <example id="zend.locale.float.normalize.example-1">
            <title>浮動小数点値の正規化</title>
            <programlisting language="php"><![CDATA[
$locale = new Zend_Locale('de_AT');
$number = Zend_Locale_Format::getFloat('13.524,678',
                                       array('precision' => 2,
                                             'locale' => $locale)
                                      );

// 13524.68 を返します
print $number;
]]></programlisting>
        </example>

    </sect2>

    <sect2 id="zend.locale.float.localize">

        <title>浮動小数点値の地域化</title>

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

        <example id="zend.locale.float.localize.example-1">
            <title>浮動小数点値の地域化</title>
            <programlisting language="php"><![CDATA[
$locale = new Zend_Locale('de_AT');
$number = Zend_Locale_Format::toFloat(13547.3655,
                                      array('precision' => 1,
                                            'locale' => $locale)
                                     );

// 13.547,4 を返します
print $number;
]]></programlisting>
        </example>

    </sect2>

    <sect2 id="zend.locale.float.test">

        <title>浮動小数点値かどうかの確認</title>

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

        <example id="zend.locale.float.test.example-1">
            <title>浮動小数点値かどうかの確認</title>
            <programlisting language="php"><![CDATA[
$locale = new Zend_Locale('de_AT');
if (Zend_Locale_Format::isFloat('13.445,36', array('locale' => $locale))) {
    print "float です";
} else {
    print "float ではありません";
}
]]></programlisting>
        </example>

    </sect2>

    <sect2 id="zend.locale.integer.normalize">

        <title>整数値の正規化</title>

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

        <example id="zend.locale.integer.normalize.example-1">
            <title>整数値の正規化</title>
            <programlisting language="php"><![CDATA[
$locale = new Zend_Locale('de_AT');
$number = Zend_Locale_Format::getInteger('13.524,678',
                                         array('locale' => $locale));

// 13524 を返します
print $number;
]]></programlisting>
        </example>

    </sect2>

    <sect2 id="zend.locale.integer.localize">

        <title>整数値の地域化</title>

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

        <example id="zend.locale.integer.localize.example-1">
            <title>整数値の地域化</title>
            <programlisting language="php"><![CDATA[
$locale = new Zend_Locale('de_AT');
$number = Zend_Locale_Format::toInteger(13547.3655,
                                        array('locale' => $locale));

// 13.547 を返します
print $number;
]]></programlisting>
        </example>

    </sect2>

    <sect2 id="zend.locale.integer.test">

        <title>整数値かどうかの確認</title>

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

        <example id="zend.locale.integer.test.example-1">
            <title>整数値かどうかの確認</title>
            <programlisting language="php"><![CDATA[
$locale = new Zend_Locale('de_AT');
if (Zend_Locale_Format::isInteger('13.445', array('locale' => $locale))) {
    print "integer です";
} else {
    print "integer ではありません";
}
]]></programlisting>
        </example>

    </sect2>

    <sect2 id="zend.locale.numbersystems">

        <title>数値系の変換</title>

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

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

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

        <example id="zend.locale.numbersystems.example-1">
            <title>東アラビア文字から European/Latin 文字への変換</title>
            <programlisting language="php"><![CDATA[
$arabicScript = "١‎٠٠";   // アラビア文字で "100" を表します
$latinScript = Zend_Locale_Format::convertNumerals($arabicScript,
                                                   'Arab',
                                                   'Latn');

print "\n元の内容:   " . $arabicScript;
print "\n正規化したもの: " . $latinScript;
]]></programlisting>
        </example>

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

        <example id="zend.locale.numbersystems.example-2">
            <title>ラテン文字から東アラビア文字への変換</title>
            <programlisting language="php"><![CDATA[
$latinScript = '123';
$arabicScript = Zend_Locale_Format::convertNumerals($latinScript,
                                                    'Latn',
                                                    'Arab');

print "\n元の内容: ".$latinScript;
print "\n地域化したもの: " . $arabicScript;
]]></programlisting>
        </example>

        <example id="zend.locale.numbersystems.example-3">
            <title>各国語での文字名を使用した、4 文字の <acronym>CLDR</acronym> 文字コードの取得</title>
            <programlisting language="php"><![CDATA[
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" となります
]]></programlisting>
        </example>

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

    </sect2>

</sect1>
<!--
vim:se ts=4 sw=4 et:
-->
