国際化 (I18N)

国際化 (I18N) はプログラムの変更なしで、各言語、各地域に適合できるように、ソフトウェアアプリケーションを設計する過程を指します。 ウェブアプリケーションでは、ユーザになる可能性のある人が世界中から訪れるため、特に重要です。

Yii は I18N のサポートをいくつかの面から提供します。

  • 各可能な言語と変形のためのロケール (地域・言語) データの提供
  • メッセージとファイルの翻訳機能の提供
  • ロケール (地域・言語) に依存する日時フォーマットの提供
  • ロケール (地域・言語) に依存する数値フォーマットの提供

以下の節で上記について詳しく説明します。

1. ロケールと言語

ロケールは、ユーザの言語、国、そして、ユーザがユーザインタフェースに期待する何らかの特別な好みを定義するパラメータのセットです。 これは、通常、言語 ID と地域 ID から成る ID により確認されます。 たとえば、ID en_US は、英語とアメリカのロケールを表します。 整合性のため、Yii の全てのロケール ID は、小文字で LanguageIDLanguageID_RegionID のフォーマットで標準化されています (例: en, en_us)。

ロケールデータは、CLocale のインスタンスとして表されます。 これは、通貨記号、数値記号、通貨フォーマット、数値フォーマット、 日時フォーマット、日付に関する名称を含むロケールに依存する情報を提供します。 言語情報はロケール ID に含まれるため、CLocale では提供されません。 同様に、多くの場合、ロケールと言語は同じ意味として使用します。

ロケール ID を与えると、CLocale::getInstance($localeID) もしくは CApplication::getLocale($localeID) により、それに一致する CLocale インタンスを取得できます。

情報: Yii にはほとんど全ての言語と地域のためのロケールデータが含まれています。 データは 共通ロケールデータリポジトリ (CLDR) より取得されています。 オリジナルのデータは滅多に使用されない多くの情報を含んでいるため、各ロケールとも、そのサブセットだけが提供されます。 ユーザが自分自身のカスタマイズしたロケールデータを供給することも出来ます。 そうするためには、CApplication::localeDataPath プロパティを構成して、カスタマイズされたロケールデータを含むディレクトリを指定します。 カスタマイズされたロケールデータファイルを作る場合は、framework/i18n/data の下にあるロケールデータファイルを参照して下さい。

Yii アプリケーションでは、ソース言語ターゲット言語 を区別します。 ターゲット言語は、アプリケーションが対象とするユーザの言語 (ロケール) で、一方、ソース言語はアプリケーションソースファイルに書かれている言語 (ロケール) を示します。 国際化は二つの言語が異なる場合のみで起こります。

ヒント: ソース言語は英語のままにしておく方が良いでしょう。 なぜなら、(例えば日本語から他の言語への翻訳者を探すよりも) 英語から他の言語への翻訳者を探す方が容易だろうと思われるからです。

ターゲット言語アプリケーション初期構成 で設定するか、または、何らかの国際化が起こる前に動的に変更することで設定できます。

ヒント: 場合によっては、ユーザが優先している言語 (ユーザのブラウザに設定されている優先言語) をターゲット言語として設定したいかもしれません。 その場合は、CHttpRequest::preferredLanguage を使ってユーザの優先言語の ID を読み出せます。

2. 翻訳

I18N でもっとも必要な機能は、おそらくメッセージ翻訳やビューの翻訳などの翻訳です。 前者はテキストメッセージのターゲット言語への翻訳、後者はファイル全体のターゲット言語への翻訳です。

翻訳リクエストは、翻訳すべきオブジェクト、オブジェクトの現在のソース言語、オブジェクトの翻訳先のターゲット言語から構成されます。 Yii では、ソース言語はデフォルトでは アプリケーションソース言語 になり、ターゲット言語はデフォルトでは アプリケーション言語 になります。 ソース言語とターゲット言語が同じ場合、翻訳されません。

メッセージ翻訳

メッセージ翻訳は、Yii::t() をコールすることで行われます。 メソッドは指定されたメッセージを、ソース言語 から ターゲット言語 へと翻訳します。

メッセージを翻訳するときは、カテゴリを指定しなければなりません。 というのは、同じメッセージでも、異なるカテゴリ (文脈) の下では、異なる翻訳が行われる可能性があるためです。 カテゴリ yii は Yii フレームワークのコアコードによって使用されるメッセージのために予約済みです。

メッセージには、Yii::t() を呼び出す際に、実際のパラメータ値によって置き換えられるパラメータプレースホルダを含められます。 例えば、以下のメッセージ翻訳リクエストは、オリジナルメッセージの {alias} プレースホルダを、実際の alias 値で置き換えます。

Yii::t('app', 'Path alias "{alias}" is redefined.',
    array('{alias}'=>$alias))

注意: 翻訳対象のメッセージは文字列定数でなければなりません。 それらにはメッセージ内容を変える変数 (例: "Invalid {$message} content.") を含めるべきではありません。 メッセージが何らかのパラメータにより変化する必要がある場合は、パラメータプレースホルダを使用してください。

翻訳されたメッセージは、メッセージソース と呼ばれるリポジトリに保存されます。 メッセージソースは、CMessageSource か、その子クラスのインスタンスとして表現されます。 Yii::t() が呼び出されると、メッセージソースのメッセージが探されて、見つかった場合には翻訳されたバージョンが返されます。

Yii は下記のタイプのメッセージソースを備えています。 CMessageSource を継承して、オリジナルのメッセージソースタイプを作成することも可能です。

  • CPhpMessageSource: メッセージ翻訳は、PHP 配列に "キー-値" のペアとして格納されます。 オリジナルメッセージがキーで、翻訳されたメッセージが値です。 各配列が、特定のカテゴリに属するメッセージの翻訳を表現します。 配列はカテゴリ名と同じ名前の独立した PHP スクリプトファイル保存されます。 同じ言語のPHP 翻訳ファイルはロケール ID を名前とした同じディレクトリ下に保存されます。 そして、それら全てのディレクトリは、basePath で指定されたディレクトリ下に位置します。

  • CGettextMessageSource: メッセージ翻訳は、GNU Gettext ファイルとして保存されます。

  • CDbMessageSource: メッセージ翻訳は、データベーステーブルとして保存されます。 詳細は、API ドキュメンテーション CDbMessageSource を参照してください。

メッセージソースは、アプリケーションコンポーネント として読み込まれます。 Yii は、messages という名前のアプリケーションコンポーネントがユーザアプリケーションで使用されるメッセージを格納するとあらかじめ宣言します。 デフォルトでは、メッセージソースのタイプは CPhpMessageSource で、protected/messages が PHP 翻訳ファイルのベースパスとなります。

要約すると、メッセージ翻訳を使用するためには、下記のステップが必要です:

  1. 適切な箇所で Yii::t() をコールします。

  2. protected/messages/LocaleID/CategoryName.php に PHP 翻訳ファイルを作成します。 各ファイルは、単にメッセージ翻訳の配列を返します。 翻訳メッセージを保存するのにデフォルトの CPhpMessageSource を使用すると仮定していることに注意して下さい。

  3. CApplication::sourceLanguageCApplication::language の設定を行います。

ヒント: CPhpMessageSource をメッセージソースとして使用する場合は、メッセージ翻訳を管理するために、Yii の yiic ツールを利用できます。 message コマンドによって、自動的に選択されたソースファイルから翻訳されるべきメッセージを抽出し、必要なら、既存の翻訳にそれらをマージできます。 messageコマンドのさらに詳細な使用方法については、yiic help messageを実行して下さい。

CPhpMessageSource を使ってメッセージソースを管理する場合、エクステンションクラス (例えばウィジェットやモジュール) のメッセージは分離して管理および使用することが出来ます。 具体的に言うと、メッセージが Xyz というクラス名のエクステンションに属している場合、メッセージカテゴリを Xyz.categoryName の形式で指定することが出来ます。 対応するメッセージファイルは BasePath/messages/LanguageID/categoryName.php であると見なされます。 ここで BasePath はエクステンションクラスファイルを含むディレクトリを指します。 そして、Yii::t() を使ってエクステンションのメッセージを翻訳するときは、かわりに、以下の書式が使用されなければなりません。

Yii::t('Xyz.categoryName', 'message to be translated')

Yii は choice format をサポートしています。 これは、複数形書式 (plural forms) としても知られているものです。 choice format は、与えられた数値に従い翻訳を選択します。 たとえば、'book' という単語は、英語では、本の数によって単数形か複数形のどちらかを取りますし、また、他の言語では、(中国語のように) 異なる形を持たない場合、(ロシア語のように) より複雑な複数形の規則がある場合があります。 choice format はこの問題を簡単かつ効果的な方法で解決します。

choice format を使用するには、翻訳メッセージが下記のように | によって分けられた "式-メッセージ" のペアで構成されている必要があります:

'expr1#message1|expr2#message2|expr3#message3'

exprN は boolean 値を返す有効な PHP の式で、対応するメッセージが返されるべきかどうかを示すものです。 最初に true と評価された式に対応するメッセージのみが返されます。 式には、数値を表す n (注意: $n ではありません) という名前の特別な変数を含められます。 この変数が、最初のメッセージパラメータとして渡される数値を受け取ります。 たとえば、翻訳されたメッセージが以下のようなものであるとします。

'n==1#one book|n>1#many books'

Yii::t() を呼び出す際に、メッセージのパラメータ配列に数値 2 を渡した場合、最終的に翻訳メッセージとして many books が返されます。

Yii::t('app', 'n==1#one book|n>1#many books', array(1));
// または、1.1.6 以降なら
Yii::t('app', 'n==1#one book|n>1#many books', 1);

略記法として、式が数値のみの場合、n==数値 と解釈されます。 そのため、上記の翻訳メッセージは下記のように記述することも可能です。

'1#one book|n>1#many books'

複数形の書式

バージョン 1.1.6 以降、CLDR ベースの複数形選択書式がより単純な文法で使用出来るようになりました。 これは複雑な複数形の規則を持つ言語のために便利です。

この複数形の選択書式の規則は、英語の場合、次のように書くことが出来ます。

Yii::t('test', 'cucumber|cucumbers', 1);
Yii::t('test', 'cucumber|cucumbers', 2);
Yii::t('test', 'cucumber|cucumbers', 0);

上記のコードは次のように翻訳されます。

cucumber
cucumbers
cucumbers

数値を含めたい場合は、次のように書くことが出来ます。

echo Yii::t('test', '{n} cucumber|{n} cucumbers', 1);

ここで {n} は渡された数値を保持する特別なプレースホルダです。 上記のコードは 1 cucumber を表示します。

追加の引数を渡すことも出来ます。

Yii::t('test', '{username} has a cucumber|{username} has {n} cucumbers',
array(5, '{username}' => 'samdark'));

さらに、数値の引数を別のもので置き換えることも出来ます。

function convertNumber($number)
{
    // 数値を言葉に変換
    return $number;
}
 
Yii::t('test', '{n} cucumber|{n} cucumbers',
array(5, '{n}' => convertNumber(5)));

複数形の書式の数は、言語によって異なります。例えば、元のメッセージが以下の通りであるとします。

Yii::t('app', '{n} cucumber|{n} cucumbers', 62);
Yii::t('app', '{n} cucumber|{n} cucumbers', 1.5);
Yii::t('app', '{n} cucumber|{n} cucumbers', 1);
Yii::t('app', '{n} cucumber|{n} cucumbers', 7);

この複数形の書式は、ロシア語に翻訳されると、二つではなく四つの表示形式を持つようになります。

'{n} cucumber|{n} cucumbers' => '{n} огурец|{n} огурца|{n} огурцов|{n} огурца',

そして、表示結果は以下のようになります。

62 огурца
1.5 огурца
1 огурец
7 огурцов

情報: 何個の表示形式をどういう順序で記述すべきかについては、CLDR Language Plural Rules page を参照して下さい。

ファイル翻訳

ファイル翻訳は、CApplication::findLocalizedFile() を呼び出すことで行われます。 翻訳を行うために、ファイルのパスを与えると、メソッドは LocaleID サブディレクトリ下にある同じ名前のファイルを探します。 ファイルが見つかれば、ファイルパスを返します。 見つからない場合、オリジナルのファイルパスを返します。

ファイル翻訳は、主にビューの描画で使用されます。 コントローラかウィジェット内でレンダーメソッドの一つを呼び出した際、ビューファイルは自動的に翻訳されます。 たとえば、ターゲット言語zh_cn で、ソース言語en_us の場合、edit という名前のビューの描画では、ビューファイル protected/views/ControllerID/zh_cn/edit.php を検索します。 ファイルが見つかれば、この翻訳された版が描画に使用されます。 見つからない場合、代わりに protected/views/ControllerID/edit.php によって描画されます。

また、ファイル翻訳は、たとえば、翻訳された画像やロケール依存のデータファイルをロードし、表示するためなど、他の目的のために使用されるかもしれません。

3. 日付と時刻フォーマット

日付と時刻は、国や地域によって異なる書式がしばしば利用されます。 日付と時刻フォーマットの目的は、ロケールに基づき、そのロケールに適した日付や時刻の文字列を生成することです。 Yii は、この問題のために、CDateFormatter を提供します。

CDateFormatter インスタンスは、ターゲットロケールと結びついています。 アプリケーション全体のターゲットロケールに結びついたフォーマッタの取得は、アプリケーションの dateFormatter プロパティを使い、簡単にアクセスできます。

CDateFormatter クラスは主に UNIX タイムスタンプをフォーマットする二つのメソッドを提供します。

  • format: このメソッドは、カスタムパターンに基づき、UNIX タイムスタンプを文字列にフォーマットします (たとえば、$dateFormatter->format('yyyy-MM-dd',$timestamp))。

  • formatDateTime: このメソッドは、ターゲットロケールデータに定義されているパターンに基づき、UNIX タイムスタンプを文字列にフォーマットします (たとえば、日付の short フォーマット、時刻の long フォーマット)。

4. 数値フォーマット

日付と時刻のように、数値も国や地域によって異なる書式を使わなければならない場合があります。 数値フォーマットは、小数フォーマット、通貨フォーマット、パーセンテージフォーマットを含みます。 Yii は、これらのために CNumberFormatter を提供します。

アプリケーション全体のターゲットロケールに結びついた数値フォーマッタは、アプリケーションの numberFormatter プロパティを使って、アクセスできます。

下記メソッドが、integer、double 値のフォーマットのために、 CNumberFormatter によって提供されています。

  • format: このメソッドは、カスタムパターンに基づき、数値を文字列にフォーマットします (たとえば、$numberFormatter->format('#,##0.00',$number))。

  • formatDecimal: このメソッドは、ターゲットロケールデータに定義されている小数パターンに基づき、数値を文字列にフォーマットします。

  • formatCurrency: このメソッドは、ターゲットロケールデータに定義されている通貨パターンに基づき、数値と通貨記号を文字列にフォーマットします。

  • formatPercentage: このメソッドは、ターゲットロケールデータに定義されているパーセンテージパターンに基づき、数値を文字列にフォーマットします。

$Id$

Be the first person to leave a comment

Please to leave your comment.