webエンジニアの日常

RubyやPython, JSなど、IT関連の記事を書いています

Railsアプリを多言語対応するまで

f:id:s-uotani-zetakansu:20170831143118j:plain

こんにちは、エンジニアのさもです。

Railsアプリを多言語(今回は英語対応)する仕事をやったので、一連の手順をメモしておきます。

目次

はじめに

システムの用件としては、

  • 何も付けなかったときと、/jaをつけたページにアクセスした場合は、日本語ページ
    • 例えば、localhost:3000/users またはlocalhost:3000/ja/users とアクセスした場合は日本語ページです
  • /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つです。

  1. 既存の画面にある日本語をja.ymlに書いて、画面にはtメソッドで表示するようにする
  2. 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の作成と全画面の置換はとても大変ですが、がんばりましょう。

私もがんばっています。