Ruby on Rails:Rails の i18n

RailsI18nとは

I18ninternationalization の略で、国際化・多言語化を意味する。

一般に、アプリケーションの国際化では、『国際化』と『ローカライズ』のプロセスがある。『国際化』プロセスでは、使われる全ての文言やロケール固有の要素(日付、通貨フォーマット等)の抽象化までの作業を行う。『ローカライズ』では、具体的な翻訳方法や、翻訳のためのフォーマットを提供したりする。

具体的には、i18n gem はアプリケーションの文言を英語以外の別の1つの言語に翻訳する機能や、多言語サポート機能を導入するためのフレームワークを提供している。

Rails アプリケーションにおいて、 国際化する プロセスでは次のことを行う。

また、Rails アプリケーションにおいて、 ローカライズする プロセスでは次のことを行う。

  • Rails のデフォルトロケールの差し替え、またはロケールの追加
    (日付や時刻フォーマット、月の呼称、Active Recordモデル名などが対象)
  • アプリケーションで使われる文字列を抽象化し、キーで検索できる辞書に保存
    (フラッシュメッセージやビュー内の固定テキストなどが対象)
  • 作成された辞書を別の場所に保存

Ruby on Rails におけるI18n

Railsフレームワーク内のすべての静的文字列(Active Recordのバリデーションメッセージ、時刻や日付のフォーマットなど)の 国際化部分は既に設定済み。 よって、Railsアプリケーションのこれら部分の「ローカライズ」は、欲しい言語の文字列について翻訳済みの値(訳文)を定義することを指す。

国際化とローカライズ

国際化でやることは、ロケール固有のあらゆる要素を抽象化する。例えば、次のようなことを行う。

# ロケール固有
## 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>)

# 国際化後
## 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 FlashHello World)、国際後では Rails#t ヘルパーを用いてそれらの文字列を置き換えている(t(:hello_flash)t :hello_world)。

抽象化したら、それらに対して訳文の辞書ファイルを追加する。

# config/locales/en.yml
en:
  hello_world: Hello world!
  hello_flash: Hello flash!

Active Recordモデルの翻訳を使う

モデル名と属性名を参照するときは、モデル名.model_name.human メソッドと モデル名.human_attribute_name(キー) を使う。

使う際には、下記のように記述する。そうすることで、当該の値がモデル名と属性名を示しているということを標準化できる。

en:
  activerecord:
    models:
      # モデル名
      book: 本
    attributes:
      # モデルの属性名
      book:
        title: 'タイトル'
        memo: 'メモ'
        author: '著者'
        picture: '画像'

ビュー や コントラローラで使うときには、次のようにする。

<table>
  <thead>
    <tr>
      <th><%= Book.human_attribute_name(:title) %></th>
      <th><%= Book.human_attribute_name(:memo) %></th>
      <th><%= Book.human_attribute_name(:author) %></th>
      <th><%= Book.human_attribute_name(:picture) %></th>
      <th colspan="3"></th>
    </tr>
  </thead>
</table>

式展開で渡す

最初、次のようなローカライズをしていた。

message:
  created: '本は正常に作成されました。'
  updated: '本は正常に更新されました。'
  destroyed: '本は正常に削除されました。'
  error_explanation: '本の登録の権限がありませんでした'

それで使うときは、t('message.created') ので呼び出す。

上記は、本固有のモデルのローカライズになってしまっている。モデルが人になった場合には、の部分をユーザとしたいが、なるべく共通部分は使いまわしたい。

そんなときに使えるのが、式展開。使うときにはローカライズを下記のようにする。

message:
  created: '%{item}は正常に作成されました。'
  updated: '%{item}は正常に更新されました。'
  destroyed: '%{item}は正常に削除されました。'
  error_explanation: '%{item}の登録の権限がありませんでした'

そして、呼び出すときには、Active Recordモデルの翻訳を合わせて用いることで、モデル名に応じてローカライズが切り替わるように翻訳される。

具体的には、モデルの場合、t('message.created', item: Book.model_name.human) と呼び出してあげると、Book.model_name.humanローカライズで定義した値『本』で itemキーに紐付き、ローカライズで定義された文章に式展開され、『本は正常に作成されました。』が表示される。

参考