ユーザーインターフェイスの翻訳
一口に「国際化機能」と言った時、漠然と思い浮かぶのは文面の翻訳でしょう。これは、XMLファイルで言語別の内容を記述し整理することで実現します。XLIFF(XML Localization Interchange File Format)ファイルと言います。具体的には「messages.<言語名>.xml」という名前でアプリケーションフォルダ内の「i18n」フォルダに配置され、次のような内容です。
<?xml version="1.0" ?> <xliff version="1.0"> <file orginal="global" source-language="en_US" datatype="plaintext"> (元テキストの言語を設定) <body> <trans-unit id="1"> (この括りで、原文と訳文をセットにする。 idはXLIFF作成ツール等によってつけられるユニークな識別属性) <source>Welcome to our website.</source> (原文。「__()」ヘルパー(後述)内の原文がこの要素内の原文と 一致すれば、その下の<target>要素内の訳文に変換される) <target>私たちのウェブサイトへようこそ。</target> (訳文) </trans-unit> <trans-unit id="2"> <source>LATEST NEWS </source> <target>最新ニュース </target> </trans-unit> </body> </file> </xliff>
<file>要素の属性については次のとおりです。
| 属性 | 内容 |
| original | 原文ファイルの場所。この場合の「global」はそのアプリケーション全体という意味 |
| source-language | <source>要素内の言語 |
| datatype | 原文ファイルのテキストの種類。plaintext(プレーンテキスト)の他にhtml(HTML)やphp(PHP)などがある |
このファイルはテンプレートにおいて__()関数が呼び出された時に参照されます。例示したファイルは、下記のメッセージを日本語で表示するためのもので、
Welcome to our website. LATEST NEWS ...
これを次のようにして活用します。
<?php use_helper('I18N') ?> (I18Nヘルパーの使用を宣言) <?php echo __('Welcome to our website.') ?> (一つ目のtrans-unitに対応) <?php echo __("LATEST NEWS ") ?> (二つ目のtrans-unitに対応) ...
また、下記のように文字列中に「%1%」などを用い置き換えることも可能です。
<?php __('Your payment is %1%. Are you sure?', array('%1%' => $a->getPayment()) ) ?>
<?php echo format_number_choice( '[0]Nobody is logged|[1]There is 1 person logged|(1,+Inf]There are%1% persons logged', array('%1%' => count_logged()), count_logged()) ?>
__()ヘルパーと同様です。第1引数のテキストの区切りの最初にある括弧と数字の組み合わせは、そのテキストが選ばれる条件となる(第3引数が示す数の)範囲を示します。上記の例では、
count_logged()が0なら最初のテキストが、1なら2つ目のテキストが、それ以上なら3つめのテキストが選ばれます。他の例を以下に示します。| 表記 | 範囲 |
| [1,5] | 1以上5以下 |
| (1,5) | 1より大きく5未満 |
| {1,5,7,15} | 1・5・7・15のいずれか |
| (5,15] | 5より大きく15以下 |
| [-Inf,5) | 5未満 |
messages.XX.xmlファイルが長すぎる場合などには、テーマに応じた任意の名前(<テーマ名>.<言語名>.xml)でファイルを分割することができます。具体的には、messages.fr.xmlファイルを次のようなファイルに分割して、「i18n/」フォルダに配置します。
- contents.fr.xml
- news.fr.xml
- weather.fr.xml
この場合は__()ヘルパーの第3引数でどのファイルを使うのかを明記します。
<?php echo __('LATEST NEWS', null, 'news(「XXXXX.YY.xml」のXXXXXの部分)') ?>
また、messages.XX.xmlファイルをモジュールごとに、つまり「modules/<モジュール名>/i18n/」フォルダにそれらを配置することもできます。
国際化機能を利用したサンプル
これまで紹介した機能を一部用いて、実際に国際化に対応した簡単なアプリケーションを作成してみます。
国名と言語と現在時刻を表示し、選択ボックスでカルチャを選べる(updateアクション)ようにします。
以下にテンプレートとアクション、XLIFFファイルを示します。
<?php use_helper('I18n', 'Date') ?> <?php echo __('こんにちは!') ?> (XLIFFファイルの<trans-unit id="1">の部分) <br /> <?php echo __('国:').format_country(substr($sf_user->getCulture(),-2)) ?> (id="2"の部分。カルチャの末尾2文字を持ってきている) <br /> <?php echo __('言語:').format_language(substr($sf_user->getCulture(),0,2)) ?> (id="3"の部分。カルチャの先頭2文字を持ってきている) <br /> <?php echo __('ただ今 %1% です', array('%1%' => format_datetime(time()))) ?> (id="4"の部分) <br /> <?php echo form_tag('i18n_test/update') ?> <?php echo select_country_tag('country', 'JP') ?> (国の選択ボックス) <br /> <?php echo select_language_tag('language', 'ja') ?> (言語の選択ボックス) <br /> <?php echo submit_tag('Go') ?> </form>
<?php /** * i18n_test actions. * * @package sym5 * @subpackage i18n_test * @author Your name here * @version SVN: $Id: actions.class.php 2692 2006-11-15 21:03:55Z fabien $ */ class i18n_testActions extends sfActions { /** * Executes index action * */ public function executeIndex() { } public function executeUpdate() { $l = $this->getRequestParameter('language'); $c = $this->getRequestParameter('country'); $this->getUser()->setCulture($l.'_'.$c); $this->redirect('i18n_test/index'); } }
<?xml version="1.0" ?> <xliff version="1.0"> <file orginal="global" source-language="ja_JP" datatype="plaintext"> <body> <trans-unit id="1"> <source>こんにちは!</source> <target>Hello!</target> </trans-unit> <trans-unit id="2"> <source>国:</source> <target>country:</target> </trans-unit> <trans-unit id="3"> <source>言語:</source> <target>language:</target> </trans-unit> <trans-unit id="4"> <source>ただ今 %1% です</source> <target>Today's date is %1%.</target> </trans-unit> </body> </file> </xliff>
結果は次のようになります。英語を選択すると英語が表示されるのが分かります(なお、選択した国と言語の組み合わせが妥当でない場合には例外が発生します)。


また、フォームヘルパーのリストについてはXLIFFファイルなしに既に国際化されているのが分かります。



There are%1% persons logged