1 <?xml version="1.0" encoding="UTF-8"?>
3 <!-- EN-Revision: 21790 -->
4 <sect1 id="zend.locale.introduction">
9 <classname>Zend_Locale</classname> は、
10 "ひとつのアプリケーションを世界中で使用するにはどうしたらいいでしょう?"
11 という質問に対するフレームワーク側からの回答です。たいていの人は
12 "かんたんじゃん。出力内容をいくつかの言語に翻訳すればいいんだよ。"
14 しかし、ただ単にフレーズを他の言語に置き換えるだけといった単純な翻訳テーブルでは不十分です。
15 たとえば姓と名の順番や敬称、そして数値や日付、時刻、通貨などの書式は、
20 <ulink url="http://en.wikipedia.org/wiki/Internationalization_and_localization">地域化だけでなく国際化</ulink>
21 も必要となります。これらは、それぞれ <emphasis>L10n</emphasis> および <emphasis>I18n</emphasis>
22 と略されることもあります。国際化とは、そのシステムを特定のユーザ集団の
23 (言語、地域、数値書式、財務規約、日付時刻書式などの)
24 ニーズにかかわらず使用できるようにすることを言います。
25 地域化とは、特定の集団のニーズに対応するために、
26 システムに明示的なサポートを追加することを言います。
27 たとえば言語の翻訳や、各地域の規約 (複数形の扱い、日付、時刻、通貨、名前、
29 <code>L10n</code> と <code>I18n</code> は、お互い補完しあうものです。
30 Zend Framework では、いくつかのコンポーネントを組み合わせることで
31 これらのサポートを提供しています。たとえば <classname>Zend_Locale</classname>、<classname>Zend_Date</classname>、
32 <classname>Zend_Measure</classname>、<classname>Zend_Translate</classname>、<classname>Zend_Currency</classname>
33 そして <classname>Zend_TimeSync</classname> といったコンポーネントがあります。
37 <title>Zend_Locale と setLocale()</title>
39 <ulink url="http://php.net/setlocale">PHP のドキュメント</ulink>
40 には、<methodname>setlocale()</methodname> はプロセス単位で動作するのでスレッドセーフではないと書かれています。
41 つまり、マルチスレッド環境では「スクリプト内で一切ロケールを変更していないのに、
42 勝手にロケールが変わってしまう」といった問題が発生する可能性があるということです。
43 スクリプトで <methodname>setlocale()</methodname> を使用すると、予期せぬ挙動を引き起こすことがあります。
46 <classname>Zend_Locale</classname> にはこのような制限はありません。なぜなら
47 <classname>Zend_Locale</classname> は <acronym>PHP</acronym> の <methodname>setlocale()</methodname>
52 <sect2 id="zend.locale.whatislocalization">
57 地域化とは、あるアプリケーション (あるいはホームページ)
58 が、さまざまな言語を話すユーザによって使用することができるということです。
59 しかし、ご存知のとおり、地域化とは単に文字列を翻訳するだけのことではありません。
63 <itemizedlist mark='opencircle'>
66 <classname>Zend_Locale</classname> -
67 他の Zend Framework コンポーネントにおける地域化サポートで対応しているロケールのバックエンドとなります。
72 <classname>Zend_Translate</classname> - 文字列を翻訳します。
77 <classname>Zend_Date</classname> - 日付や時刻を地域化します。
82 <classname>Zend_Calendar</classname> -
83 カレンダーを地域化します (グレゴリオ暦以外の暦もサポートしています)。
88 <classname>Zend_Currency</classname> - 通貨を地域化します。
93 <classname>Zend_Locale_Format</classname> - 地域化された数値のパースおよび生成を行います。
98 <classname>Zend_Locale_Data</classname> -
100 <ulink url="http://unicode.org/cldr/"><acronym>CLDR</acronym> にあるさまざまな内容</ulink>
101 について、各地域の標準文字列を取得します。
106 <code>TODO</code> - Localization of collations
113 <sect2 id="zend.locale.whatis">
115 <title>ロケールとは?</title>
118 コンピュータのユーザは皆、(気づいていないかもしれませんが) ロケールを使用しています。
119 地域化をサポートしていないアプリケーションの場合は、
120 通常は暗黙的に特定のロケール (そのアプリケーションの作者のロケール)
122 クラスや関数が地域化されていることを、ここでは
123 <code>ロケールに対応している</code>ということにします。
124 そのユーザがどの地域にいるのかを、どうやってコードで知るのでしょうか?
128 ロケール文字列あるいはロケールを表すオブジェクトを使用して、
129 <classname>Zend_Locale</classname> およびそのサブクラスはユーザが希望する言語および地域を知ります。
130 この情報にもとづいて、正しい書式化や正規化、規約を適用します。
135 <sect2 id="zend.locale.representation">
137 <title>ロケールの表現方法は?</title>
140 ロケール識別子に含まれる情報は、ユーザの言語と
141 地理上の地域 (たとえば自宅あるいは勤務先の属する州など) です。
142 Zend Framework が使用するロケール識別文字列は、
143 国際的に定義されている言語と地域の略称で、
144 <code>language_REGION</code> という形式です。
145 言語および地域は、どちらも <acronym>ASCII</acronym> 文字列となります。
150 大半の人の予想に反して、実はロケールは 2 文字とは限りません。
151 言語についても地域についても、短縮形が 2 文字にならないものがあります。
152 したがって、地域や言語の切り出しは自前では行わないようにしましょう。
153 ロケール文字列から言語や地域を切り出したい場合は <classname>Zend_Locale</classname> を使用しましょう。
154 自前で行ってしまうと、予期せぬ結果となってしまうことがあります。
159 アメリカのユーザの言語は <code>英語</code>、そして地域は <code>アメリカ</code>
160 です。そこで、ロケール識別子は "en_US" となります。
161 ドイツのユーザの言語は <code>ドイツ</code>、そして地域は <code>ドイツ</code>
162 です。そこで、ロケール識別子は "de_DE" となります。
163 <ulink url="http://unicode.org/cldr/data/diff/supplemental/languages_and_territories.html">
164 ロケールおよび地域の組み合わせの定義済みの一覧</ulink>
165 を参考に、Zend Framework で使用するロケールを選択しましょう。
168 <example id="zend.locale.representation.example-1">
169 <title>特定のロケールの選択</title>
170 <programlisting language="php"><![CDATA[
171 $locale = new Zend_Locale('de_DE'); // ドイツ語 _ ドイツ
176 アメリカに住むドイツ人は、言語は <code>ドイツ語</code> で地域は <code>アメリカ</code>
177 としたいかも知れません。しかし、このような非標準の組み合わせは、
178 "ロケール" としては直接サポートしていません。
179 そのかわりに、もし無効な組み合わせが使用されると、
181 たとえば "de_IS" は "de" に切り捨てられ、"xh_RU" は "xh"
182 に切り捨てられます。これらの組み合わせは無効だからです。
183 さらに、言語コードがサポートされていない場合 (例 "zz_US")
184 や存在しない場合は、デフォルトの "root" ロケールを使用します。
185 "root" ロケールではデフォルトとして、
186 国際的に認知されている日付、時刻、数値、通過等を定義しています。
187 この切捨て処理は、要求された情報の内容に依存します。
189 特定の型のデータ (たとえば日付) では有効だけれども
190 別の型 (たとえば通貨) では無効だというものがあるからです。
194 過去の歴史には注意しましょう。Zend Framework コンポーネントは、
195 これまでさまざまな場所で変更されてきた過去のタイムゾーンについては対応しません。
197 <ulink url="http://www.statoids.com/tus.html">この一覧表</ulink>
198 をご覧ください。特定の地域が夏時間を採用するかどうかや、
199 どのタイムゾーンに属するかなどは、時の政府によって何度も変更されています。
201 Zend Framework コンポーネントはこれらの変更には対応しません。
202 その代わりに、現時点の夏時間対応、現時点のタイムゾーンに対応した正しい時刻を使用します。
207 <sect2 id="zend.locale.selection">
209 <title>正しいロケールの選択</title>
212 たいていの場合は、<methodname>new Zend_Locale()</methodname>
213 とすると自動的に正しいロケールを選択します。
214 これはユーザのウェブブラウザから送られてきた情報をもとに判断します。
215 しかし、<methodname>new Zend_Locale(Zend_Locale::ENVIRONMENT)</methodname>
216 を使用すると、以下に示すようにホストサーバの環境設定から情報を取得するようになります。
219 <example id="zend.locale.selection.example-1">
220 <title>ロケールの自動選択</title>
221 <programlisting language="php"><![CDATA[
222 $locale = new Zend_Locale();
225 $locale1 = new Zend_Locale(Zend_Locale::BROWSER);
228 $locale2 = new Zend_Locale(Zend_Locale::ENVIRONMENT);
230 // フレームワークアプリケーションのデフォルト設定を使用します
231 $locale3 = new Zend_Locale(Zend_Locale::FRAMEWORK);
236 <classname>Zend_Locale</classname> がロケールの自動選択に使用する検索アルゴリズムは、
241 const <constant>Zend_Locale::BROWSER</constant> -
242 ユーザのウェブブラウザは、リクエストの際に情報を送信します。これは、
243 <acronym>PHP</acronym> のグローバル変数 <varname>$_SERVER['HTTP_ACCEPT_LANGUAGE']</varname> で取得できます。
244 対応するロケールが見つからない場合は <constant>ENVIRONMENT</constant>
246 <constant>FRAMEWORK</constant> を使用します。
251 const <constant>Zend_Locale::ENVIRONMENT</constant> -
252 <acronym>PHP</acronym> は、ホストサーバのロケールを
253 <methodname>setlocale()</methodname> 関数で取得します。
254 対応するロケールが見つからない場合は <constant>FRAMEWORK</constant> による検索を行い、
255 それでもだめなら最後は <constant>BROWSER</constant> を使用します。
260 const <constant>Zend_Locale::FRAMEWORK</constant> -
261 Zend Framework がコンポーネントのデフォルトを指定できる仕組みが定まったら
262 (予定されていますが、現在はまだありません)、
263 この定数を使用することでデフォルト設定を選択できるようになります。
264 対応するロケールが見つからない場合は <constant>ENVIRONMENT</constant>
266 <constant>BROWSER</constant> を使用します。
274 <sect2 id="zend.locale.selection.automatic">
276 <title>自動ロケールの使用法</title>
279 <classname>Zend_Locale</classname> では、さらに 3 つのロケールを用意しています。
280 これらのロケールは、どこか特定の言語や地域を表すものではありません。
282 <methodname>getDefault()</methodname> メソッドと同じような働きをするものです。
283 しかし、インスタンスを作成したりといった余計な作業が不要になります。
284 これらの "自動" ロケールは、標準のロケールを使用できるところなら
285 どこででも使用可能で、文字列で指定することになります。
286 これを使用することで、ブラウザが提供するロケール情報などをうまく利用できるようになります。
290 以下の 3 つのロケールは、それぞれ微妙に異なる働きをします。
295 <code>'browser'</code> - <classname>Zend_Locale</classname>
296 は、ユーザが使用するウェブブラウザが提供する情報を使用します。
297 これは、<acronym>PHP</acronym> のグローバル変数 <constant>HTTP_ACCEPT_LANGUAGE</constant>
301 ブラウザが複数のロケールを指定している場合は、
302 <classname>Zend_Locale</classname> は最初に見つけたロケールを使用します。
303 ブラウザがロケールを指定していなかったり、
304 あるいはコマンドラインからスクリプトを実行したりした場合は、
305 代わりに自動ロケール <code>'environment'</code>
311 <code>'environment'</code> - <classname>Zend_Locale</classname> は、
312 サーバが提供する情報を使用します。これは、<acronym>PHP</acronym> の内部関数
313 <methodname>setlocale()</methodname> で取得します。
317 <classname>Zend_Locale</classname> は最初に見つけたロケールを使用します。
319 代わりに自動ロケール <code>'browser'</code>
325 <code>'auto'</code> - <classname>Zend_Locale</classname> は、
326 可能な限りの方法でロケールを検出しようとします。
327 まず最初にユーザが指定するロケールを探し、
328 それに失敗するとホストのロケールを探します。
331 ロケールの検出に失敗した場合は例外をスローし、
338 <example id="zend.locale.selection.automatic.example-1">
339 <title>自動ロケールの使用法</title>
340 <programlisting language="php"><![CDATA[
342 //$locale = new Zend_Locale(Zend_Locale::BROWSER);
343 //$date = new Zend_Date($locale);
346 $date = new Zend_Date('auto');
352 <sect2 id="zend.locale.defaultlocale">
354 <title>デフォルトのロケールの使用</title>
357 環境によっては、ロケールの自動検出ができないこともあります。
358 コマンドラインからのリクエストを受け取った場合や
359 リクエスト元のブラウザに言語が設定されていない場合、
361 あるいはその他のプロプライエタリなロケールだったりする場合などです。
365 このような場合は、<classname>Zend_Locale</classname>
366 は通常は例外をスローして自動検出に失敗したことを示します。
367 このような状況への対応方法は二通りあります。
368 新たなロケールを手動で設定するか、あるいはデフォルトのロケールを定義するかです。
371 <example id="zend.locale.defaultlocale.example-1">
372 <title>ロケールの例外処理</title>
373 <programlisting language="php"><![CDATA[
376 $locale = new Zend_Locale('auto');
377 } catch (Zend_Locale_Exception $e) {
378 $locale = new Zend_Locale('de');
382 $date = new Zend_Date($locale);
387 この方法には大きな問題点があります。<classname>Zend_Locale</classname>
388 を使用するすべてのクラス内で、ロケールオブジェクトを設定することになるのです。
389 複数のクラスを使用している場合など、これはとても面倒です。
393 Zend Framework リリース 1.5 以降では、もっとうまいやりかたが用意されています。
394 デフォルトのロケールを、静的メソッド <methodname>setDefault()</methodname> で設定できるのです。
395 もちろん、未知のロケールや不完全なロケールが指定された場合も例外をスローします。
396 <methodname>setDefault()</methodname> は、<classname>Zend_Locale</classname>
397 を使用するクラスのインスタンスを作成する前に最初にコールする必要があります。
401 <example id="zend.locale.defaultlocale.example-2">
402 <title>デフォルトのロケールの設定</title>
403 <programlisting language="php"><![CDATA[
405 Zend_Locale::setDefault('de');
408 $date = new Zend_Date();
413 ロケールが検出できなかった場合は、自動的にロケール
414 <emphasis>de</emphasis> を使用します。
415 見つかった場合は、そのロケールを使用します。
420 <sect2 id="zend.locale.interoperate">
422 <title>ZF のロケール対応のクラス</title>
425 Zend Framework では、ロケール対応のクラスは <classname>Zend_Locale</classname>
426 を使用しています。そして、上で説明したように自動的にロケールを選択します。
427 たとえば、Zend Framework のウェブアプリケーションで <classname>Zend_Date</classname>
428 を使用して日付を作成すると、何もロケールを指定しなくても
429 ユーザのウェブブラウザの設定からロケール情報を取得してそれを使用します。
432 <example id="zend.locale.interoperate.example-1">
433 <title>日付のデフォルトが、ウェブのユーザのロケールになる例</title>
434 <programlisting language="php"><![CDATA[
435 $date = new Zend_Date('2006',Zend_Date::YEAR);
440 このデフォルトを上書きし、ロケール対応の Zend Framework
441 コンポーネントでウェブサイトの訪問者の設定にかかわらず特定のロケールを指定するには、
442 コンストラクタの三番目の引数でロケールを明示的に指定します。
445 <example id="zend.locale.interoperate.example-2">
446 <title>デフォルトのロケール選択のオーバーライド</title>
447 <programlisting language="php"><![CDATA[
448 $usLocale = new Zend_Locale('en_US');
449 $date = new Zend_Date('2006',Zend_Date::YEAR, $usLocale);
450 $temp = new Zend_Measure_Temperature('100,10',
451 Zend_Measure::TEMPERATURE,
457 多くのオブジェクトですべて同一のデフォルトロケールを使用することがわかっている場合は、
458 それを明示的に指定すると、毎回デフォルトロケールを検索することによる
462 <example id="zend.locale.interoperate.example-3">
463 <title>デフォルトのロケールを使用する際のパフォーマンスの最適化</title>
464 <programlisting language="php"><![CDATA[
465 $locale = new Zend_Locale();
466 $date = new Zend_Date('2006', Zend_Date::YEAR, $locale);
467 $temp = new Zend_Measure_Temperature('100,10',
468 Zend_Measure::TEMPERATURE,
475 <sect2 id="zend.locale.frameworkwidelocale">
477 <title>アプリケーション単位のロケール</title>
480 Zend Framework ではアプリケーション単位でのロケールの使用も可能です。
481 そのためには、<classname>Zend_Locale</classname> のインスタンスをレジストリに
482 'Zend_Locale' というキーで登録します。すると、Zend Framework
483 のロケール対応のクラスすべてがこのインスタンスを使うようになります。
484 このようにして一度レジストリにロケールを設定してしまえば、
486 他のすべてのクラスでも自動的にこれが用いられるようになります。
487 具体的な使用法は、以下の例を参照ください。
490 <example id="zend.locale.frameworkwidelocale.example">
491 <title>アプリケーション単位のロケールの使用例</title>
492 <programlisting language="php"><![CDATA[
494 $locale = new Zend_Locale('de_AT');
495 Zend_Registry::set('Zend_Locale', $locale);
498 $date = new Zend_Date();
499 // print $date->getLocale();
500 echo $date->getDate();
506 <sect2 id="zend.locale.formatoptions">
508 <title>Zend_Locale_Format::setOptions(array $options)</title>
511 オプション 'precision' の値を使用して、桁数の切り詰めあるいは拡張を行います。
512 '-1' を指定すると、値の小数部分の桁数を変更しないようにします。
513 オプション 'locale' は、数値や日付をパースする際の区切り文字や月名を判断するために使用します。
514 オプション 'format_type' では、<acronym>CLDR</acronym>/ISO 日付書式指定トークンおよび <acronym>PHP</acronym>
515 の date() で使用するトークンのどちらを使用するかを選択します。
516 オプション 'fix_date' は、無効な形式の日付に対する自動修正処理を有効あるいは無効にします。
517 オプション 'number_format' は、<methodname>toNumber()</methodname>
518 で使用するデフォルトの数値書式を指定します
519 (詳細は <xref linkend= "zend.locale.number.localize"/> を参照ください)。
523 'date_format' オプションでデフォルトの日付書式文字列を指定できます。
524 しかし、setOptions() で 'date_format' を指定した後で getDate() や
525 checkdateFormat() そして getTime() を使用する際には十分注意しましょう。
526 これらのメソッドをそのロケールのデフォルトの日付書式で使用するには
527 array('date_format' => null, 'locale' => $locale) をメソッドのオプションで指定します。
530 <example id="zend.locale.formatoptions.example-1">
531 <title>日付のデフォルトを、ウェブユーザの正しいロケールに設定する</title>
532 <programlisting language="php"><![CDATA[
533 Zend_Locale_Format::setOptions(array('locale' => 'en_US',
535 'format_type' => 'php'));
540 ロケールの標準の定義を使用する場合は、オプション <constant>Zend_Locale_Format::STANDARD</constant>
541 を指定します。<code>date_format</code> に <constant>Zend_Locale_Format::STANDARD</constant> を設定すると、
542 実際に設定されているロケールの標準定義を使用します。
543 これを number_format に設定すると、このロケールの標準数値書式を使用します。
544 また、locale に設定すると、この環境あるいはブラウザの標準のロケールを使用します。
547 <example id="zend.locale.formatoptions.example-2">
548 <title>setOptions() での STANDARD の使用</title>
549 <programlisting language="php"><![CDATA[
550 Zend_Locale_Format::setOptions(array('locale' => 'en_US',
551 'date_format' => 'dd.MMMM.YYYY'));
552 // グローバル設定の日付書式をオーバーライドします
553 $date = Zend_Locale_Format::getDate('2007-04-20',
554 array('date_format' =>
555 Zend_Locale_Format::STANDARD);
558 Zend_Locale_Format::setOptions(array('locale' => Zend_Locale_Format::STANDARD,
559 'date_format' => 'dd.MMMM.YYYY'));
565 <sect2 id="zend.locale.cache">
567 <title>Zend_Locale とそのサブクラスの高速化</title>
570 <classname>Zend_Locale</classname> およびそのサブクラスを高速化するには、
571 <classname>Zend_Cache</classname> を使用します。<classname>Zend_Locale</classname>
572 を使用している場合は、静的メソッド <methodname>Zend_Locale::setCache($cache)</methodname>
573 を使用します。<classname>Zend_Locale_Format</classname> を高速化するには、
574 オプション <code>cache</code> を
575 <classname>Zend_Locale_Format::setOptions(array('cache' => $adapter));</classname>
576 のように指定します。両方のクラスを使用している場合は <classname>Zend_Locale</classname>
577 にのみキャッシュを設定します。そうしないと、
578 後から設定したキャッシュがそれまでの内容を上書きしてしまうことになります。
580 <methodname>getCache()</methodname>、<methodname>hasCache()</methodname>、
581 <methodname>clearCache()</methodname> および
582 <methodname>removeCache()</methodname> も用意されています。
586 キャッシュを設定しなかった場合は、<classname>Zend_Locale</classname>
588 時には、パフォーマンスが低下するのを承知のうえで
589 敢えてキャッシュを設定しないようにしたいこともあるでしょう。
591 <methodname>disableCache(true)</methodname> を使用します。
592 このメソッドは、実際に設定されているキャッシュを無効にする
594 キャッシュの設定を省略した際に自動的にキャッシュが設定されてしまうことも防ぎます。