RoR: i18n_template_selector
[ English | Japanese ]

News

2007/11/10

  • RoR: i18n_template_selectorのページを作成しました。

Introduction

RoRには(少なくとも1.2.5では)残念ながら国際化の枠組みがありません。そのため、国際化を実現しようという有志によって数多くのプラグインが開発されています。現在のところ、その多くがruby-gettextをはじめとする、gettextをもちいた(あるいはそれに準じた)アプローチを採用しています。

MVCフレームワークにおける国際化があるべき姿については、おそらく様々な議論がなされてきたのではないかと思います。私は特にそれらの議論に詳しい訳ではありませんが(というか全く知らない)、個人的にMVCとgettext(あるいはそれに準じたアプローチ)が混在することは原則としてあり得ないと考えています。それは、以下のような理由によります。

  • 言語によって切り替える必要があるのは、ほぼ出力部分である。
  • C(ontroller)にgettextが介入するのは、出力の一部をC(ontroller)で制御すると云うことであるから、MVCから逸脱している。
  • V(iew)は原則としてほぼ出力部分だけで構成されるから、言語によって出力を切り替えるのであれば、その影響範囲はほぼ全域にわたるはずである。したがって、gettextによるアプローチは効率が悪い。
  • M(odel)で言語依存なことはあまりないと思われる(もし言語依存なコードが必要であれば、ここはgettextを使ってもいいかも)。

i18n_template_selectorは、言語によってV(iew)のテンプレート自体を切り替えようというアプローチによってRoRの国際化を試みています。

Features

i18n_template_selectorは以下のような特徴を持っています。

  • インストールするだけで機能します。
  • 既存のアプリケーションはそのまま稼働します。すなわち、徐々にテンプレートを追加して国際化を進めることが可能です。
  • 簡単なコードで、ユーザによる言語切り替えも可能です。

Environment

i18n_template_selectorは、少なくともRuby on Rails 1.2.5での動作が確認されています。

API & Basic Usage

i18n_template_selectorで追加されるメソッドは、AbstractRequest#accept_languagesだけです。これは、AbstractRequest内にインスタンス変数として保持される言語コードの配列を返します。たとえば、以下のような感じです。

request.accept_languages
=> [ "ja", "ko", "en" ]

配列内は、優先度の高い言語コードから順に並んでいると解釈されます。なお、最初の呼び出し時にはHTTPヘッダ内のAccept-Languageに従って初期化されます。

テンプレートには、通常のaction.rhtmlに加えてaction.lang.rhtmlを準備します。実際にrenderが呼ばれるとき、これらのテンプレートはrequest.accept_languagesに従って自動的に選択されます。例えば、WelcomeController#indexに対して、view/welcomeに以下のテンプレートが存在していたとしましょう。

index.en.rhtml
index.ja.rhtml
index.rhtml

ここで、request.accept_languagesが前述の内容だったとすると、優先度が最も高いjaに対応するindex.ja.rhtmlを利用します。index.ja.rhtmlが存在しない場合は、順番にたどってindex.en.rhtmlが採用されることになります。request.accept_languages内のすべての言語に対して対応するテンプレートが存在しない場合は、通常通りindex.rhtmlが利用されることになります。

Tips

ユーザが言語を設定できるようにしたい

request.accept_languagesを編集することで可能です。たとえば、langというQuery Stringで変更できるようにするには、以下のようにすればいいでしょう。

class ApplicationController < ActionController::Base
  before_filter :set_lang

  private

  def set_lang
    session[:lang] = params[:lang] if params[:lang]
    request.accept_languages.unshift(session[:lang]) if session[:lang]
  end
end

デフォルトの言語を規定したい

これも上記と同様にrequest.accept_languagesを編集すれば可能です。

class ApplicationController < ActionController::Base
  before_filter :set_default_lang

  private

  def set_default_lang
    request.accept_languages.push("en")
  end
end

これで、Accept-Languageで設定された言語に対応するテンプレートが存在しなくても、action.en.rhtmlを準備しておけばそれが利用されます。この場合、index.rhtmlは準備する必要はありません。

Download & Install

Subversion経由でのインストールは準備中です。暫定的に、ここから取得して、RAILS_ROOT/vendor/plugins以下に展開してください。