海外IT企業で働いていた純日本人エンジニアがいろいろと考えてみる。

i18nしてますか? (symfonyその1)

»

Creative Commons License This work is licensed under Creative Commons Attribution-Share Alike 3.0 Unported License.

 どうも、鹿島和郎(かしまかずお)です。日本では食欲の秋、プログラムの秋などとよくいわれますが、食欲旺盛(おうせい)なプログラマの皆さまはいかがお過ごしでしょうか。

 わたしの方はというと、エンジニアライフでコラムを書いている方々が集まるオフ会のようなものが先週末にあり参加してきました。その際に

 「みんなネタコラムばっかりで、技術的な事を書いている人ってほとんどいないですよね」「(一同うなずく)」

なんていう場面があったのですが、そんな逆風にも負けずに今回も技術ネタでいきます。内容は前回予告したとおり2回に渡ってsymfonyでのi18nについて説明していきます。具体的には以下の内容を説明します。

  • 設定ファイルの変更
  • URLにカルチャーを含める設定
  • ソースコードの修正
  • 言語切り替えメニューの追加

■設定変更(settings.yml)

 取りあえずおなじみのfrontend/backendという2つのアプリケーションがあると仮定します。

 apps/frontend/config/settings.ymlに対する変更点としては以下の3つです。

  • i18nの有効化
  • デフォルトのカルチャーの設定
  • I18Nヘルパークラスを有効にする

 i18nの有効化は、単に1行設定を書くだけです。おまじない的なものなので、説明は省略します。

 デフォルトのカルチャーは、ハリウッドを目指すのであればen_US、まずは国内向けで展開するのであればja_JPです。

 ここまでは問題ないかと思いますが、3番目のI18Nヘルパークラスに関して少し説明します。

 I18Nヘルパークラスはその名の通り、i18n関係の処理をまとめたヘルパークラスで、具体的には、後述する__()などがI18Nヘルパークラスで提供される機能です。settings.ymlでI18Nヘルパークラスで有効にすると、すべてのページ(テンプレート)で使えます。settings.ymlで有効にしない場合は、I18Nヘルパークラスを使う際に以下のコードを書く必要があります。

<?php use_helper('I18N') ?>

 settings.ymlの最終的な変更点は以下の通りです。

# apps/frontend/config/settings.yml
all:
  .settings:
    i18n: true
    default_culture: ja_JP  # 又はen_US
    standard_helpers: [Partial, Cache, I18N]

■URLにカルチャー名を含める設定(routing.yml)

 分かりにくい見出しですみません。要するに以下のようなURLでアクセスして言語が切り替わる設定です。

  • http://www.example.com/i18ntest/frontend.php/ja/
  • http://www.example.com/i18ntest/frontend.php/en/

 具体的には、routing.ymlの"homepage"以外のエントリに対して、以下のように:sf_cultureという文字列を追加します。

# apps/frontend/config/routing.yml
# 変更前
default_index
  url:    /:module
  param:  { action: index }

default:
  url:    /:module/:action/*
# 変更後
default_index
  url:    /:sf_culture/:module
  param:  { action: index }

default:
  url:    /:sf_culture/:module/:action/*

 また、各国語用のホームページ(localized_homepage)も用意します。

localized_homepage:
  url:    /:sf_culture/
  param:  { module: default, action: index }
  requirements:
    sf_culture: (?:ja|en)

■ソースコードの修正

 ここまでで、事前準備は大体完了しました。後はソースコードを少し修正する必要があります。もう一息ですのでお付き合いください。

 コードの修正内容は、基本的にはsymfonyチュートリアルの以下のページに載っているのものをそのまま使えばOKですが、違いがある場合のみ説明します。

 Day 19: Internationalization and Localization (日本語英語

○myUser.class.php

 まずはmyUser.class.phpに初回アクセスかどうかを返すメソッド(isFirstRequest)を追加します。

 実装内容は、チュートリアルのページの apps/frontend/lib/myUser.class.php と同じで以下の通りです。

class myUser extends sfBasicSecurityUser
{
  public function isFirstRequest($boolean = null)
  {
    if (is_null($boolean))
    {
      return $this->getAttribute('first_request', true);
    }
    $this->setAttribute('first_request', $boolean);
  }
}

○action.class.php

 次に、routing.ymlの"homepage"で呼び出されるモジュールを修正します。わたしの場合、routing.ymlは以下のようになっています。

# routing.yml
homepage:
  url:   /
  param: { module: default, action: index }

 従って、修正するのは以下のファイルです。

 apps/frontend/modules/default/actions/action.class.php

 もしこのファイルが存在しない場合、symfonyのインストールされているディレクトリからコピーしてきて使いましょう。

cp -R /usr/share/pear/symfony/controller/default/ apps/frontend/modules/

 修正内容としては、初回リクエストの場合にはカルチャーをセットし、それ以外の場合はセットされているカルチャーの値に従って、localized_homepageを表示するようにします。

 実装内容は、チュートリアルのページの apps/frontend/modules/job/actions/actions.class.php と同じで以下の通りです。

public function executeIndex(sfWebRequest $request)
{
  if (!$request->getParameter('sf_culture'))
  {
    if ($this->getUser()->isFirstRequest())
    {
      $culture = $request->getPreferredCulture(array('ja', 'en'));
      $this->getUser()->setCulture($culture);
      $this->getUser()->isFirstRequest(false);
    }
    else
    {
      $culture = $this->getUser()->getCulture();
    }
    $this->redirect('localized_homepage');
  }
}

○ここまでで動作確認

 ブラウザで以下のURLにアクセスすると、

 http://www.example.com/i18ntest/frontend.php/

自動的に以下のURLにリダイレクトされればOKです。

 http://www.example.com/i18ntest/frontend.php/ja/

■言語切り替えメニューの追加

 これで大体完了なのですが、もうちょっと頑張って、言語切り替えのプルダウンメニューを追加します。行うことは、基本的には本家チュートリアルの通りです。

○sfFormExtraPlugin のインストール

 これは問題ないでしょう。以下の通りインストールします。

$ php symfony plugin:install sfFormExtraPlugin

 ※実はこのプラグインにはごく最近までバグがあったのですが、最近は直ったようです。

○languageコンポーネントの作成

 言語切り替えメニューは「コンポーネント」として実装します。その為に、最初にlanguageという名前のモジュールを作成します。

$ php symfony generate:module frontend language

 次に、apps/frontend/modules/language/actions/components.class.php というファイルを作成し、コンポーネントを実装します。チュートリアルのページの内容とほぼ同様ですが、今回対応するのは英語(en)と日本語(ja)ですので、コードは以下のようになります。

<?php
class languageComponents extends sfComponents
{
  public function executeLanguage(sfWebRequest $request)
  {
    $this->form = new sfFormLanguage(
      $this->getUser(),
      array('languages' => array('ja', 'en'))
    );
  }
}
?>

 最後に、言語切り替え用のフォームを部品化します。パーシャルと同様の命名規則で、_language.php というファイルを作成します。

 実装内容は、チュートリアルのページの apps/frontend/modules/language/templates/_language.php と同じで以下の通りです。

<form action="<?php echo url_for('change_language') ?>">
  <?php echo $form ?><input type="submit" value="ok" />
</form>

○アクションの作成

 あとは、言語切替用のプルダウンの値が変更されたときに呼び出されるアクションを作成します。

 実装内容は、チュートリアルのページの apps/frontend/modules/language/actions/actions.class.php とほぼ同様ですが、ここでも対応するのは英語(en)と日本語(ja)ですので、コードは以下のようになります。

// apps/frontend/modules/language/actions/actions.class.php
class languageActions extends sfActions
{
  public function executeChangeLanguage(sfWebRequest $request)
  {
    $form = new sfFormLanguage(
      $this->getUser(),
      array('languages' => array('en', 'ja'))
    );
    $form->process($request);
    return $this->redirect('localized_homepage');
  }
}

 次に、apps/frontend/config/routing.yml に以下のエントリを追加し、change_languageにアクセスされたときに、上で作成したアクションが呼び出されるようにします。

change_language:
  url:   /change_language
  param: { module: language, action: changeLanguage }

○layout.phpの編集

 あとは apps/frontend/templates/layout.php の好きな場所に以下1行を追加し、どのページでも言語が切り替えられるようにします。

    <?php include_component('language', 'language') ?>

■動作確認

 今回のテストサイト用に、以下のようなトップページを作成しました。

<!-- apps/frontend/modules/default/templates/indexSuccess.php -->
<h1>Welcome to my i18n test page.</h1>
Go to <?php echo link_to('list page', 'post/index') ?> 

 http://www.example.com/i18ntest/frontend.php/

にアクセスすると、

 http://www.example.com/i18ntest/frontend.php/ja/

にリダイレクトされ、以下のようなページが表示されるはずです。

 I18nsymfonytop

 Languageが「日本語」になっているのが分かるかと思います。

■まとめ

 ここまででsymfonyでのi18nの設定関連はほとんど完了しました。次回は、ソースコード中のメッセージをメッセージファイルに抜き出して、それを翻訳するところを説明します。

 それではまた。

Comment(0)

コメント

コメントを投稿する