Ruby-Locale for Ruby on Rails HOWTO
ruby-locale-rails-howto
サンプルアプリケーション
ファイルの編集
以下の順番でファイルを編集していきます。
I18nモジュールの初期化
まずは、他のRails i18nアプリケーション同様にI18nモジュールの初期化を行います。
# in config/initializer/locale.rb
# 翻訳ファイルが置かれているディレクトリを指定します。
I18n.load_path += Dir[ File.join(RAILS_ROOT, 'lib', 'locale', '*.{rb,yml}') ]
# このアプリケーションがサポートしているロケールを指定します。
# これはRuby-Locale for Ruby on Railsが提供する追加機能です。
# 指定がない場合は、特にロケールを限定することなく、WWWブラウザから与えられたロケール情報を
# 値として使用します。
# リソースを適切に絞り込むためにはこの設定が必須です。
I18n.supported_locales = Dir[ File.join(RAILS_ROOT, 'lib', 'locale', '*.{rb,yml}') ].collect{|v| File.basename(v, ".*")}.uniq
# デフォルトのロケールを設定します。"en"以外を指定したい場合のみ、この値を使用します。
# Ruby-Localeでは優先度のもっとも低いロケールとしてこの値が使われます。
I18n.default_locale = "pt-BR"
1言語のみのアプリとして使用する場合は、I18n.supported_locales, I18n.default_localeにそれぞれ、ターゲットとなる言語のみを記述します。
config/environment.rb
Ruby-Locale, Ruby-Locale for Ruby on Railsのライブラリを読み込みます。
Rails::Initializer.run do |config| : : config.gem 'locale', :version => '2.0.4' config.gem 'locale_rails' end
locale_railsはRailsのバージョンに依存しており、Railsのバージョンによって動作しないことが多いです。そこで使用するバージョンを固定することをお奨めします。 どのRailsバージョンで動作するか、は各ライブラリのREADME.rdocのSupport Matrixを参照してください。
ApplicationController
基本的に、AppicationControllerですべきことは何もありません。 I18n rails guideでは、以下のようにロケールを設定していますがこのような設定は不要です。
# 不要です。
# app/controllers/application.rb
class ApplicationController < ActionController::Base
before_filter :set_locale
def set_locale
I18n.locale = params[:locale]
end
end
実際は、上記の設定と同様のことを本ライブラリ内部で実施しています。
この初期化処理により、ユーザからのリクエストごとにロケールが決まるのですが、その前後で何かを実行したい、と言う場合は(before|after)_init_localeを使用してください。 以下にafter_init_localeを使った例を示します。
# app/controllers/application.rb
class ApplicationController < ActionController::Base
def init_i18n
OtherL10n.locale = Locale.candidates
end
after_init_locale :init_i18n
end
なお、上記の例では、OtherL10n.というライブラリにLocale.candidates(後述します)を使って候補となるロケールを設定する例です。
after_init_localeは、Ruby on Railsに依存しないローカライズされたライブラリ等を使用するときのロケールの初期化に使うとよいでしょう。
Views/ActionMailer
I18n.t等、Rails I18nが提供するメソッドを使うとリクエストごとに適切なロケールでメッセージを表示できます。
# app/views/home/index.html.erb <h1><%=t :hello_world %></h1>
ローカライズドテンプレートの使用
foo_ja.hml.erb, foo_ja_JP.html.erbと言う風にテンプレート自体を英語の元ファイルから分離させてしまうこともできます。例えば以下のようにファイルを配置します。
/app/views/blog/list.html.erb /app/views/blog/list_ja.html.erb /app/views/blog/list_ja_JP.html.erb
このケースでは日本語(jaロケール)の場合のみ、2番目のファイルが呼び出され、それ以外の時は1番目のファイルが呼び出されます。 render_partialの場合は、_foo.html.erb, _foo_ja.html.erbとすると、日本語の場合のみ_foo_ja.html.erbが呼び出されます。
ローカライズドルーティング
":lang"をconfig/routes.rbで使用することでルーティング時にロケールを指定することができます。
# config/routes.rb ActionController::Routing::Routes.draw do |map| # Localized Routing. map.connect '/:lang/:controller/:action/:id' map.connect '/:lang/:controller/:action/:id.:format' end
この:langの値は、param[:lang]として本ライブラリ内の最優先のロケールとして使用されます。
上記の記述をすることで、
http://www.foobar.com/ja_JP/foos/show http://www.foobar.com/fr/foos/show
など、URLを言語ごとに分けてアクセスすることができます。
Viewの方はconfig/routes.rbを上記のように指定した上で、以下のように:langを指定することで上記のURLを生成することができます。
url = foos_path(:lang => lang) link_to "Click", :controller => :foos, :action => :show, :lang => lang
ロケール情報の取得
ユーザリクエストごとのロケール情報を取得するには、I18n.localeかLocale.candidatesを使います。
それぞれ、以下のような機能を持ちます。
I18n.locale
I18n.localeはRails2.2 I18n APIが提供するI18n.localeメソッドを拡張したもので、ユーザリクエストのロケール情報のうち、もっとも優先度の高い情報を1つだけ返します。
# app/views/home/index.html.erb <div><%= I18n.locale.inspect %></div>
返す値はRuby on Rails 2.2標準の文字列形式ではなく、Locale::Tag::Rfcオブジェクト(RFC4646, ja-Hira-JP-VARIANTS、通常はja-JPなどの<language>-<REGION>の形式)です。これにより、CLDR形式、POSIX形式等に変換したり、language部分のみを取得したりすることが可能です。 単に文字列として扱うこともできますので、従来のRails 2.2 I18n APIを利用したプラグイン等でもそのまま利用できます。
Locale.candidates
Locale.candidatesは考えられる候補すべてをLocale::TagListの形式で返します。一番最後の候補としてI18n.default_localeで指定された値が返ります。
Locale.candidatesはデフォルトでCommon形式(ja_Hira_JP_VARIANTS)を返しますが引数で、:simple, :common, :rfc, :cldrを選択することができます。
# app/views/home/index.html.erb <div><%= Locale.candidates.inspect %></div>
I18n.supported_localesを指定することで、I18n.localeの結果の値をそのまま使えばアプリケーションが想定したロケールを取得できるはずですが、I18n.supported_localesを想定しない場合や何らかの理由で他の候補も使用する場合はLocale.candidatesの中から候補を選ぶとよいでしょう。
Locale.candidates.each do |lang|
path = "/foo/bar/locale/#{lang}/foo.rb"
if File.exist?(path)
File.open(path)
:
:
break
end
end
なお、I18n.localeはLocale.candidates(:type => :rfc)[0]と同等です。
Railsプラグイン、ライブラリのローカライズの際の注意点
I18n.localeはI18n.supported_localesで定義されたロケールの範囲で値を返します。
このI18n.supported_localesは通常アプリケーションが設定するもので、I18n.localeは、そのアプリケーションのサポートしているロケールの範囲でもっとも優先度の高いロケールIDを返します。
ここで注意していただきたいのですが、この値がRailsプラグイン・ライブラリがサポートできる範囲と同じかどうかというのは要検討だ、ということです。
たとえば、アプリケーション自体がサポートしているロケールとして、I18n.localeがja-JPを返したからと言って、そのプラグインがja-JPをサポートしていないのであれば、その部分だけローカライズ処理に失敗するはずです。
そこで、Locale.candidatesを使って、プラグイン・ライブラリがサポートできるロケールまでフォールバックすると良いでしょう。
ブラウザからのアクセスとCookieへの情報格納
ロケール情報は、QUERY_STRINGのlangの値 > Cookieのlangの値 > WWWブラウザが返すHTTP_ACCEPT_LANGUAGE環境変数 > "en"(英語) の順番で決まります。QUERY_STRINGのlangの値とは、例えば、http://foo/?lang=ja という感じでURLの最後に追加する方法です。 QUERY_STRINGのlangの値やCookieのlangの値はアプリケーション側で適切に設定する必要があります。
アプリケーションを作って最初に確認するときは、http://foo/?lang=ja とアクセスしてみれば日本語になっていることがわかるでしょう。
また、ここでは上記のようにQUERY_STRINGからlangを受け取りCookieに設定して返す機能を紹介します。
Session情報を使う場合はそちらに設定しても良いかもしれません。
class BlogController < ApplicationController
:
:
def cookie_locale
cookies["lang"] = @params["id"]
redirect_to :action => 'list'
end
end
あとは、View側からcoolie_localeをアクションとして呼び出すようにします。
<%= link_to "Set Locale to japanese", :action => "cookie_locale", :id => "ja" %>
キャッシュについて
RailsにはPage/Action/Fragmentの3種類のキャッシュがありますが、Action/Fragmentについてはロケール毎に管理するように拡張されており、特に(本ライブラリを使わない)アプリケーションと同様にRailsのキャッシュ機能を使用することができます。
Pageキャッシュについてはロケールの特定をhttpサーバ、Rails双方でうまく連携をとる必要があるため、今のところ上手な解決策が思いつきません。何かいいアイデアがある方は教えてくださいませ。
ChangeLog
- 2008-11-24: 新規作成
キーワード:
参照:[Ruby-Locale for Ruby on Rails] [Ruby on RailsでRuby-GetText-Packageを使う (Rails-2.3.2以降)]