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

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

ヒント: ユーザー(ブラウザの設定で定められている)により優先された言語により、 ターゲット言語を設定したいかもしれません。その場合、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 タイムスタンプをフォーマットする 2 つのメソッドを提供します。

  • 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: topics.i18n.txt 2890 2011-01-18 15:58:34Z qiang.xue $

Be the first person to leave a comment

Please to leave your comment.