18.3. 正規化および地域化

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

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

[注意] デフォルトの "root" ロケール

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

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

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

例 18.18. 数値の正規化

<?php
require_once 'Zend/Locale.php';

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

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

18.3.1.1. 計算の精度

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

また、結果の十進表現の精度も、 getNumber() で指定した長さに切り詰められます。 精度を指定しなかった場合は、切り詰められることはありません。 精度を指定するには、PHP の整数のみを使用します。 結果の丸めは行われません。つまり、もし精度がゼロなら、 "1.6" は "1" であり、"2" とはなりません。

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

<?php
require_once 'Zend/Locale.php';

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

print $number; // 13524.6 を返します
?>

18.3.2. 数値の地域化

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

例 18.20. 数値の地域化

<?php
require_once 'Zend/Locale.php';

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

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

[注意] 長さは無制限

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

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

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

<?php
require_once 'Zend/Locale.php';

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

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

[注意] 注意

toNumber() は結果を切り詰めます。 結果の丸めは行われません。つまり、1.6 は 2 ではなく 1 となります。

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

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

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

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

<?php
require_once 'Zend/Locale.php';

$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;
?>

18.3.3. 数値かどうかの確認

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

例 18.23. 数値かどうかの確認

<?php
require_once 'Zend/Locale.php';

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

18.3.4. 浮動小数点値の正規化

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

例 18.24. 浮動小数点値の正規化

<?php
require_once 'Zend/Locale.php';

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

// 13524.67 を返します
print $number;
?>

18.3.5. 浮動小数点値の地域化

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

例 18.25. 浮動小数点値の地域化

<?php
require_once 'Zend/Locale.php';

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

// 13.547,3 を返します
print $number;
?>

[注意] 注意

toFloat() は結果を切り詰めます。 結果の丸めは行われません。つまり、1.6 は 2 ではなく 1 となります。

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

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

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

<?php
require_once 'Zend/Locale.php';

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

18.3.7. 整数値の正規化

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

例 18.27. 整数値の正規化

<?php
require_once 'Zend/Locale.php';

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

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

18.3.8. 整数値の地域化

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

例 18.28. 整数値の地域化

<?php
require_once 'Zend/Locale.php';

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

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

18.3.9. 整数値かどうかの確認

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

例 18.29. 整数値かどうかの確認

<?php
require_once 'Zend/Locale.php';

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

18.3.10. 数値系の変換

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 に変換したものを返します。

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

<?php
require_once 'Zend/Locale.php';

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

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

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

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

<?php
require_once 'Zend/Locale.php';

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

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

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

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

18.3.10.1. サポートしている数値系の一覧

表 18.3. サポートしている数値系の一覧

記法名 文字
アラビア文字 Arab
バリ文字 Bali
ベンガル文字 Beng
デーバナーガリー文字 Deva
グジャラート文字 Gujr
グルムキー文字 Guru
カンナダ文字 Knda
カンボジア文字 Khmr
ラオ文字 Laoo
リンブ文字 Limb
マラヤーラム文字 Mlym
モンゴル文字 Mong
ミャンマー文字 Mymr
タイレ文字 Talu
N'Ko Nkoo
オリヤー文字 Orya
タミール文字 Taml
テルグ文字 Telu
タイ文字 Tale
チベット文字 Tibt