symfony Forms in Action

第8章 - 国際化とローカライズ

You are currently browsing
the website for symfony 1

Visit the Symfony2 website


About

You are currently reading "symfony Forms in Action" which is licensed under the Creative Commons Attribution-Share Alike 3.0 Unported License license.

Master symfony

Be trained by SensioLabs experts (2 to 6 day sessions -- French or English).
trainings.sensiolabs.com

Books on symfony

Learn more about symfony with the official guides.
books.sensiolabs.com

L'audit Qualité par SensioLabs

200 points de contrôle de votre applicatif web.
audit.sensiolabs.com

Chapter Content

フォームの国際化

翻訳のために使うカタログを指定する

エラーメッセージの国際化

翻訳オブジェクトのカスタマイズ

パラメータとして受容できる翻訳のcallable

Propelのオブジェクトの国際化

ローカライズされたウィジェット

日付セレクタ

国セレクタ

cultureセレクタ

symfony training
Be trained by symfony experts
May 29: Paris (Web Development with Symfony2 - Français)
May 31: Paris (Mastering Symfony2 - Français)
Jun 06: Paris (Introduction to Symfony2 - Français)
Jun 06: Paris (Introduction to Symfony2 - English)
Jun 06: Paris (Going Further with Symfony2 - English)
and more...

Search


powered by google
You are currently browsing "symfony Forms in Action" in Japanese for the 1.1 version - Switch to version: - Switch to language:
Creative Commons License This work is licensed under a Creative Commons Attribution-Share Alike 3.0 Unported License.
This version of symfony is not maintained anymore.
If some of your projects still use this version, consider upgrading as soon as possible.

人気のあるWebアプリケーションの多くはさまざまな言語で利用可能で、時にユーザーのcultureに基づいてカスタマイズされます。symfonyはこれらの機能の管理を楽にする組み込みのフレームワークを搭載しています(symfony bookの"国際化と ローカライズ"の章を参照)。

フォームフレームワークはユーザーのインターフェイス用の組み込みサポートを備えており国際化オブジェクトの管理を楽にする方法を提供します。

フォームの国際化

symfonyのフォームはデフォルトで国際化が可能です。翻訳ファイルを編集することでラベルヘルパーテキスト、とエラーメッセージを翻訳できます。これらはXLIFFgettext、もしくはsymfonyがサポートするその他のフォーマットです。

リスト8-1は以前の章で開発したコンタクトフォームを示します。

リスト8-1 - コンタクトフォーム

class ContactForm extends sfForm
{
  public function configure()
  {
    $this->setWidgets(array(
      'name'  => new sfWidgetFormInput(),    // デフォルトのラベルは"Name"
      'email' => new sfWidgetFormInput(),    // デフォルトのラベルは"Email"
      'body'  => new sfWidgetFormTextarea(), // デフォルトのラベルは"Body"
    ));
 
    // emailのウィジェットのラベルを変更する
    $this->widgetSchema->setLabel('email', 'Email address');
  }
}

リスト8-2で示されるようにラベルのフランス語訳をXLIFFで定義します。

リスト8-2 - XLIFF翻訳ファイル

// apps/frontend/i18n/messages.fr.xml
<?xml version="1.0" ?>
<xliff version="1.0">
  <file original="global" source-language="en" datatype="plaintext">
    <body>
      <trans-unit>
        <source>Name</source>
        <target>Nom</target>
      </trans-unit>
      <trans-unit>
        <source>Email address</source>
        <target>Adresse email</target>
      </trans-unit>
      <trans-unit>
        <source>Body</source>
        <target>Message</target>
      </trans-unit>
    </body>
  </file>
</xliff>

翻訳のために使うカタログを指定する

symfonyの国際化フレームワークの機能を利用する場合 (http://www.symfony-project.org/book/1_1/13-I18n-and-L10n#Managing%20Dictionaries)、フォームを特定のカタログにバインドできます。リスト8-3において、ContactFormフォームをcontact_formカタログに関連づけします。ですので、フォーム要素の翻訳はcontact_form.fr.xmlファイルで捜索されます。

リスト8-3 - 翻訳カタログのカスタマイズ

class ContactForm extends sfForm
{
  public function configure()
  {
    // ...
 
    $this->widgetSchema->getFormFormatter()->setTranslationCatalogue('contact_form');
  }
}

カタログを利用することで例えばフォームごとに1つのファイルを使用する翻訳の編成がよりベターになります。

エラーメッセージの国際化

時々、エラーメッセージにはユーザーによって投稿された値が埋め込まれます(例えば、"Eメールアドレスのuser@domainは有効ではありません。")。これをフォームクラスの中でカスタマイズされたエラーメッセージを定義してユーザーが投稿した値を簡単に利用できることを2章ですでに見ました。これらの参照は%parameter_name%のパターンに従います。

リスト8-4はこの原則をコンタクトフォームのnameフィールドに適用する方法を示しています。

リスト8-4 - エラーメッセージの国際化

class ContactForm extends sfForm
{
  public function configure()
  {
    // ...
 
    $this->validatorSchema['name'] = new sfValidatorEmail(
      array('min_length' => 2, 'max_length' => 45),
      array('min_length' => 'Name "%value%" must be at least %min_length% characters.',
            'max_length' => 'Name "%value%" must not exceed %max_length% characters.',
      ),
    );
  }
}

リスト8-5で示されるようにXLIFFファイルを編集することでこれらのエラーメッセージを翻訳できます。

リスト8-5 - エラーメッセージ用のXLIFF翻訳ファイル

<trans-unit>
  <source>Name "%value%" must be at least %min_length% characters</source>
  <target>Le nom "%value%" doit comporter un minimum de %min_length% caractères</target>
</trans-unit>
<trans-unit>
  <source>Name "%value%" must not exceed %max_length% characters</source>
  <target>Le nom "%value%" ne peut comporter plus de %max_length% caractères</target>
</trans-unit>

翻訳オブジェクトのカスタマイズ

symfonyの国際化フレームワーク無しでsymfonyのフォームフレームワークを使いたい場合、翻訳オブジェクトを提供する必要があります。

翻訳オブジェクトはPHPの単なるcallableです。これは次の3つのものの1つです:

PHPのcallableは関数もしくはメソッドのインスタンスへの参照です。これはis_callable()関数に渡されるときにtrueを返すPHP変数でもあります。

リスト8-6で示されるクラスによって提供される独自の国際化メカニズムをすでに持つプロジェクトをマイグレートしなければならない場合を考えてみましょう。

リスト8-6 - カスタムの国際化クラス

class myI18n
{
  static protected $default_culture = 'en';
  static protected $messages = array('fr' => array(
    'Name'    => 'Nom',
    'Email'   => 'Courrier électronique',
    'Subject' => 'Sujet',
    'Body'    => 'Message',
  )); 
 
  static public function translateText($text)
  {
    $culture = isset($_SESSION['culture']) ? $_SESSION['culture'] : self::$default_culture; 
    if (array_key_exists($culture, self::$messages)
        && array_key_exists($text, self::$messages[$culture]))
    {
      return self::$messages[$_SESSION['culture']][$text];
    }
    return $text;
  }
}
 
// クラスの使い方
$myI18n = new myI18n();
 
$_SESSION['culture'] = 'en';
echo $myI18n->translateText('Subject'); // => display "Subject"
 
$_SESSION['culture'] = 'fr';
echo $myI18n->translateText('Subject'); // => display "Sujet"

リスト8-7で示されるようにそれぞれのフォームはフォームの要素の国際化を管理する独自のcallableを定義できます。

リスト8-7 - フォームのための国際化メソッドをオーバーライドする

class ContactForm extends sfForm
{
  public function configure()
  {
    // ...
    $this->widgetSchema->getFormFormatter()->setTranslationCallable(array(new myI18n(), 'translateText'));
  }
}

パラメータとして受容できる翻訳のcallable

翻訳のcallableは3つの引数を取ります:

下記のコードは翻訳のcallableを呼び出すためにsfFormWidgetSchemaFormatter::translate()メソッドによって使われる呼び出しです:

return call_user_func(self::$translationCallable, $subject, $parameters, $catalogue);

self::$translationCallableは翻訳のcallableへの参照です。ですので、以前のコードは下記のものと同等です:

$myI18n->translateText($subject, $parameters, $catalogue);

下記のコードはこれらの追加の引数をサポートするMyI18nクラスのアップデートされたバージョンです:

class myI18n
{
  static protected $default_culture = 'en';
  static protected $messages = array('fr' => array(
    'messages' => array(
      'Name'    => 'Nom',
      'Email'   => 'Courrier électronique',
      'Subject' => 'Sujet',
      'Body'    => 'Message',
    ),
  ));
 
  static public function translateText($text, $arguments = array(), $catalogue = 'messages')
  {
    $culture = isset($_SESSION['culture']) ? $_SESSION['culture'] : self::$default_culture; 
    if (array_key_exists($culture, self::$messages) &&
        array_key_exists($messages, self::$messages[$culture] &&
        array_key_exists($text, self::$messages[$culture][$messages]))
    {   
      $text = self::$messages[$_SESSION['culture']][$messages][$text];
      $text = strtr($text, $arguments);
    }   
    return $text;
  }
}

Propelのオブジェクトの国際化

フォームフレームワークは国際化されたPropelオブジェクト用の組み込みサポート機能を持ちます。これが動作する方法を説明するために国際化されたモデルの例を見てみましょう:

propel:
  article:
    id:
    author:     varchar(255)
    created_at:
  article_i18n:
    title:      varchar(255)
    content:    longvarchar

次のコマンドでPropelのクラスと関連するフォームクラスを生成できます:

$ php symfony build:model
$ php symfony build:forms

これらのコマンドはsymfonyのプロジェクトディレクトリの中で次のようなファイルを生成します:

lib/
  form/
    ArticleForm.class.php
    ArticleI18nForm.class.php
    BaseFormPropel.class.php
  model/
    Article.php
    ArticlePeer.php
    ArticleI18n.php
    ArticleI18nPeer.php

リスト8-8は同じフォームでフランス語と英語の記事を編集できるようにするためにArticleFormを設定する方法を示しています。

リスト8-8 - 国際化されたPropelオブジェクト用の国際化フォーム

class ArticleForm extends BaseArticleForm
{
  public function configure()
  {
    $this->embedI18n(array('en', 'fr'));
  }
}

リスト8-9で示されるように次のコードをconfigure()メソッドに追加することでフォームの言語ラベルをカスタマイズすることもできます。

リスト8-9 - 言語のラベルのカスタマイズ

$this->widgetSchema->setLabel('en', 'English');
$this->widgetSchema->setLabel('fr', 'French');

図8-1 - 国際化されたPropelのフォーム

国際化されたPropelのフォーム

これでお終いです。フォームオブジェクトのsave()メソッドを呼び出すとき、関連するPropelオブジェクトと国際化オブジェクトは自動的に保存されます。

ローカライズされたウィジェット

symfonyのフォームフレームワークは国際化を"認識する"(aware)いくつかのウィジェットを搭載しています。ユーザーのcultureに従ってウィジェットをローカライズするためにこれらを使うことができます。

日付セレクタ

日付をローカライズするために利用できるウィジェットは下記の通りです:

国セレクタ

sfWidgetFormI18nSelectCountryウィジェットは国のリストで満たされた選択ボックスを表示します。国の名前は指定された言語に翻訳されます:

$this->widgetSchema['country'] = new sfWidgetFormI18nSelectCountry(array('culture' => 'fr'));

countriesオプションのおかげで、選択ボックス内の国を制限することもできます:

$countries = array('fr', 'en', 'es', 'de', 'nl');
$this->widgetSchema['country'] = new sfWidgetFormI18nSelectCountry(array('culture'   => 'fr',
                                                                         'countries' => $countries));

cultureセレクタ

sfWidgetFormI18nSelectLanguageウィジェットは言語の一覧で満たされた選択ボックスを表示します。言語の名前は指定された言語に翻訳されます:

$this->widgetSchema['language'] = new sfWidgetFormI18nSelectLanguage(array('culture' => 'fr'));

languagesオプションのおかげで、選択ボックスの言語を制限することもできます:

$languages = array('fr', 'en', 'es', 'de', 'nl');
$this->widgetSchema['language'] = new sfWidgetFormI18nSelectLanguage(array('culture'   => 'fr',
                                                                           'languages' => $languages));

Questions & Feedback

If you find a typo or an error, please register and open a ticket.

If you need support or have a technical question, please post to the official user mailing-list.