RubyのI18nフレームワークでは、Railsアプリケーションの国際化/ローカライズに必要な手段がすべて提供されています。もちろん、さまざまなプラグインや拡張機能を導入してそれ以外の機能を追加しても構いません。詳細についてはrails-i18n gemを参照してください。
1 Ruby on RailsにおけるI18nのしくみ
国際化は何かと複雑な作業です。自然言語には、たとえば単数形/複数形の違いなどひとつとってもさまざまな違いがあり、すべての問題を一度に解決する魔法のようなツールを提供するのは非常に困難です。このため、Rails I18n APIでは以下の点に絞り込んで問題の解決を図っています。
- 基本的に英語およびそれに近い言語に対するサポートを提供する
- それ以外の言語についてもあらゆる要素をカスタマイズおよび拡張可能にする
問題解決の一環として、Railsフレームワーク内のすべての静的文字列 (Active Recordのバリデーションメッセージ、時刻や日付のフォーマットなど)の 国際化部分は既に完了しています 。従って、Railsアプリケーションのこれらの部分の ローカライズ とは、欲しい言語の文字列について翻訳済みの値を定義することを指します。
アプリケーションのコンテンツ(ブログ記事の翻訳など)の保存方法や更新方法をローカライズする場合は、モデルのコンテンツを翻訳するを参照してください。
1.1 ライブラリのアーキテクチャ概観
以上のことから、RubyのI18nのgemは2つに分割されています。
- i18nフレームワークのパブリックAPI - ライブラリの動作を定義するパブリックなメソッドを持つRubyモジュール
- 上記メソッドを実装する、デフォルトの シンプルな (あえてこう呼んでいます) バックエンド
I18nのユーザーとしては、I18nモジュールのパブリックなメソッドにだけアクセスするのが筋ですが、バックエンドの機能についても知っておくと何かと便利です。
Rails備え付けの「シンプルな」バックエンドを、より高性能なものに置き換えることもできます。たとえば訳文データをリレーショナル・データベースやGetText(訳注: Unixの国際化ライブラリの1つ)辞書などに保存できます。詳細についてはこの後のバックエンドを切り替えるを参照してください。
1.2 パブリックI18n API
I18n APIで最も重要なメソッドを以下に示します。
translate # 訳文を参照する localize # DateオブジェクトやTimeオブジェクトを現地のフォーマットに変換する
上のメソッドにはそれぞれ#tと#lという別名メソッドがあるので、以下のように簡潔に書くことができます。
I18n.t 'store.title' I18n.l Time.now
以下の属性については読み取り属性と書き込み属性が使えます。
load_path # カスタム訳文ファイルの場所を示す locale # 現在のロケールの取得と設定 default_locale # デフォルトロケールの取得と設定 available_locales # アプリケーションでの利用が許されるロケールのホワイトリスト enforce_available_locales # ロケールのホワイトリスト化を強制するかどうか(true/false) exception_handler # 異なるexception_handlerを使う backend # 異なるバックエンドを使う
次の章では、わずかな手順でRailsアプリケーションを一から国際化してみましょう。
2 Railsアプリケーションを国際化向けに設定する
RailsアプリケーションでI18nのサポートを導入および実行するには、いくつかの手順を実施するだけで済みます。
2.1 I18nモジュールを設定する
Railsは、 「設定より規約」の哲学に従い、十分に吟味されたデフォルト設定をアプリケーションに対して行います。i18nは文字列のデフォルト訳文を適切に提供します。別の訳文が必要な場合は上書きできます。
config/locales
以下にあるすべての.rb
ファイルと.yml
ファイルは、自動的に 訳文読み込みパス に追加されます。
上記ディレクトリにあるデフォルトのen.yml
ロケールファイルには、サンプルとなる原文・訳文ペアが含まれています。
en: hello: "Hello world"
上の例は、「:en
というロケールでは、 hello というキーは Hello world という文字列に対応付けられる」という意味です。Rails内部の文字列はすべてこのように国際化されています。具体例については、Active Modelの検証(バリデーション)メッセージ一覧(activemodel/lib/active_model/locale/en.yml
ファイル) や日付時刻フォーマット一覧 (activesupport/lib/active_support/locale/en.yml
ファイル) を参照してください。デフォルトの (シンプルな) バックエンドの訳文は、YAMLや標準のRubyハッシュに保存できます。
I18nライブラリでは、 English を デフォルトのロケール として扱います。デフォルトのロケールに他の言語を指定しなかった場合は、訳文の検索に:en
が使われます。
いくつかの議論 を経た結果、Railsのi18nライブラリではロケールキーの扱いについて 実用に則したアプローチ を採用しています。つまり、:en
や:pl
のようないわゆる ロケール (="言語") 部分のみをロケールキーとして採用しました。:en-US
や:en-GB
のような、言語と地域(あるいは方言)を分離した表記法は、ロケールキーとしては使われていません。実際、国際化されたアプリケーションの多くは、:cs
、:th
、:es
(それぞれチェコ語、タイ語、スペイン語) のような言語部分のみをロケール表記として採用しています。しかし、同じ言語グループに属していても、地域による違いが重要になることもあります。端的な例として、:en-US
の通貨記号は$
(ドル)ですが、:en-GB
の通貨記号は£
(ポンド)です。上のように、このような地域ごとの違いを言語から分離することについては何も問題はありません。この場合、"English - United Kingdom"というロケールを:en-GB
辞書に追加することだけが必要です。
訳文読み込みパス (I18n.load_path
) はファイルへのパスの配列であり、自動的に読み込まれます。このパスを設定することで、訳文のディレクトリ構造やファイル命名スキームをカスタマイズできます。
I18のバックエンドは、訳文が初めて参照されるときに遅延読み込みを行います。これにより、訳文を既に公開した後でもバックエンドを他のものに差し替えることができます。
config/application.rb
では次のように、デフォルトのロケールを変更したり訳文読み込みパスを設定したりできます。
config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}')] config.i18n.default_locale = :de
読み込みパスは、訳文の参照前に指定する必要があります。config/application.rb
のイニシャライザのデフォルトロケールを変更するには次のようにします。
# config/initializers/locale.rbファイルの内容: # I18nライブラリに訳文の探索場所を指示する I18n.load_path += Dir[Rails.root.join('lib', 'locale', '*.{rb,yml}')] # アプリケーションでの利用を許可するロケールをホワイトリスト化する I18n.available_locales = [:en, :pt] # ロケールを:en以外に変更する I18n.default_locale = :pt
ただし、アプリケーションのi18nで設定する代わりにI18n.load_paths
に直接追加すると、外部gem由来の訳文はオーバーライドされません。
2.2 リクエスト間でロケールを管理する
ローカライズされたアプリケーションは、将来複数ロケールのサポートが必要になるかもしれません。これを行うためには、各リクエストの冒頭にロケールを設定して、リクエストが持続する間はすべての文字列が指定のロケールで翻訳されるようにしておくべきです。
I18n.locale=
やI18n.with_locale
を使わない場合、すべての訳文でデフォルトのロケールが使用されます。
I18n.locale
の設定がすべてのコントローラで一貫していないと、同じスレッドやプロセスによって処理される以後のリクエストにI18n.locale
が漏出する可能性があります。たとえば、あるPOSTリクエストでI18n.locale = :es
を実行すると、ロケールを設定していないコントローラで以後のすべてのリクエストに効いてしまいます。こうした理由から、I18n.locale =
の代わりに、漏出が発生しないI18n.with_locale
を利用することもできます。
ロケールはApplicationController
のaround_action
で設定できます。
around_action :switch_locale def switch_locale(&action) locale = params[:locale] || I18n.default_locale I18n.with_locale(locale, &action) end
上の例では、ロケールをURLクエリパラメータで設定しているところを示しています(http://example.com/books?locale=pt
など)。このアプローチの場合、http://localhost:3000?locale=pt
でポルトガル語のローカライズを出力し、http://localhost:3000?locale=de
でドイツ語のローカライズを出力するようになります。
ロケールの設定にはさまざまな方法を使えます。
2.2.1 ドメイン名を元にロケールを設定する
その他のオプションの1つとして、アプリケーションが実行されているドメイン名に基いてロケールを設定することもできます。たとえば、www.example.com
にアクセスした場合は (デフォルト) の英語ロケールにし、www.example.es
にアクセスした場合はスペイン語にするという具合です。従って、ここでは トップレベルドメイン名 を使ってロケールを設定します。この方法には以下のような多くの利点があります。
- ロケールがURLの一部として 明確に 示される。
- ユーザーはそのWebページが何語で表示されるのかをすぐ理解できる。
- Railsでの実装はかなりたやすく行える。
- 検索エンジンは、このようにドメイン別に異なる言語のコンテンツが置かれ、しかもドメイン名同士に関連性があるものを優先的に扱っているようです。
このように設定するには、ApplicationController
で以下のように実装します。
around_action :switch_locale def switch_locale(&action) locale = extract_locale_from_tld || I18n.default_locale I18n.with_locale(locale, &action) end # トップレベルドメインからロケールを取得する、なければ+nil+を返す # この動作をローカルPCで行なうためには、 # 127.0.0.1 application.com # 127.0.0.1 application.it # 127.0.0.1 application.pl # /etc/hosts上のように記述する必要がある def extract_locale_from_tld parsed_locale = request.host.split('.').last I18n.available_locales.map(&:to_s).include?(parsed_locale) ? parsed_locale : nil end
ほぼ同じ方法で、サブドメインを使ってロケールを設定することもできます。
# リクエストのサブドメインからロケールを取り出す (http://it.application.local:3000のような形式) # この動作をローカルPCで行なうためには # 127.0.0.1 gr.application.local # /etc/hostsファイルに上のように記述する必要がある def extract_locale_from_subdomain parsed_locale = request.subdomains.first I18n.available_locales.map(&:to_s).include?(parsed_locale) ? parsed_locale : nil end
アプリケーションにロケール切り替えメニューを取り付けるのであれば、以下のような記述が使えるでしょう。
link_to("Deutsch", "#{APP_CONFIG[:deutsch_website_url]}#{request.env['PATH_INFO']}")
ここではAPP_CONFIG[:deutsch_website_url]
の部分にhttp://www.application.de
のような値を設定するとします。
ドメイン名からロケールを取得する方法には前述のメリットがありますが、ドメイン名が変わったときにローカライズ内容まで変えるわけにいかない事情や、変えたくないような事情もあるでしょう。そのような場合に最適な解決法は、URL paramsやリクエストパスにロケールコードを含めることでしょう。
2.2.2 URL paramsを元にロケールを設定する
最も一般的なロケールの設定方法と受け渡し方法は、既に最初の例でI18n.with_locale(params[:locale], &action)
around_action を使ったのと同じように、ロケールをURL paramsに含めることでしょう。この場合、www.example.com/books?locale=ja
やwww.example.com/ja/books
のようなURLを使えます。
このアプローチは、ドメイン名からロケールを取得するのとほぼ同じメリットを得ることができます。これによりアプリケーションはWorld Wide Webに則ってRESTfulを保つことができるからです。ただし、少しだけ実装を追加する必要があります。
params
からロケールを取り出して設定するのは案外簡単です。ロケールをすべてのURLに含めてリクエスト経由で渡せばよい のです。ただし、たとえばlink_to(books_url(locale: I18n.locale))
のような形式ですべてのURLにロケールオプションを直接含める方法はかなり面倒になり、実用的ではありません。
Railsには、こういうときのためにApplicationController#default_url_options
に「URLの動的な決定を集中制御する」ためのインフラが備わっています。これを使うことで、url_for
や、これに依存するヘルパーメソッドの"デフォルト値"を設定できます(この場合、default_url_options
を実装してオーバーライドする必要があります)。
ApplicationController
にも同様の設定を含めることができます。
# app/controllers/application_controller.rb def default_url_options { locale: I18n.locale } end
上のようにすることで、url_for
に依存するすべてのヘルパーメソッド (root_path
やroot_url
などの名前付きメソッドやbooks_path
やbooks_url
などのリソースルーティングを持つヘルパー) では自動的にロケール情報がクエリ文字列に含まれるようになります。たとえばhttp://localhost:3001/?locale=ja
のような形式になります。
ほとんどの場合、これだけで要件は満たされるでしょう。これによってURLが読みにくくなるようなことはほとんどありませんが、URLの末尾にロケール情報がぶらさがることになるのも確かです。さらにアプリケーションの設計面から見れば、ロケールはアプリケーションドメインの他の部分よりも構造上の上位に位置するのだから、ロケール情報はURLの上の方に置くべきではないかという考え方もあります。
その場合であれば、URLはhttp://www.example.com/en/books
(英語ロケールを読み込む) や http://www.example.com/nl/books
(オランダ語ロケールを読み込む) のような形式にしたくなることでしょう。これは、"default_url_options
の設定をオーバーライドする" 手法で達成できます。以下のようにルーティングでscope
設定する必要があります。
# config/routes.rb scope "/:locale" do resources :books end
これでbooks_path
メソッドを呼び出すと、デフォルトロケールが"/en/books"
のようにURLに現れます。http://localhost:3001/nl/books
のようなURLの場合はオランダ語ロケールが読み込まれ、その後books_path
を呼び出すと、ロケールが反映された"/nl/books"
が返されます。
default_url_options
の戻り値はリクエストごとにキャッシュされるため、対応するI18n.locale
を繰り返しごとに設定するループ内では、ロケールセレクタ内のURLがヘルパー呼び出しによって生成されません。この方法ではなく、I18n.locale
は変更せずにヘルパーに明示的に:locale
オプションを渡すか、request.original_fullpath
を編集してください。
ルーティングでロケールの使用を強制されたくない場合は、以下のように、かっこで示されるオプションのパススコープを使うこともできます。
# config/routes.rb scope "(:locale)", locale: /en|nl/ do resources :books end
上記のようにロケールを必須でない設定にすることで、http://localhost:3001/books
のようにロケールを含まないURLを使ってもRouting Error
は生じなくなります。これは、ロケールの指定がなければデフォルトロケールを使うようにしたい場合に便利です。
ただし上記の方法を使う場合、アプリケーションのホームページやダッシュボードが設置される、いわゆる「ルートURL」については特別な注意が必要です。たとえば、http://localhost:3001/nl
のようなURLを指定しても機能しません。これは、routes.rb
におけるroot to: "books#index"
宣言ではロケールが考慮されないからです。(そして、原理上"root" URLは1つのアプリケーションに1つしかないからです)
この問題を回避するには、たとえば以下のようにURLをマッピングする必要があります。
# config/routes.rb get '/:locale' => 'dashboard#index'
このルーティング宣言が他のルーティングを「食べてしまう」ようなことのないよう、ルーティング宣言の順序 には十分ご注意ください。(この記述はroot :to
の直前に置くこともできます)
ルーティングに対してこのような形でシンプルに動作する、以下のようなさまざまなgemをチェックしてみてもよいかもしれません。routing_filter、rails-translate-routes、route_translator。
2.2.3 ロケールをユーザーが自由に設定する
アプリケーションの認証済みユーザーに、アプリケーションのインターフェイスからロケールをユーザー好みに設定させることができます。このアプローチでは、ユーザーが選択したロケール設定をデータベースに保存しておき、それを用いてユーザーからの認証済みリクエストごとにロケールを設定します。
around_action :switch_locale def switch_locale(&action) locale = current_user.try(:locale) || I18n.default_locale I18n.with_locale(locale, &action) end
2.2.4 暗黙のロケールを選択する
リクエストにロケールが明示的に設定されていない場合(上のいずれかの方法などで)、望ましいロケールをアプリケーションが推測すべきです。
2.2.4.1 Languageヘッダーからロケールを推測する
Accept-Language
HTTPヘッダーは、リクエストへのレスポンスで使いたい言語を示します。ブラウザはユーザーの言語設定に基づいてこのヘッダーの値を設定し、ロケール推測時に使える適切な第一候補とします。
Accept-Language
ヘッダーを使った簡単な実装は、たとえば以下のような感じになります。
def switch_locale(&action) logger.debug "* Accept-Language: #{request.env['HTTP_ACCEPT_LANGUAGE']}" locale = extract_locale_from_accept_language_header logger.debug "* Locale set to '#{locale}'" I18n.with_locale(locale, &action) end private def extract_locale_from_accept_language_header request.env['HTTP_ACCEPT_LANGUAGE'].scan(/^[a-z]{2}/).first end
実際には、この信頼性を実現するのにより堅固なコードが必要です。Iain Hackerのhttp_accept_languageライブラリやRyan Tomaykoのlocale Rackミドルウェアがこの問題へのソリューションを提供しています。
2.2.4.2 IP地理情報からロケールを推測する
リクエストを送信するクライアントのIPアドレスは、クライアントの地理上の位置やロケールを推測するのに使えます。GeoIP Lite Countryなどのサービスや、geocoderなどのgemは、このアプローチの実装に利用できます。
一般に、このアプローチはlanguageヘッダーを用いる方法に比べて信頼性がかなり落ちるため、ほとんどのWebアプリケーションではおすすめできません。
2.2.5 セッションやcookieに含まれるロケールの保存について
開発者は、選択したロケールをセッションやcookieに保存したくなる誘惑にかられるかもしれません。しかしこれは行ってはいけません。ロケールは透過的であるべきで、かつURLの一部に含めるべきです。こうすることで、ユーザーがweb自体に対して抱く基本的な前提を崩さずに済みます。あなたがそのURLを知人に送れば、あなたが見ているのとまったく同じページとコンテンツを知人も見ることができます。この前提を表す重要な言い回しが「RESTfulである」ということです。RESTfulアプローチについて詳しくは、Stefan Tilkovの記事を参照してください。RESTfulというルールから外れる場合もありますが、それについては後述します。
3 国際化とローカライズ
お疲れさまでした。以上でRuby on RailsアプリケーションのI18nサポートの初期化が完了しました。使用すべきロケールも設定され、リクエスト間でロケールを保存する方法も指定されました。
次に必要なのはアプリケーションの国際化です。これは、ロケール固有のあらゆる要素を抽象化することによって行います。最後に必要なのはローカライズです。これは、これらの抽象化に対して必要な訳文を提供することによって行います。
次の例をご覧ください。
# config/routes.rb Rails.application.routes.draw do root to: "home#index" end
# app/controllers/application_controller.rb class ApplicationController < ActionController::Base around_action :switch_locale def switch_locale(&action) locale = params[:locale] || I18n.default_locale I18n.with_locale(locale, &action) end end
# app/controllers/home_controller.rb class HomeController < ApplicationController def index flash[:notice] = "Hello Flash" end end
# app/views/home/index.html.erb <h1>Hello World</h1> <p><%= flash[:notice] %></p>
3.1 ローカライズされたコードを抽象化する
上のコードには英語にローカライズされた文字列が2つあり("Hello Flash"と"Hello World")、これらがユーザー側でレンダリングされます。このコードを国際化するには、Railsの#t
ヘルパーを使って これらの英文字列を置き換えます 。この#t
ヘルパーに、各訳文の意味を適切に表すキーを与えます。
# app/controllers/home_controller.rb class HomeController < ApplicationController def index flash[:notice] = t(:hello_flash) end end
# app/views/home/index.html.erb <h1><%= t :hello_world %></h1> <p><%= flash[:notice] %></p>
の段階でビューがレンダリングされると、:hello_world
と:hello_flash
をキーに持つ訳文が見つからないというエラーメッセージが表示されます。
Railsはt(
translate) ヘルパーメソッドを自動的にビューに追加してくれるので、
I18n.tとフルスペルで書かなくても済みます。さらに、このヘルパーは訳文が見つからない場合にエラーメッセージを
` でラップして表示してくれます。
3.2 訳文を与えて文字列を国際化する
訳文がないので、訳文の辞書ファイルに追加しましょう。
# config/locales/en.yml en: hello_world: Hello world! hello_flash: Hello flash! # config/locales/pirate.yml pirate: hello_world: Ahoy World hello_flash: Ahoy Flash
default_locale
はまだ変更されていないので、訳文では:en
ロケールが使われ、レスポンスで英文の文字列が出力されます。
URLを変更して、海賊語のロケールを渡すと (http://localhost:3000?locale=pirate
)、以下のように表示されます。
ロケールファイルを新しく追加した場合は、サーバーを再起動するまで反映されません。
訳文をSimpleStoreに保存する際、YAML (.yml
) ファイルまたはRuby (.rb
) ファイルのいずれかを選べます。YAMLは多くのRails開発者に好まれている形式です。ただし、YAMLには1つ大きな問題があります。YAMLはホワイトスペースや特殊文字による影響を非常に受けやすいため、アプリケーションが辞書を正しく読み込めないことがあります。Rubyファイル形式を選んだ場合、問題があれば最初のリクエストの時点でアプリケーションがクラッシュするので問題を見つけやすいというメリットがあります。(YAML辞書を使っていて「原因不明の奇妙な問題」が発生した場合は、その部分をRubyファイルに移動してみると問題が解決するかもしれません)
訳文がYAMLファイルに保存されている場合は、一部のキーをエスケープしなければなりません。以下のキーでエスケープが必要です。
-
true
、on
、yes
-
false
、off
、no
例(failure
以下のキーはエスケープされていない):
# config/locales/en.yml en: success: 'true': 'True!' 'on': 'On!' 'false': 'False!' failure:ß true: 'True!' off: 'Off!' false: 'False!'
I18n.t 'success.true' # => 'True!' I18n.t 'success.on' # => 'On!' I18n.t 'success.false' # => 'False!' I18n.t 'failure.false' # => Translation Missing I18n.t 'failure.off' # => Translation Missing I18n.t 'failure.true' # => Translation Missing
3.3 訳文に変数を渡す
アプリケーションの国際化を成功させるために考慮しておきたいのは、ローカライズされたコードを抽象化するときに(そのロケールの)文法を間違えないようにすることです。あるロケールで基礎に据えられている文法の規則が、他のロケールでもそうであるとは限りません。
不適切な抽象化の例を以下に示します。この例では、訳文を構成する各部分の順序(ここでは通貨記号の表示位置)に関する思い込みがあります。Railsでは、以下のような場合に使えるnumber_to_currency
ヘルパーが提供されています。
# app/views/products/show.html.erb <%= "#{t('currency')}#{@product.price}" %>
# config/locales/en.yml en: greet_username: "%{message}, %{user}!" currency: "$" # config/locales/es.yml es: currency: "€"
@product.price
が10の場合、スペイン語での正しい表記は「€10」ではなく「10 €」なのですが、こうした点が抽象化に含まれていません。
抽象化を正しく行うために、I18n gemには「変数の式展開」機能が含まれており、訳文定義で変数を使えるようにし、翻訳メソッドでそれらに値を渡せるようにします。
適切な抽象化の例を以下に示します。
# app/views/products/show.html.erb <%= t('product_price', price: @product.price) %>
# config/locales/en.yml en: product_price: "$%{price}" # config/locales/es.yml es: product_price: "%{price} €"
この抽象化では、文法や約物がすべて定義自身の中で決定されているので、正しい訳文を得られます。
default
キーワードおよびscope
キーワードは予約されているため、変数には利用できません。利用するとI18n::ReservedInterpolationKey
例外が発生します。
ある訳文で式展開変数が期待されているにもかかわらず、#translate
に値が渡されない場合は、I18n::MissingInterpolationArgument
例外が発生します。
3.4 日付・時刻フォーマットを追加する
お疲れさまでした。今度はビューにタイムスタンプを追加し、 日付・時刻のローカライズ 機能が動作するところもお目にかけましょう。時間のフォーマットをローカライズするには、I18n.l
にTimeオブジェクトを渡すか、Railsの#l
ヘルパーを使います(後者がお勧めです)。:format
オプションを渡すことでフォーマットを選べます。デフォルト値は:default
フォーマットです。
# app/views/home/index.html.erb <h1><%= t :hello_world %></h1> <p><%= flash[:notice] %></p> <p><%= l Time.now, format: :short %></p>
それでは、 海賊語の訳文ファイルに時刻フォーマットを追加してみましょう (既にデフォルトロケールを英語から海賊語に切り替えているとします)。
# config/locales/pirate.yml pirate: time: formats: short: "arrrround %H'ish"
出力結果は以下のようになります。
現時点では、I18nバックエンドが (少なくとも海賊ロケールで) 本当に正常に動作するためには、日付・時刻フォーマットを追加する必要があるでしょう。もちろん、誰か親切な人が Railsのデフォルト文字列をすべて翻訳してくれた 結果がネット上のどこかに既にあるかもしれません。ロケールファイルのアーカイブがあるかどうか、GitHubのrails-i18nリポジトリを探してみるとよいでしょう。運よくそうしたファイルが見つかれば、config/locales/
ディレクトリに置くだけで即座に使えるようになります。
3.5 他のロケール向けの活用形ルールを設定する
Railsでは英語以外の言語についても単数形/複数形のような活用形を定義できます。config/initializers/inflections.rb
には、複数言語向けの活用形ルールを置くことができます。このイニシャライザには英語の活用形の追加例が記載されています。他の言語でも同じ要領で活用形ルールを追加できます
3.6 ローカライズ済みビューテンプレート
アプリケーションに BooksController というコントローラがあるとします。このコントローラにある index アクションが実行されるとapp/views/books/index.html.erb
テンプレートが実行されます。同じディレクトリにこのテンプレートの スペイン語ローカライズ版 index.es.html.erb
を置くと、ロケールが:es
のときにこのテンプレートが表示に使われます。ロケールがデフォルトに設定されている場合、汎用のデフォルトindex.html.erb
ビューテンプレートが使われます。(今後のRailsでは、public
ディレクトリなどに置かれるアセットを 自動的にローカライズする 機能が搭載されるかもしれません。)
ビューに大量の文章が含まれているような場合、これらを文単位に分解してYAML辞書やRuby辞書の訳文に置き換えると面倒な上に訳文を滑らかにするのが難しくなることがあります。そのような場合は上のようにロケールごとにビュー全体を切り替える機能を使うのがよいでしょう。ただし、ビュー内で繰り返される訳文の一部を後に変更した場合、同じ変更をビュー内の他の訳文にも手動で適用しなければならない点にご注意ください。
3.7 ロケールファイルの編成
I18nライブラリにデフォルトで同梱されるSimpleStoreを使う場合、辞書は平文テキストファイルとしてディスク上に保存されます。アプリケーションで使われるすべての訳文をロケールごとに1つのファイルに保存すると、サイズが大きくなったときに管理が困難になる可能性があります。このため、訳文ファイルを階層化してわかりやすく保存できるようになっています。
たとえば、config/locales
ディレクトリ以下を以下のように編成できます。
|-defaults |---es.rb |---en.rb |-models |---book |-----es.rb |-----en.rb |-views |---defaults |-----es.rb |-----en.rb |---books |-----es.rb |-----en.rb |---users |-----es.rb |-----en.rb |---navigation |-----es.rb |-----en.rb
このようにして、モデル名とモデル属性名をビュー内部のテキストから分離し、そして日付・時刻フォーマットなどすべてをデフォルトから分離できます。i18nライブラリ用の他のストアでは、別の方法で分離しているものもあります。
Railsのデフォルトのロケール読み込みメカニズムでは、ここで使ったようなネストした辞書に含まれるロケールファイルを読み込みません。従って、これらが読み込まれるようにするためには以下のようにRailsで明示的に指定する必要があります。
# config/application.rb config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}')]
4 I18n API機能の概要
ここまででi18nライブラリに対する理解がかなり進み、基本的なRailsアプリケーションの国際化で必要となる要素についてはひととおり学べたはずです。ここから先の章では、各機能の詳細について説明します。
以後の章では、I18n.translate
メソッドとtranslate
ビューヘルパーメソッド の両方を例にとって説明します (このビューヘルパーメソッドが提供する追加機能についても言及します)。
以下の機能について説明します。
- 訳文の参照
- データを訳文に式展開(interpolate)する
- 訳文の複数形化
- 安全なHTML変換(ビューヘルパーメソッドのみ)
- 日付、数値、通貨などのローカライズ
4.1 訳文の参照
4.1.1 基本的な参照、スコープ、ネストしたキー
訳文は、シンボルまたは文字列のどちらをキーとして参照することもできます。したがって、以下の2つの呼び出しは等価です。
I18n.t :message I18n.t 'message'
translate
メソッドは:scope
オプションを取ることもできます。このオプションには、「名前空間」を指定するための追加キーを1つ以上含めたり、訳文キーのスコープを含めることができます。
I18n.t :record_invalid, scope: [:activerecord, :errors, :messages]
上のコードでは、Active Recordエラーメッセージの:record_invalid
メッセージを参照しています。
さらに、キーとスコープにはドットで区切ったキーを指定することもできます。
I18n.translate "activerecord.errors.messages.record_invalid"
したがって、以下の4つの呼び出しはすべて等価です。
I18n.t 'activerecord.errors.messages.record_invalid' I18n.t 'errors.messages.record_invalid', scope: :activerecord I18n.t :record_invalid, scope: 'activerecord.errors.messages' I18n.t :record_invalid, scope: [:activerecord, :errors, :messages]
4.1.2 :default
:default
オプションが与えられると、訳文が見つからない場合にここで指定した値が返されます。
I18n.t :missing, default: 'Not here' # => 'Not here'
:default
オプションに与えられる値がシンボルの場合、キーとして使われ、訳文に置き換えられます。複数の値をデフォルトとして指定できます。複数の場合、最初に返された値が返されます。
例: 以下では最初に:missing
というキーを訳文に置き換えようとし、続いて:also_missing
というキーを置き換えようとします。ここではどちらからも結果を得られないので、「Not here」という文字列が返されます。
I18n.t :missing, default: [:also_missing, 'Not here'] # => 'Not here'
4.1.3 一括参照と名前空間参照
キーの配列を渡すことで、複数の訳文を一度に参照できます。
I18n.t [:odd, :even], scope: 'errors.messages' # => ["must be odd", "must be even"]
キーは、グループ化された訳文のハッシュに翻訳できます。このハッシュはネストしている可能性があります。例: 以下のコードでは、 すべての Active Recordエラーメッセージをハッシュとして受け取ることができます。
I18n.t 'activerecord.errors.messages' # => {:inclusion=>"is not included in the list", :exclusion=> ... }
多数の訳文を持つハッシュで式展開(interpolation)を行いたい場合は、パラメータにdeep_interpolation: true
を渡す必要があります。以下の辞書があるとします。
en: welcome: title: "Welcome!" content: "Welcome to the %{app_name}"
この設定を行わない場合、ネストした式展開は以下のように無視されます。
I18n.t 'welcome', app_name: 'book store' # => {:title=>"Welcome!", :content=>"Welcome to the %{app_name}"} I18n.t 'welcome', deep_interpolation: true, app_name: 'book store' # => {:title=>"Welcome!", :content=>"Welcome to the book store"}
4.1.4 探索の「遅延」(lazy lookup)
Railsには、 ビュー 内部でロケールを参照するときに便利な方法が実装されています。以下のような辞書があるとします。
es: books: index: title: "Título"
以下のようにして、app/views/books/index.html.erb
ビューテンプレート 内部 でbooks.index.title
値にアクセスできます。ドットが使われていることにご注目ください。
<%= t '.title' %>
パーシャルによる自動訳文スコープは、translate
ビューヘルパーメソッドでのみ使えます。
遅延探索はコントローラでも使えます。
en: books: create: success: Book created!
上は、たとえば次のようにflashメッセージを設定するのに便利です。
class BooksController < ApplicationController def create # ... redirect_to books_url, notice: t('.success') end end
4.2 複数形化
英語を含む多くの言語では、ある名詞には単数形が1種類のみ、複数形も一種類のみがあります (例: "1 message"と"2 messages")。その他の言語 (アラビア語、日本語、ロシア語 など多数) では文法がさまざまに異なっており、複数形 の数は英語より多いものもあれば少ないものもあります。これらに対応するため、I18n APIでも柔軟性の高い複数形化機能を備えています。
:count
という式展開変数には特殊な役割が与えられており、通常の訳文への式展開に使われるほかに、複数形化バックエンドによって定義される複数形化ルールに沿って適切な複数形を選択するのにも使われます。デフォルトでは、英語の複数形化ルールのみが適用されます。
I18n.backend.store_translations :en, inbox: { zero: 'no messages', # オプション one: 'one message', other: '%{count} messages' } I18n.translate :inbox, count: 2 # => '2 messages' I18n.translate :inbox, count: 1 # => 'one message' I18n.translate :inbox, count: 0 # => 'no messages'
ロケールが:en
の場合の複数形化アルゴリズムは単純です。
lookup_key = :zero if count == 0 && entry.has_key?(:zero) lookup_key ||= count == 1 ? :one : :other entry[lookup_key]
つまり、ここでは:one
と表記されている訳語が単数形と見なされ、それ以外はすべて複数形と見なされます(ゼロも複数形と見なされます)。countがゼロで、かつ:zero
エントリが存在する場合は、:other
ではなく:zero
エントリが用いられます。
キーの探索で、複数形のために適切なハッシュが返されない場合は、I18n::InvalidPluralizationData
例外が発生します。
4.2.1 ロケール固有のルール
I18n gemにはPluralization
バックエンドが用意されており、これを用いてロケール固有のルールを有効にできます。これをSimple
というバックエンドにinclude
し、複数形化のためのアルゴリズムをローカライズしたものをi18n.plural.rule
という形で訳文ストアに保存します。
I18n::Backend::Simple.include(I18n::Backend::Pluralization) I18n.backend.store_translations :pt, i18n: { plural: { rule: lambda { |n| [0, 1].include?(n) ? :one : :other } } } I18n.backend.store_translations :pt, apples: { one: 'one or none', other: 'more than one' } I18n.t :apples, count: 0, locale: :pt # => 'one or none'
あるいは、rails-i18nという別のgemを用いて、ロケール固有の複数形化ルールの完全なセットを提供する方法もあります。
4.3 ロケールの設定と受け渡し
ロケールは、擬似グローバルなI18n.locale
(これはThread.current
を使っており、Time.zone
などに似ています) に設定したり、#translate
および#localize
のオプションとして渡すことができます。
ロケールが渡されなかった場合は、I18n.locale
が使われます。
I18n.locale = :de I18n.t :foo I18n.l Time.now
ロケールを明示的に渡すと次のようになります。
I18n.t :foo, locale: :de I18n.l Time.now, locale: :de
I18n.locale
のデフォルトはI18n.default_locale
であり、そのデフォルトはen
です。デフォルトのロケールは以下のように設定できます。
I18n.default_locale = :de
4.4 安全なHTML変換
名前が'html'であるキー、および名前が'_html'で終わるキーは、「HTML safe」とマークされます。これらのキーをビューで使うと、その部分のHTMLはエスケープされません。
# config/locales/en.yml en: welcome: <b>welcome!</b> hello_html: <b>hello!</b> title: html: <b>title!</b>
# app/views/home/index.html.erb <div><%= t('welcome') %></div> <div><%= raw t('welcome') %></div> <div><%= t('hello_html') %></div> <div><%= t('title.html') %></div>
ただし式展開(interpolation)を使うと、必要に応じてエスケープされます。次のyamlがあるとします。
en: welcome_html: "<b>Welcome %{username}!</b>"
ユーザーが設定したこのusername
は、安全に渡せます。
<%# This is safe, it is going to be escaped if needed. %> <%= t('welcome_html', username: @current_user.username) %>
逆に、安全(safe)とマークされた文字列は「そのまま」展開されますのでご注意ください。
安全なHTML変換への自動変換は、translate
ビューヘルパーメソッドでのみ利用可能です。
4.5 Active Recordモデルで翻訳を行なう
Model.model_name.human
メソッドとModel.human_attribute_name(attribute)
メソッドを使うことで、モデル名と属性名を透過的に参照できるようになります。
たとえば以下のような訳文があるとします。
en: activerecord: models: user: Customer attributes: user: login: "Handle" # Userの"login"属性は"Handle"という語に翻訳される
User.model_name.human
は"Customer"を返し、User.human_attribute_name("login")
は"Handle"を返します。
以下のように、モデル名を複数形にしたものを訳文に加えることもできます。
en: activerecord: models: user: one: Customer other: Customers
これにより、User.model_name.human(count: 2)
は複数形の"Customers"を返します。count: 1
またはparamsなしの場合、単数形の"Customer"が返されます。
指定のモデル内のネストした属性にアクセスする必要が生じた場合は、訳文ファイルのモデルレベルでそれらをmodel/属性
の下でネストすべきです。
en: activerecord: attributes: user/role: admin: "Admin" contributor: "Contributor"
上はUser.human_attribute_name("role.admin")
で"Admin"を返します。
ActiveModel
をinclude
するクラスを使っており、かつActiveRecord::Base
を継承しないのであれば、上述のキーパスのactiverecord
をactivemodel
に置き換えてください。
4.5.1 エラーメッセージのスコープ
Active Record検証(バリデーション)エラーメッセージもI18nで簡単に訳文に置き換えられます。Active Recordは、メッセージの訳文を置ける名前空間をいくつも提供しています。名前空間が複数あるのは、モデル・属性・検証ごとに異なるメッセージと訳文を提供できるようにするためです。また、これは単一のテーブル継承のみを透過的に考慮します。
このしくみは、必要に応じて最適なメッセージを柔軟に選択できる強力な手段となります。
以下のUserモデルでは、name属性で検証が1つ行われています。
class User < ApplicationRecord validates :name, presence: true end
この場合、エラーメッセージのキーは:blank
になります。Active Recordは名前空間からこのキーを参照します。
activerecord.errors.models.[model_name].attributes.[attribute_name] activerecord.errors.models.[model_name] activerecord.errors.messages errors.attributes.[attribute_name] errors.messages
この例では、以下のキーを記載順に探索し、最初に見つかったものを結果として返します。
activerecord.errors.models.user.attributes.name.blank activerecord.errors.models.user.blank activerecord.errors.messages.blank errors.attributes.name.blank errors.messages.blank
モデルで継承も使われている場合は、メッセージ探索は継承チェーンに対しても行われます。
たとえば以下のように、Userモデルを継承したAdminモデルがあるとします。
class Admin < User validates :name, presence: true end
このとき、Active Recordは以下の順にメッセージを探索します。
activerecord.errors.models.admin.attributes.name.blank activerecord.errors.models.admin.blank activerecord.errors.models.user.attributes.name.blank activerecord.errors.models.user.blank activerecord.errors.messages.blank errors.attributes.name.blank errors.messages.blank
以上のように、モデル継承チェーンのさまざまな場所や、属性・モデル・デフォルトスコープで使われている多数のエラーメッセージに対して、専用の訳文を提供できます。
4.5.2 エラーメッセージ内での式展開
翻訳されたモデル名・属性名・値は、それぞれmodel
、attribute
、value
という名前でいつでも式展開に使えます。
したがって、たとえば"cannot be blank"
というデフォルトのエラーメッセージに代えて、"Please fill in your %{attribute}"
のように属性名を展開できます。
- 以下の表で式展開の列に
count
が記載されている行の項目では、count
の値に応じて複数形化を行えます。
検証 | 使用可能なオプション | メッセージ | 式展開 |
---|---|---|---|
confirmation | - | :confirmation | - |
acceptance | - | :accepted | - |
presence | - | :blank | - |
absence | - | :present | - |
length | :within, :in | :too_short | count |
length | :within, :in | :too_long | count |
length | :is | :wrong_length | count |
length | :minimum | :too_short | count |
length | :maximum | :too_long | count |
uniqueness | - | :taken | - |
format | - | :invalid | - |
inclusion | - | :inclusion | - |
exclusion | - | :exclusion | - |
associated | - | :invalid | - |
non-optional association | - | :required | - |
numericality | - | :not_a_number | - |
numericality | :greater_than | :greater_than | count |
numericality | :greater_than_or_equal_to | :greater_than_or_equal_to | count |
numericality | :equal_to | :equal_to | count |
numericality | :less_than | :less_than | count |
numericality | :less_than_or_equal_to | :less_than_or_equal_to | count |
numericality | :only_integer | :not_an_integer | - |
numericality | :odd | :odd | - |
numericality | :even | :even | - |
4.5.3 Active Record error_messages_for
ヘルパー用メッセージの訳文
Active Recordのerror_messages_for
ヘルパーを使っているのであれば、そこに独自の訳文を追加したくなることでしょう。
Railsには以下の訳文が最初から含まれています。
en: activerecord: errors: template: header: one: "1 error prohibited this %{model} from being saved" other: "%{count} errors prohibited this %{model} from being saved" body: "There were problems with the following fields:"
このヘルパーを使うには、DynamicForm gemをインストールする必要があります。このgemは、Gemfile
にgem 'dynamic_form'
を追加することでインストールできます。
4.6 Action Mailerメールの件名を訳文に置き換える
mail
メソッドに件名が渡されなかった場合、Action Mailerは既存の訳文の利用を試みます。「<mailer_scope>.<action_name>.subject
」というパターンでキーが構築されます。
# user_mailer.rb class UserMailer < ActionMailer::Base def welcome(user) #... end end
en: user_mailer: welcome: subject: "Welcome to Rails Guides!"
訳文にパラメータを渡したい場合には、default_i18n_subject
メソッドをmailer内で使用します。
# user_mailer.rb class UserMailer < ActionMailer::Base def welcome(user) mail(to: user.email, subject: default_i18n_subject(user: user.name)) end end
en: user_mailer: welcome: subject: "%{user}, welcome to Rails Guides!"
4.7 I18nサポートを提供するその他のビルトインメソッドの概要
Railsでは、固定された文字列の他に、文字列のフォーマットやその他のフォーマット情報をいくつかのヘルパーで使っています。これらについて簡単に説明します。
4.7.1 Action Viewヘルパーメソッド
distance_of_time_in_words
は、得られた結果を訳文に置き換えて複数形化し、秒・分・時などの数値を式展開します。置き換えの詳細についてはdatetime.distance_in_words を参照してください。datetime_select
とselect_month
は月を月名に置き換え、生成されたselectタグに展開します。置き換えの詳細についてはdate.month_namesを参照してください。datetime_select
は、date.order の順序オプションも探します(明示的にオプションを渡さなかった場合)。日付選択用ヘルパーは、すべてdatetime.prompts スコープに訳文があればそれを使って日付オプションを訳文に置き換えてユーザーに表示します。number_to_currency
、number_with_precision
、number_to_percentage
、number_with_delimiter
、およびnumber_to_human_size
ヘルパーは、number スコープに置かれている数値フォーマット設定を使います。
4.7.2 Active Modelのメソッド
model_name.human
とhuman_attribute_name
は、activerecord.models スコープにモデル名と属性名の訳語があればそれを使います。これらのメソッドは、前述の「エラーメッセージのスコープ」で説明されているとおり、継承されたクラス名 (単一テーブル継承 (STI) で使う場合など) の訳語もサポートします。ActiveModel::Errors#generate_message
はmodel_name.human
とhuman_attribute_name
を使います (上記参照)。generate_messageはActive Model検証で使われますが、手動で使うこともできます。このメソッドは、エラーメッセージの訳文への置換と、前述の「エラーメッセージのスコープ」で説明されている、継承されたクラス名の訳文への置き換えもサポートします。ActiveModel::Errors#full_messages
は、エラーメッセージの冒頭に属性名を追加します。このとき、errors.formatで参照される区切り文字を使います。なお、デフォルトでは"%{属性} %{メッセージ}"
の形式になります。
4.7.3 Active Supportのメソッド
-
Array#to_sentence
は、support.array スコープで与えられたフォーマット設定を使います。
5 独自の訳文を保存する方法
Active Supportにデフォルトで装備されている「シンプルな」バックエンドを使っている場合、純粋なRubyファイル形式およびYAMLフォーマット2が使えます。
たとえば、訳文を提供するRubyハッシュは以下のような感じになります。
{ pt: { foo: { bar: "baz" } } }
上と同等のYAMLファイルは以下のような感じになります。
pt: foo: bar: baz
どちらの場合も、トップレベルに置かれているのはロケール名です。:foo
は名前空間のキー、:bar
は"baz"という訳文のキーです。
以下は、Active Supportのen.yml
訳文YAMLファイルから取り出した実例です。
en: date: formats: default: "%Y-%m-%d" short: "%b %d" long: "%B %d, %Y"
上の設定により、以下の4つのコードはいずれも:short
日付フォーマット"%b %d"
を返します。
I18n.t 'date.formats.short' I18n.t 'formats.short', scope: :date I18n.t :short, scope: 'date.formats' I18n.t :short, scope: [:date, :formats]
訳文を保存するには、一般にYAMLがお勧めです。ただし、特殊な日付フォーマットを使うなどの目的で、ロケールデータの一部としてラムダ(lambda)を保存するためにRubyファイル形式を選ぶこともできます。
6 I18n設定をカスタマイズする
6.1 バックエンドを切り替える
Active Supportで利用できる組み込みの「Simple」バックエンドは、さまざまな理由により、 Ruby on Rails では「正常に動作する可能性の高い、最も単純な動作しか行いません」3。つまり、「Simple」バックエンドで動作が保証されているのは英語と、英語に極めて近い言語ぐらいしかないということです。同様に、「Simple」バックエンドは訳文を読み出すことしかできず、訳文を動的に任意のフォーマットで保存することはできません。
もちろん、この制限を突破できないということではありません。Ruby I18n gemを利用して、「Simple」バックエンド実装をよりふさわしいものに差し替えることができます。これを行うには、I18n.backend=
セッターにバックエンドのインスタンスを1つ渡します。
たとえば「Simple」バックエンドを、複数のバックエンドをチェインさせる「Chain」バックエンドに置き換えることもできます。これは、基本的には「Simple」バックエンドに保存された標準的な訳文を使いたいが、アプリケーションのカスタム訳文はデータベースなどの別のバックエンドに保存しておきたい、というような場合に便利です。
「Chain」バックエンドを使うと、通常はActive Recordのバックエンドが使われ、フォールバック先(デフォルト)が「Simple」バックエンドになります。
I18n.backend = I18n::Backend::Chain.new(I18n::Backend::ActiveRecord.new, I18n.backend)
6.2 標準以外の例外ハンドラを使う
I18n APIでは以下の例外が定義されています。これらの例外は、予想外の条件が発生した場合にバックエンドによって発生します。
MissingTranslationData # リクエストされたキーに対応する訳文が見つからない InvalidLocale # I18n.localeに設定されたロケールが無効 (nilなど) InvalidPluralizationData # countオプションが渡されたが訳文データが複数形化に対応していない MissingInterpolationArgument # 訳文側で必要となる式展開用の引数が渡されなかった ReservedInterpolationKey # 訳文に含まれる式展開の変数名に予約済みの変数名が使われている(scopeやdefaultなどのいずれか1つ) UnknownFileType # I18n.load_pathに追加されたファイルの種類をバックエンドが判定できない
I18n APIはバックエンドでスローされた例外をすべてキャッチし、default_exception_handlerメソッドに渡します。このメソッドは例外をすべて再度raiseしますが、MissingTranslationData
のみ再度のraiseを行いません。MissingTranslationData
例外がキャッチされた場合は、失われたキーとスコープを含む例外エラーメッセージ文字列を返します。
MissingTranslationData
例外がこのような動作になっているのは、開発中に訳文がなくても画面を表示できるようにするためです。
開発中以外の状況に合わせてこの動作を変更することもできます。たとえば、自動テストをスムーズに行えるよう、訳文が見つからないエラーをデフォルトの例外ハンドリングでキャッチさせないようにしたい場合などです。このような目的のために、標準以外の例外ハンドラを指定できます。指定された例外ハンドラは、I18nモジュールのメソッド、または#call
メソッドを持つクラスでなければなりません。
module I18n class JustRaiseExceptionHandler < ExceptionHandler def call(exception, locale, key, options) if exception.is_a?(MissingTranslationData) raise exception.to_exception else super end end end end I18n.exception_handler = I18n::JustRaiseExceptionHandler.new
上のコードはMissingTranslationData
例外のみを再raiseし、それ以外のすべての入力をデフォルトの例外ハンドラに渡します。
ただし、I18n::Backend::Pluralization
を使っている場合、このハンドラはI18n::MissingTranslationData: translation missing: en.i18n.plural.rule
例外も生成します。通常この例外は無視され、英語ロケールのデフォルトの複数形化ルールにフォールバックします。この動作を回避するには、以下のように訳文キーを追加でチェックします。
if exception.is_a?(MissingTranslationData) && key.to_s != 'i18n.plural.rule' raise exception.to_exception else super end
デフォルトの動作があまり望ましくないもう一つの例として、Rails TranslationHelperがあります。これは#t
メソッド (および#translate
) を提供します。このコンテキストでMissingTranslationData
例外が発生すると、このヘルパーメソッドはCSSクラスtranslation_missing
を持つspanタグでメッセージを装飾します。
これを行なうために、このヘルパーは:raise
オプションでどのような設定が行われていてもI18n#translate
で強制的に例外を発生させます。
I18n.t :foo, raise: true # always re-raises exceptions from the backend
7 モデルのコンテンツを翻訳する
本ガイドに記載されているI18n APIでは、主に「UI文字列」の翻訳を想定しています。モデルのコンテンツ(ブログ記事など)を翻訳する方法をお探しの場合は、別のソリューションを検討する必要があります。
そうした目的に使える以下のようなさまざまなgemがあります。
- Globalize: 訳文を別の翻訳用テーブル(各テーブルは1つの翻訳済みモデルに対応)に保存するgemです。
- Mobility: 訳文テーブルやJSONカラム(PostgreSQL)など、訳文のさまざまな保存方法を提供します。
- Traco: Rails 3やRails 4向けの翻訳可能なカラムを提供し、モデルのテーブル自身に保存します。
8 まとめ
ここまでの解説をお読みいただいたことで、Ruby on RailsでサポートされているI18nの概要を把握でき、アプリケーションを翻訳する準備が整ったことと思います。
9 Rails I18nへの貢献について
Ruby on Rails 2.2から導入されたI18nサポートは、現在も進化し続けています。I18nプロジェクトは、Ruby on Railsの優れた開発慣習に従って進められています。つまり、機能をいきなりコアに導入するのではなく、最初はプラグインとして進化させてアプリケーションで実地に使って改良を重ね、その後に最も広く一般的に利用可能な最善の機能を組み合わせたものだけが抽出され、Railsのコアに採用されるのです。
ですから、Railsチームはすべての皆様にプラグインなどのライブラリに採り入れられた新しいアイディアや機能をどしどし試していただき、その結果をコミュニティで利用できるようにしていただければと思います。(ぜひメーリングリスト) でもお知らせください)
欲しいロケールがRuby on Railsの訳文データの例リポジトリにない場合、リポジトリをfork し、訳文をそこに追加いただいた後pull requestを送信してください。
10 リソース
- Google group: rails-i18n - I18nプロジェクトのメーリングリストです。
- GitHub: rails-i18n - I18nプロジェクトのコードリポジトリです。Rails用の訳文は訳文例に多数掲載されています。これらの訳文は大半のアプリケーションで利用できるはずです。
- GitHub: i18n - I18n gemのコードリポジトリです。
11 作者
- Sven Fuchs (最初の作者)
- Karel Minařík
本ガイドがお役に立ちましたら、workingwithrails でこれらの作者を推奨いただければ幸いです(訳注: 翻訳時点ではこのサイトは引退したと表示されていました)。
12 脚注
1 あるいは、Wikipedia によれば「国際化とは、技術上の実装変更を伴わずに多数の言語や地域への適合を行なうための、ソフトウェアアプリケーションの設計プロセスである。ローカライズとは、ロケール固有のコンポーネントを追加したりテキストを翻訳したりすることによってソフトウェアを特定の言語や地域に適合させるプロセスである。」となっています。
2 この他のバックエンドでは、異なるフォーマットが利用できたり、必須とされる可能性があります。たとえば、GetTextバックエンドはGetTextファイルを読み込めるでしょう。
3 理由のひとつは、I18n機能を必要としないアプリケーションで不必要な読み込みを強要したくないためです。そのために、私たちチームはI18nを極力シンプルに保ち、あえて英語のみに絞り込んでいるのです。もうひとつの理由は、既存のあらゆる言語で生じるあらゆる問題を一度に解決できるような万能のソリューションを実装するというのは無理な相談だからです。結局私たちのようなI18n開発者にできることは、実装全体をいつでも簡単に差し替えられるようにすることぐらいしかありません。I18nを差し替え可能にすることで、実験や拡張がずっと容易になるというメリットも得られます。
支援・協賛
Railsガイドは下記のサポーターから継続的な支援を受けています。