こんにちは、エンジニアのさもです。
Railsアプリを多言語(今回は英語対応)する仕事をやったので、一連の手順をメモしておきます。
目次
はじめに
システムの用件としては、
- 何も付けなかったときと、/jaをつけたページにアクセスした場合は、日本語ページ
- /enを付けた場合は英語ページ
- localhost:3000/en/users とした場合は英語ページが表示されます
を満たすように作っていきます。
実装
gemの追加(2017/09/11追記)
rails-i18n
というgemを追加します
追加しないと、バリデーションメッセージが
translation missing ja.activerecord.errors.models.user.attributes.family_name.blank
となってしまいました
application.rbの修正
config/application.rbへi18nの設定を書いておきます.
# 有効にする言語のホワイトリスト config.i18n.available_locales = %i(ja en) # ホワイトリストをチェックするかどうか config.i18n.enforce_available_locales = true # 言語を指定されなかった場合のデフォルト値 config.i18n.default_locale = :ja
routesの変更
次に/enや/jaという引数を取るために、routesを修正します。
scope '(:locale)', locale: /#{I18n.available_locales.map(&:to_s).join('|')}/ do 多言語化する画面のroutes定義 end
これでlocaleという名前でjaやenをパラメータのように扱うことができます。
この時点で、/jaや/enをルートパスの次に書いてアクセスしてもエラーにならず、普通にアクセスできるようになります。
コントローラの変更
params[:locale]でja,enを取れるようになったので、パラメータに応じてアプリ全体で使う言語を指定するようにします
application_controller.rbへ次のメソッドを追加します。
def set_locale I18n.locale = locale end def locale @locale ||= params[:locale] ||= I18n.default_locale end def default_url_options(options={}) options.merge(locale: locale) end
- localeメソッド
- パラメータで渡ってきた言語をインスタンス変数へセットします。
- パラメータがない場合は、デフォルトの言語を使用します。
- set_localeメソッド
- アプリの設定へ反映します
- default_url_options
- 画面遷移をしたときに言語の指定が消えないようにしておきます
これでパラメータで渡した値をアプリのどこからでも見ることができるようになりました。
画面の多言語化
パラメータに応じて画面の表示を変えるには、大きく分けて次の2通りあると思います
- 英語用と日本語用のviewを用意しておいて出し分ける
- メリット
- 言語であまりにも画面が違うときは簡単
- デメリット
- 画面のつくりが同じ場合は、保守が面倒になるだけ
- メリット
- 共通の画面を作っておき、文字を表示するところは、t()メソッドでja.yml, en.ymlをアプリが選んで出し分ける
- メリット
- 共通の画面なので、保守性が高い
- デメリット
- ja.yml, en.ymlを作るのが大変
- メリット
特に理由がなければ2つ目の方法がいいと思います。
もし、フランス語にも対応するとなったとき、全ての画面を作るのは大変ですよね。
2つ目の対応を選んだ場合、やることは2つです。
- 既存の画面にある日本語をja.ymlに書いて、画面にはtメソッドで表示するようにする
- en.ymlを書く
既存の画面の修正
全ての画面の日本語部分を修正します。
例えば、views/users/index.html.erbなら、ja.ymlに
ja: users: index: title: ユーザ一覧 name: 名前 age: 年齢
と書いていきます。
画面側では、「ユーザ一覧」となっているところをt('.title')
で置き換えます。
「名前」ならt('.name')
に置換します。
また、views/users/_form.html.erbにも同じような日本語が出てくると思います。
yamlではアンカーとエイリアスを使って、共通のものを使いまわすことができます。
ja: users: index: &user_common title: ユーザ一覧 name: 名前 age: 年齢 form: <<: *user_common
このようにしておくと、_form.html.erbでもt('.name')
が使えます。
en.ymlの作成
こちらも大変ですが、ja.ymlで書いた項目全てに英語を割り当てていきます。
もし漏れがあると、エラーが画面に表示されてしまうので注意が必要です。
最後に
yamlの作成と全画面の置換はとても大変ですが、がんばりましょう。
私もがんばっています。