【Rails】I18n入門書

Rails

I18nとは、ある言語の文言を別の言語の文言に翻訳してくれる機能のことです。

以下のようにデフォルトで使用する言語を設定し、config/locales/以下に翻訳ファイルを配置することで、現在の言語に対応する翻訳文を取得して表示します。

config/application.rb | デフォルト言語を日本語に設定する
1
2
3
4
5
module I18nApp
  class Application < Rails::Application
    config.i18n.default_locale = :ja # 追加
  end
end
config/locales/ja.yml | 日本語に翻訳したい文言を設定する
1
2
3
4
5
6
7
8
9
10
11
ja:
  activerecord:
    errors:
      models:
        user:
          attributes:
            name:
              blank: "空になっています。入力してください。"
            age:
              blank: "空になっています。入力してください。"
# 省略

I18nを使うと、以下の画像のようなvalidationのエラー表示も日本語に翻訳することが出来ます。

validationのエラー表示を日本語に翻訳

また、翻訳だけではなく、現地の日付のフォーマットに変換することもできます。

基本的な使い方

この章では、I18nの設定方法や基本的な使い方について解説します。

アプリケーションを日本語化対応する手順
リンクをコピーしました

i18n_appアプリケーションを日本語化する手順を解説します。
以下は作成するアプリケーションの完成図です。

アプリケーションの完成図

以下の手順で作成していきます。

  1. デフォルト言語の設定
  2. 翻訳ファイルの作成
  3. 翻訳ファイルの設定
  4. エラーメッセージの確認

I18nを使ったことがない方は、一緒にアプリケーションを作成して理解を深めていきましょう。

前準備:サンプルアプリケーション用意
リンクをコピーしました

まずは、rails newi18n_appアプリケーションを作成します。

ターミナル | データベースをMySQLを指定してアプリケーションを作成する
1
rails _5.2.1_ new i18n_app -d mysql

以下のように作成したi18n_appのディレクトリに移動して、簡易的なユーザー登録や一覧機能を一気に作成してくれるscaffoldを実行します。

ターミナル | ユーザー管理する為の雛形を作成
1
2
3
cd i18n_app # ディレクトリを移動
rails g scaffold User name:string age:integer
# rails g scaffold モデル名 カラム名:型 カラム名:型

このコマンドでnameカラム、ageカラムを含めたusersテーブルが作成されて、ユーザーを作成するフォームも自動で作成されています。今回はこのフォームを使って解説します。

そして、以下のコマンドを実行してデータベースの作成を行います。

ターミナル | データベース作成とマイグレーションを実行
1
2
bundle exec rails db:create && rails db:migrate 
# scaffoldの内容を元にして作成されたマイグレーションファイルを実行してデータベースを作成

次に、Userモデルに以下のvalidationを追加します。validationに引っかかった際は、エラーメッセージが表示されます。

app/models/user.rb | validationを追加する
1
2
3
class User < ApplicationRecord
  validates :name, :age, presence: true
end

このvalidationを追加することによって、フォームからユーザーを作成するときにnameとageの項目が空であればエラーが出ます。

また、以下のコードの<h1>New User</h1>は、scaffoldで自動で作成された部分なので日本語に変更します。

app/views/users/new.html.erb | 英語表記の部分を日本語へ
1
2
3
4
5
6
7
<h1>New User</h1> <!--変更前-->
<h1>新規登録</h1> <!--変更後-->

<%= render 'form', user: @user %>

<%= link_to 'Back', users_path %> <!--変更前-->
<%= link_to '戻る', users_path %> <!--変更後-->

サーバーを起動させて「localhost:3000/users/new」にアクセスし、以下の画像のようにフォームに何も入力しないでユーザーを作成すると、エラーメッセージが表示されます。

validationに引っかかってエラーメッセージが表示されている例

英語のエラーメッセージが表示されていれば、アプリケーションの雛形は完成です。

h1のNew Userを手動で新規登録に変更した箇所とは違い、このエラーメッセージは、Railsアプリケーションによって自動で付与されます。デフォルトでは英語になってしまうので、デフォルト言語を日本語に変更して、英語のエラーメッセージを日本語に翻訳する翻訳ファイルを作成します。

1. デフォルト言語の設定
リンクをコピーしました

デフォルト言語を英語から日本語に設定するには、以下のコードをconfig/application.rbに追加します。

config/application.rb | デフォルト言語を日本語に設定する
1
2
3
4
5
module I18nApp
  class Application < Rails::Application
    config.i18n.default_locale = :ja # 追加
  end
end

2. 翻訳ファイルの作成
リンクをコピーしました

日本語の翻訳を設定するファイルを作成する為に、config/locales以下にデフォルト言語で設定した名前のyamlファイル(ja.yml)を作成します。

翻訳ファイルの作成方法

config/locales以下に翻訳する言語の設定ファイルを配置すると、自動で読み込まれます。

i18n_appディレクトで以下のコマンドを実行して、ファイルを作成します。

ターミナル | 翻訳ファイルを作成する
1
touch config/locales/ja.yml

ja.ymlファイルには、以下のコードを記述します。

config/locales/ja.yml | 初期設定追加
1
2
ja:
  activerecord:

次の章で、ja.ymlファイルにエラーメッセージを翻訳する詳しい設定方法について解説します。

3. 翻訳ファイルの設定
リンクをコピーしました

翻訳ファイルの設定の解説をする前に、ymlファイルの使い方について触れます。

ymlファイルの基本的な書き方は、以下のようにインデントを使うことで、データの階層構造を表現することが出来ます

ja.yml | 基本的な書き方
1
2
3
4
ja:
  word:
    greeting:
      hello: "こんにちは" # このデータが欲しい

階層構造になったデータにアクセスするには、以下のコードのように階層を.で繋いだ文字列をtメソッドに渡します。
tメソッドについては、後述します。

コンソール | 階層化したデータにアクセスする
1
2
irb(main):001:0> I18n.t("word.greeting.hello")
=> "こんにちは"

そして、このja.ymlファイルに翻訳を追加する際は、以下の点に気をつけてください。

Pikawakaマークyamlファイルの書き方のポイント

  1. キー: "値"とする場合は、コロンの後には半角スペースを入れる
  2. 上記のような入れ子の階層構造にする場合は、インデント(半角スペース2)を使う

それでは、i18n_appアプリケーションの日本語化する手順について確認します。

ここまでの日本語翻訳の設定を反映させる為に、一度サーバーを再起動させて「localhost:3000/users/new」にアクセスし、フォームに何も入力しないで新規登録を行うと、以下のようにtranslation missingのエラーが発生します。

translation missingというエラーが発生する動画

通常、I18nは設定した言語に応じてconfig/locales/以下から対応する翻訳ファイルを読み込んで、その言語に翻訳してくれますが、今回の場合は、以下の画像のように日本語に設定したのに、「エラーメッセージに対応する日本語の翻訳が見つからない」というエラーが発生しています。

translation missingというエラーが発生

現在、翻訳ファイルは以下のコードのように初期設定のみ記述しているので、日本語に翻訳する事が出来ません。

config/locales/ja.yml | 日本語の翻訳ファイル
1
2
ja:
  activerecord:

この翻訳ファイル(ja.yml)に、エラーメッセージが対応する日本語訳を設定する事で、translation missingを解決して日本語に表示することが出来ます。

翻訳ファイルに設定するNameAgeのエラーメッセージのキーは、以下の画像の通りです。

NameとAgeのエラーメッセージのキー

冒頭でも少し触れましたが、上記のキーを繋げる.は翻訳ファイルの階層を表しています。翻訳ファイルに、この階層通りにキーを配置して訳文を記述することで、エラーメッセージを正しく設定することが出来ます。

コピー用
1
2
3
4
5
# Nameが空だった場合に、日本語に翻訳されるエラーメッセージのキー
ja.activerecord.errors.models.user.attributes.name.blank

# Ageが空だった場合に、日本語に翻訳されるエラーメッセージのキー
ja.activerecord.errors.models.user.attributes.age.blank

翻訳ファイルの階層は、インデントを使って記述します。Nameの値が空だった場合は、以下の画像のようにインデントでエラーメッセージの階層を表現します。

エラーメッセージの階層をインデントで表現する

また、NameAgeのエラーメッセージのキーはattributesまで階層が一緒なので、以下のように記述する事が出来ます。日本語で表示したい訳文をblankの箇所に記述します。

config/locales/ja.yml | エラーメッセージの日本語訳を追加
1
2
3
4
5
6
7
8
9
10
ja:
  activerecord:
    errors:
      models:
        user:
          attributes:
            name:
              blank: "Nameが空だった場合の日本語のエラーメッセージを入れる"
            age:
              blank: "Ageが空だった場合の日本語のエラーメッセージを入れる" 

このように翻訳ファイルには、階層を表現するためにインデントを使ってキーを記述します。それでは、最後にblankを以下のように記述しましょう。

config/locales/ja.yml | エラーメッセージの日本語訳を追加
1
2
3
4
5
6
7
8
9
10
ja:
  activerecord:
    errors:
      models:
        user:
          attributes:
            name:
              blank: "空になっています。入力してください。"
            age:
              blank: "空になっています。入力してください。"

4. エラーメッセージの確認
リンクをコピーしました

config/以下のファイルの内容を変更した場合は、変更を反映させる為にサーバーを再起動させる必要があるので、一度サーバーを再起動させてから「localhost:3000/users/new」にアクセスします。

フォームを空にしてユーザーを作成すると、以下の画像のようにエラーメッセージが日本語で表示されるようになりました。

エラーメッセージが日本語で表示

ここまでが、I18nを使って日本語に翻訳する為の基本的な手順になります。
ちなみに以下のエラーメッセージの部分は、コードを変更するだけで日本語表記に出来ます。

手動で変更できる部分

app/views/users/_form.html.erb | エラーメッセージを日本語へ変更する
1
2
3
4
5
<!-- 変更前 -->
<h2><%= pluralize(user.errors.count, "error") %> prohibited this user from being saved:</h2>

<!-- 変更後 -->
<h2><%= user.errors.count %> 件のエラーが発生しました</h2>

コードを上記に変更すると、以下のように日本語で表示出来ます。

日本語表示に変更

英語で表示されてる他の箇所(Name, Age, submit)は、I18nを使って日本語へ翻訳する必要がありますが、この後のmodelやsubmitの日本語化の章で解説させて頂きます。

Pikawakaマークポイント

  1. デフォルトの英語から日本語に翻訳するには、application.rbで config.i18n.default_locale = :jaのコードを追加することでデフォルトを日本語に設定できる
  2. localesディレクトリの下にja.ymlファイルを作成する
  3. config/以下のファイルの内容を変更した場合は、変更を反映させる為にサーバーを再起動させる必要がある

modelを日本語化対応する設定
リンクをコピーしました

modelやmodelの属性を日本語化するには、以下のキーを翻訳ファイルに設定します。

modelを日本語化対応する際に使うキー
1
2
3
4
5
# モデル名
ja.activerecord.models.モデル名

# モデルの属性
activerecord.attributes.モデル名.属性

上記を翻訳ファイルに設定する事で、ユーザー登録の以下の部分を日本語へ翻訳することが出来ます。

ラベルを日本語に翻訳

この部分は、以下のようにform_withの第一引数に「Userモデルのインスタンス(model: user)の情報」をFormBuilderオブジェクト(form)に渡しているので、<%= form.label :name %>でUserモデルのname属性をラベル名として表示する事ができます。

app/views/users/_form.html.erb | 新規登録フォームのコードを確認
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<%# model: userには、部分テンプレートで@user = User.newが渡される %>

<%= form_with(model: user, local: true) do |form| %>
 <%# 省略 %>
  <div class="field">
    <%= form.label :name %>
    <%= form.text_field :name %>
  </div>

  <div class="field">
    <%= form.label :age %>
    <%= form.number_field :age %>
  </div>

  <div class="actions">
    <%= form.submit %>
  </div>
<% end %>

上記では、Userモデルのname,age属性を使っているので、Userモデルのname,age属性を取得するymlファイルのキーは以下になります。

翻訳ファイルに設定するmodelとmodelの属性のキー
1
2
3
4
5
6
7
8
# Userモデル名の設定
ja.activerecord.models.user

# Userモデルのnameの設定
ja.activerecord.attributes.user.name

# Userモデルのageの設定
ja.activerecord.attributes.user.age

以下のように、modelsから下のコードをja.ymlファイルに追加します。

config/locales/ja.yml | modelの日本語訳を追加
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
ja:
  activerecord:
    errors:
      models:
        user:
          attributes:
            name:
              blank: "空になっています。入力してください。"
            age:
              blank: "空になっています。入力してください。"
    models: #ここから下のコードを追加
      user: "ユーザー"
    attributes:
      user:
        name: "名前"
        age: "年齢"

上記を確認すると、attributesの下の階層にnameageの属性名ではなくuserが入っています。

これは、以下の画像のようにラベルを作成する際に、Userモデルの情報を持つformの中のnameageの属性を使っているので、翻訳ファイルにも属性名の前にuserを入れる必要があるからです。

formオブジェクトにはユーザーモデルの情報が入っているので、attributes、モデル名(今回の場合はuser)以下のカラム名を見に行くように設定されます。

FormBuilderオブジェクトとi18nのキーの確認

ja.ymlにmodelの日本語を追加したら、サーバーを再起動させて「localhost:3000/users/new」にアクセスすると、以下の画像のようにラベルを日本語に翻訳する事が出来ました。

ラベルを日本語に翻訳

また、エラーメッセージも日本語に翻訳されている事が確認できます。

submitを日本語化対応する設定
リンクをコピーしました

ja.helpers.submit以下に設定する事で、デフォルトのsubmitも日本語に翻訳する事が出来ます。
先ほどのユーザー登録のsubmitは、以下の画像のようにモデル名だけ翻訳され中途半端なボタンになっています。

中途半端に翻訳された不自然なボタン

以下のように、helpersから下のコードをja.ymlファイルに追加します。

config/locales/ja.yml | submitの日本語訳を追加
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
ja:
  activerecord:
    errors:
      models:
        user:
          attributes:
            name:
              blank: "空になっています。入力してください。"
            age:
              blank: "空になっています。入力してください。"
    models:
      user: "ユーザー"
    attributes:
      user:
        name: "名前"
        age: "年齢"
  helpers: # ここから下を追加する
    submit:
      create: 登録する
      update: 更新する
      submit: 保存する

サーバーを再起動させて「localhost:3000/users/new」にアクセスします。

submitを日本語化

上記の画像のように、submitを「登録する」という日本語に翻訳する事が出来ました。

このsubmitの表示は、form_withに渡されるUserモデルの状態に応じて変更されます。例えば、すでにUserモデルの情報が存在する場合は、updateの翻訳を見に行き「更新する」と表示されます。

I18nの主要なメソッド
リンクをコピーしました

I18nには、以下の主要なメソッドがあります。

  • translateメソッド - config/locales以下の翻訳ファイルの参照
  • localizeメソッド - 日付や時刻を設定した言語のフォーマットに変換する

以下のように翻訳ファイルの訳文を参照したり、日付をフォーマットに変換することが出来ます。

コンソール | translateメソッドとlocalizeメソッドを実行する
1
2
3
4
5
[1] pry(main)> I18n.translate("word.greeting.hello")
=> "こんにちは"

[2] pry(main)> I18n.localize(Date.today)
=> "2020/04/15"

また、上記のtranslateメソッドとlocalizeメソッドは、以下のようにtメソッドとlメソッドを使ってシンプルに記述することが出来ます。(こちらのメソッドで解説していきます。)

コンソール | tメソッドとlメソッドを実行する
1
2
3
4
5
[1] pry(main)> I18n.t("word.greeting.hello")
=> "こんにちは"

[2] pry(main)> I18n.l(Date.today)
=> "2020/04/15"

それでは、各メソッドについて解説していきます。

translateメソッド
リンクをコピーしました

translateメソッドは、config/locales/以下の翻訳ファイルを参照することが出来ます。

例えば、翻訳ファイルに以下のような階層で日本語翻訳が設定してある場合は、I18n.tメソッドにja:以下の階層の文字列を渡す事で参照することが出来ます。

ja.yml | 基本的な書き方
1
2
3
4
ja:
  word:
    greeting:
      hello: "こんにちは" # このデータが欲しい
コンソール | helloの訳文を参照する
1
2
[1] pry(main)> I18n.t("word.greeting.hello")
=> "こんにちは"

また、scopeオプションを使って以下のようにシンボルで記述することも出来ます。

コンソール | helloの訳文を参照する
1
2
[1] pry(main)> I18n.t(:hello, scope: [:word, :greeting])
=> "こんにちは"

Pikawakaマーク注意点

以下のようにtranslation missingのエラーが発生した場合は、翻訳ファイルに正しく設定されていない可能性があるので、返り値の階層通りに設定し直してください。

translation missingのエラー
I18n.tを省略する
リンクをコピーしました

Controllerやviewファイルでは、以下のようにI18n.t()t()に省略して記述することが出来ます。

app/views/users/new.html.erb | helloの訳文を参照する
1
2
<h1>新規登録</h1>
<%= t("word.greeting.hello") %> <%# 追加するコード %>

I18n.t()を省略した例

コンソールでは、省略することが出来ないので注意してください。

コンソールでI18nを省略することが出来ない

上記のようにt("word.greeting.hello")を実行した場合は、NomethodErrorのエラーが発生してます。

localizeメソッド
リンクをコピーしました

localizeメソッドは、DateオブジェクトやTimeオブジェクトをconfig/locales/以下の翻訳ファイルに設定した日付や時刻のフォーマットに変換することが出来ます。

例えば、デフォルトでは以下のコードのような形式で返ります。

コンソール | DateオブジェクトやTimeオブジェクトのデフォルトの返り値
1
2
3
4
5
[1] pry(main)> Date.today
=> Wed, 15 Apr 2020

[2] pry(main)> Time.now
=> 2020-04-15 22:48:50 +0900

変換するフォーマットを設定するために、翻訳ファイルに以下のように記述します。

config/locales/ja.yml | 日付や時刻のフォーマットを追加
1
2
3
4
5
6
7
ja:
  date:
    formats:
      default: "%Y/%m/%d"
  time:
    formats:
      default: "%y/%m/%d %H:%M"

そして、以下のようにI18n.l()Date.todayTime.nowを渡す事で、それぞれ翻訳ファイルに設定したフォーマットに変換されます。

コンソール | 翻訳ファイルに設定したフォーマットに変換させる
1
2
3
4
5
[1] pry(main)>I18n.l(Date.today)
=> "2020/04/15"

[2] pry(main)> I18n.l(Time.now)
=> "20/04/15 22:35"
default以外のフォーマットを追加する
リンクをコピーしました

以下のlongshortのように、default以外にもフォーマットを自由に追加することが出来ます。

config/locales/ja.yml | default以外にもフォーマットを追加する
1
2
3
4
5
6
ja:
  date:
    formats:
      default: "%Y/%m/%d"
      long: "%Y年%m月%d日" # 追加
      short: "%m/%d" # 追加

default以外のフォーマットに変換したい場合は、I18n.l()の第二引数に以下のように指定します。

コンソール | default以外のフォーマットに変換する
1
2
3
4
5
[1] pry(main)> I18n.l(Date.today, format: :long)
=> "2020年04月15日"

[2] pry(main)> I18n.l(Date.today, format: :short)
=> "04/15"

第二引数の指定がない場合は、以下のようにdefaultのフォーマットに変換されます。

コンソール | defaultのフォーマットに変換する
1
2
[1] pry(main)> I18n.l(Date.today)
=> "2020/04/15"

localizeメソッドは、翻訳ファイルのフォーマットに変換してくれますが、アプリケーションで使用する言語が1つに決まっている場合は、time_formats.rbで日付のフォーマットを指定するのも良いでしょう。

その他の翻訳ファイルの設定
リンクをコピーしました

翻訳ファイルを設定する際に、そのほかの便利な設定方法を解説します。

式展開
リンクをコピーしました

翻訳ファイルは、以下のように式展開を使うことで変数を渡すことが出来ます。

config/locales/ja.yml | 翻訳ファイルに式展開を使う
1
2
3
4
ja:
  word:
    greeting:
      hello: "こんにちは、%{name}さん" # 式展開を使う

I18n.t()の第二引数以降に変数名: "値"を渡すと、以下のように変数の値を展開して汎用性のある文言にすることが出来ます。

コンソール | defaultのフォーマットに変換する
1
2
3
4
5
6
[1] pry(main)> I18n.t("word.greeting.hello", name: "ぴっか")
=> "こんにちは、ぴっかさん"

# 以下でもok
[2] pry(main)> I18n.t(:hello, scope: [:word, :greeting], name: "ぴっか")
=> "こんにちは、ぴっかさん"

この変数に渡す値には、以下のようにモデルのインスタンスを使うことも出来ます。

コンソール | Userモデルのインスタンスを変数に渡す
1
2
3
4
5
6
7
8
9
10
[1] pry(main)> user = User.first
=> #<User:0x00007f80565a1fd0
 id: 1,
 name: "田中",
 age: 18,
 created_at: Thu, 16 Apr 2020 01:12:24 JST +09:00,
 updated_at: Thu, 16 Apr 2020 01:12:24 JST +09:00>

[2] pry(main)> I18n.t("word.greeting.hello", name: user.name)
=> "こんにちは、田中さん"

lazy lookup
リンクをコピーしました

「lazy lookup」とは、「Controllerやviewファイルのディレクトリの階層」を翻訳ファイルに設定する事で、Controllerやviewファイルの内部で参照するキーを短縮してアクセスする事が出来る仕組みのことです。

例えば、翻訳ファイルを以下のようにapp/views/users/new.html.erbの階層を設定します。

config/locales/ja.yml | app/views/users/new.html.erbの階層を設定する
1
2
3
4
ja:
  users: # app/views/users/を表す
    new: # app/views/users/new.html.erbを表す
      title: "ユーザー登録"

この設定をすると、以下のようにapp/views/users/new.html.erbの内部からt .titleの記述だけで、users.new.titleを参照する事が出来ます。

app/views/users/new.html.erb | lazy lookupでキーを短縮する
1
2
<h1><%= t '.title' %></h1>  <!-- 本来は  t 'users.new.title'  -->
<%= render 'form', user: @user %>

シンプルな記述で翻訳ファイルにアクセス

このようにControllerやviewファイルで翻訳ファイルを参照する際は、「lazy lookup」を使う事でキーを短縮して参照する事が出来ます。

応用的な使い方

この章では、I18nについて応用的な使い方を解説します。

「基本的な使い方」で作成したi18n_appアプリケーションを使って解説するので、初期設定等を行なってない場合はアプリケーションを日本語化対応する手順を参照してください。

翻訳ファイルのテンプレートを使用する
リンクをコピーしました

基本的な使い方では、I18nの仕組みを理解するために1つ1つ手動で設定して解説しましたが、実際のアプリケーションでは、ja.activerecord.errors.models.user.attributes.name.blank のキーに対して「空になっています。入力してください。」の様な翻訳ファイルの設定は行いません。

なぜなら、よく利用される英語から日本語に翻訳するパターンの内容(例: blank等)は、I18nテンプレートとしてGithubに公開されているからです。

このテンプレートファイルをダウンロードすると、翻訳ファイルの設定がかなり楽になるので、このテンプレートを利用します。また、管理しやすいようにviewやmodelで分ける手順も解説します。

1. テンプレートをダウンロードする
リンクをコピーしました

まずは、Githubから日本語のテンプレートをダウンロードするために、以下のコマンドをアプリケーションのディレクトリに移動して実行します。

ターミナル | 日本語の翻訳ファイルのテンプレートをダウンロードする
1
2
cd i18n_app # ディレクトリを移動
curl -s https://raw.githubusercontent.com/svenfuchs/rails-i18n/master/rails/locale/ja.yml -o config/locales/ja.yml

上記を実行してconfig/locales/ja.ymlを確認すると、以下のようにテンプレートが反映されています。

テンプレートを使用した場合のja.yml

サーバーを再起動させて「localhost:3000/users/new」にアクセスし、フォームに何も入力しないで新規登録を行うと、以下のようにテンプレートによって日本語に翻訳されたエラーメッセージが表示されます。

テンプレートによって日本語に翻訳されたエラーメッセージ

当然ですが、テンプレートはUserモデルの日本語化対応する設定を行なっていないので、ラベル部分は英語表記のままになります。

2. modelやviewにディレクトリを分ける
リンクをコピーしました

テンプレートを使用する際は、ja.ymlファイルの記述量が多いので、管理しやすいようにmodelやviewの翻訳の設定を以下のように別のファイルに分ける事が出来ます。

ディレクトリ構成の例
1
2
3
4
5
6
7
config/locales
├── en.yml
├── ja.yml
├── models
│          └─ ja.yml
└──  views   
              └─ ja.yml

Userモデルの設定を以下のように、config/locales/models/以下の翻訳ファイルに記述します。

config/locales/models/ja.yml | Userモデルの日本語の翻訳を設定
1
2
3
4
5
6
7
8
ja:
  activerecord:
    models:
      user: "ユーザー"
    attributes:
      user:
        name: "名前"
        age: "年齢"

I18nは、現在のlocaleに対応する翻訳ファイル(ja.yml)は自動で読み込んでくれますが、上記のディレクトリ構成にしたmodelやviewの翻訳ファイルは自動で読み込まれません。

config/locales/以下に設定した翻訳ファイルが全て読み込まれるように、以下のコードを設定する必要があります。

config/application.rb | 翻訳ファイルが全て読み込まれるように設定する
1
2
3
4
5
6
7
8
9
module I18nApp
  class Application < Rails::Application
    config.load_defaults 5.2
    config.i18n.default_locale = :ja

   # 以下のコードを追加する
    config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}').to_s]
  end
end

サーバーを再起動させて「localhost:3000/users/new」にアクセスして、以下のように確認するとUserモデルの翻訳が反映されてラベルを日本語に表示する事が出来ました。

ラベルの日本語化

今回解説したディレクトリ構成は、例として簡単な構成にしましたが、翻訳設定が多い場合はconfig/locales/models/config/locales/views/以下にディレクトリを作成してmodelやviewごとに分けることもできます。

URLパラメーターでlocaleを設定
リンクをコピーしました

I18nでは、以下のようにURLクエリパラメータで使用したいlocaleを設定する事が出来ます。

URLクエリパラメータにlocaleを設定する
1
2
http://localhost:3000/users/new?locale=en # 英語を使用する
http://localhost:3000/users/new?locale=ja # 日本語を使用する

URLクエリパラメーターでlocaleを設定

上記は、ApplicationControllerを以下のように記述する事でURLクエリパラメーターで送信されたlocaleに設定する事が出来ます。

app/controllers/application_controller.rb | URLクエリパラメーターのlocaleを設定する
1
2
3
4
5
6
7
8
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

参照:Railsガイド 2.2 リクエスト間でロケールを管理する

ちなみに、韓国語や中国語は、以下のように変更することが出来ます。

URLクエリパラメータにlocaleを設定する
1
2
http://localhost:3000/users/new?locale=ko # 韓国語を使用する
http://localhost:3000/users/new?locale=zh-CN # 中国語を使用する

どちらもGithubにテンプレートが用意されているので、以下のようにconfig/locales/以下に配置します。

翻訳ファイルの設置

ファイルには、翻訳したい文言を設定することで対応する言語に翻訳することが出来ます。

enum
リンクをコピーしました

enumとは、1つのカラムに指定した複数個の定数を保存できる仕組みですが、I18nを併用する事でこの定数名を設定したデフォルト言語に翻訳する事が出来ます。

それでは、i18n_appアプリケーションにenumを追加して日本語化する手順を解説します。enumが分からない方は、enumチュートリアルを参考にしてください。

1.アプリケーションにenumを追加する
リンクをコピーしました

i18n_appアプリケーションにenumを追加するので、初期設定等を行なってない場合はアプリケーションを日本語化対応する手順を参照してください。

まずは、以下のコマンドを実行してusersテーブルにenum用のroleカラムを追加します。

ターミナル | enum用のroleカラムを追加する
1
rails g migration AddColumnToUser role:integer

作成されたマイグレーションファイルに、以下のようにnull: falsedefault: 0(初期値には0)を追加してマイグレーションを実行します。

db/migrate/日時_add_column_to_user.rb | nullとdefaultを追加する
1
2
3
4
5
class AddColumnToUser < ActiveRecord::Migration[5.2]
  def change
    add_column :users, :role, :integer, null: false, default: 0 # nullとdefaultを追加する
  end
end
ターミナル | マイグレーションを実行する
1
rails db:migrate

次に、モデルの定義を参考にして、以下のようにroleカラムの値(0,1,2)にそれぞれowner, member, guestの定数を設定します。

app/models/user.rb | Userモデルにenumを定義する
1
2
3
class User < ApplicationRecord
  enum role: { owner: 0, member: 1, guest: 2 }
end

ユーザーの登録フォームでrole(権限)も登録出来るように、以下のコードを追加して権限のセレクトボックスを作成します。

app/views/users/_form.html.erb | Userモデルにenumを定義する
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<%= form_with(model: user, local: true) do |form| %>
  <%# name, ageのコードを省略 %>

  <%# ここから下のコードを追加する %>
  <div class="field">
    <%= form.label :role %>
    <%= form.select :role, User.roles.keys.map {|k| [k, k]}, {}, { class: 'form-control', style: 'margin-bottom: 15px;', data: {} } %>
  </div>
  <%# ここまで %>

  <div class="actions">
    <%= form.submit %>
  </div>
<% end %>

上記コードの詳しい解説は、「formにenumを追加する方法」を参考にしてください。

次に、roleのデータを登録できるようにするために、以下のようにUsersControllerストロングパラメーターroleを追加します。

app/controllers/users_controller.rb |
1
2
3
4
5
class UsersController < ApplicationController
    def user_params
      params.require(:user).permit(:name, :age, :role) # roleを追加
    end
end

そして、追加したUserモデルのrole名を「role」から「権限」に翻訳させるために、ja.ymlファイルに以下を追加します。

config/locales/models/ja.yml | roleの日本語の翻訳を追加する
1
2
3
4
5
6
7
8
9
ja:
  activerecord:
    models:
      user: "ユーザー"
    attributes:
      user:
        name: "名前"
        age: "年齢"
        role: "権限" # 追加する

サーバーを再起動させて「localhost:3000/users/new」にアクセスすると、以下のように権限のセレクトボックスが追加されています。

権限のセレクトボックスが追加

2. 権限の定数名を翻訳する
リンクをコピーしました

権限のセレクトボックスを追加することが出来ましたが、以下のように表示される定数名は英語表記のままです。この権限の定数名をI18nを使って日本語に翻訳します。

権限の定数名が英語表記のままの状態

Userモデルに追加したenumの設定をもう一度確認しましょう。

app/models/user.rb | Userモデルにenumを定義する
1
2
3
class User < ApplicationRecord
  enum role: { owner: 0, member: 1, guest: 2 }
end

上記を確認すると、roleの値はそれぞれowner, member, guestが定数名として定義されているので以下のようにroles以下に指定します。

config/locales/models/ja.yml | roleの定数名を日本語に翻訳する
1
2
3
4
5
6
7
8
9
10
11
12
13
ja:
  activerecord:
    models:
      user: "ユーザー"
    attributes:
      user:
        name: "名前"
        age: "年齢"
        role: "権限"
        roles: # ここから下を追加
          owner: "オーナー"
          member: "メンバー"
          guest: "ゲスト"

ja.ymlファイルに設定した翻訳を表示できるように、日本語表示のselectboxを作成を参考にして、roleのセレクトボックスを以下のように変更します。

app/views/users/_form.html.erb | セレクトボックスを日本語化対応させる
1
2
3
4
5
<%# 変更前 %>
<%= form.select :role, User.roles.keys.map {|k| [k, k]}, {}, { class: 'form-control', style: 'margin-bottom: 15px;', data: {} } %>

<%# 変更後 %>
<%= form.select :role, options_for_select(User.roles.map { |k, _v| [t("activerecord.attributes.user.roles.#{k}"), k] }), { class: 'form-control', style: 'margin-bottom: 15px;', data: {} } %>

サーバーを再起動させて再び「localhost:3000/users/new」にアクセスすると、以下のように権限のセレクトボックスを日本語に表示する事が出来ました。

権限のセレクトボックスを日本語に表示

注意点
リンクをコピーしました

enumにI18nを使い場合は、翻訳ファイルに設定するキー名に気をつけてください。

今回の権限の場合で考えると、以下のようにrole配下の階層に定数名をそのまま定義する事が出来そうですが、これはenumの他の機能の仕様と重なってしまうため以下のようにエラーが発生します。

config/locales/models/ja.yml | roleの定数名の設定が間違っている例
1
2
3
4
5
6
7
8
9
10
11
12
ja:
  activerecord:
    models:
      user: "ユーザー"
    attributes:
      user:
        name: "名前"
        age: "年齢"
        role: "権限"  # role配下に定数名の翻訳を設定
          owner: "オーナー"
          member: "メンバー"
          guest: "ゲスト"

enumのキーを間違えてエラーが発生する例

そのため、以下のようにroleと同じ階層にrolesを配置し、その中で定数名を定義する事で日本語の翻訳をする事が出来ます。

config/locales/models/ja.yml | roleの定数名の設定が正しい例
1
2
3
4
5
6
7
8
9
10
11
12
13
ja:
  activerecord:
    models:
      user: "ユーザー"
    attributes:
      user:
        name: "名前"
        age: "年齢"
        role: "権限"
        roles: # roles以下に定数名の翻訳を設定
          owner: "オーナー"
          member: "メンバー"
          guest: "ゲスト"

enumでI18nを使用する場合は、enumを使用するカラム名を複数形にして定数名を日本語へ翻訳するように気をつけてください。

まとめ
  • I18nとは、ある言語の文言を別の言語の文言に翻訳してくれる機能のことです。
  • config/locales/以下に翻訳ファイルを配置することで、現在の言語に対応する翻訳文を取得して表示します。
  • エラーメッセージやアプリケーション内の文言をI18nに設定することで、国際化対応することが出来ます。