【Rails】I18nを使用した多言語対応(日本語化)

はじめに

Ruby on Railsのデフォルトの言語は英語です。デフォルト言語が英語ということで一番初めに困るのは、エラーメッセージが英語で表示されることでしょう。バリデーションエラーにより表示されたメッセージが英語だと、とてもユーザーフレンドリーなアプリケーション設計とはいえません。

Railsには、このようなエラーメッセージを多言語化(もちろん日本語化も)する機能があります。エラーメッセージ以外にも、例えばビューで使用する文字列なども簡単に変換することができます。

本記事では、I18nを使用した多言語対応についてまとめています。

I18nについて

I18nとはRubyのGemのひとつで、「Internationalization(国際化)」の略記です。Rails 2.2から標準同梱されているのでインストールすることなく使えます。

Railsアプリの日本語化

手っ取り早くRailsアプリを日本語化したいだけなら、次の手順を行います。

config/application.rbに以下を追記します。Railsアプリのデフォルト言語を英語(en)から日本語(ja)に変更します。これにより、ロケールファイルのうち、ja配下の翻訳が使用できるようになります。また、config/locales/ディレクトリ配下の拡張子がrbまたはymlのファイルをロケールファイルとして追加します。

module ApplicationName
  class Application < Rails::Application
    # 以下を追記
    config.i18n.default_locale = :ja
    config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}').to_s]
  end
end

rails-i18nのGitHubから日本語のロケールファイルをダウンロードし、config/locales/ディレクトリに配置します。

config
 |-locale
    |-en.yml
    |-ja.yml   # 追加

以上で日本語化対応は完了です。バリデーションのエラーメッセージなどが日本語されていることを確認してください。

I18nの使い方

ロケールファイルの形式

I18nのロケールファイルでは、Ruby形式(rb)とYAML形式(yml)2種類のファイル形式をサポートしています。どちらの形式で書いても構いませんが、書き方が若干異なるので注意が必要です。

Ruby形式(rb)の書き方は以下の通りです。

{
  ja: {
    article: {
      title: 題名,
      content: 内容
    }
  }
}

YAML形式(yml)の書き方は以下の通りです。

ja:
  article:
    title: 題名
    content: 内容

見て分かる通り、{}を書かなくて言い分、YAML形式のほうが簡単に書けます。Railsにデフォルトで用意されている英語のロケールファイルもYAML形式で書いてあるので、自分でロケールファイルを作成するときもYAML形式で書くのがいいかと思います。

なお、新しいロケールファイルを追加した場合はサーバーを再起動する必要があります(追記の場合は不要)。

ロケールファイルの書き方

ロケールファイルの基本的な書き方は、階層ごとにインデントを足していくだけという非常にシンプルなものですが、特別な階層名を使用することでより便利に使うことができます。なお、以下の分け方は独断によるものなので、公式見解とは異なる可能性があります。

ビューの翻訳

日本語の識別子jaの次の階層をコントローラー名、次の階層をビューのファイル名とし、その次の階層にビュー内で使用する文字列の翻訳を書きます。ビュー内ではスコープを省略して翻訳を呼び出すことがでるようになります。以下の例だと、articles/index.html.erb内ではt(".title")のように呼び出すことができます。

ja:
  articles:
    index:
      title: 題名
      content: 本文

モデルの翻訳

日本語の識別子jaの次の階層をactiverecordとし、modelsの下にモデル名、attributesの下にモデル名とカラム名の翻訳を書きます。このような翻訳は特別な識別子で呼び出すことができるようになります。以下の例だと、モデル名はArticle.model_name.human、カラム名はArticle.human_attribute_name(:title)で呼び出すことができます。

なお、カラム名の次の階層にカラムの値を書いても、特別な識別子で呼び出せるようになるわけではありません。

ja:
  activerecord:
    models:
      article:  記事
    attributes:
      article:
        title: 題名
        content: 本文

エラーメッセージの翻訳

I18nはエラーメッセージの翻訳をロケールファイルの中から以下の優先度で探索します。最も優先度の低い翻訳も見つからなければデフォルト(英語)のエラーメッセージが表示されます。

1. activerecord.errors.models.[model_name].attributes.[attribute_name]
2. activerecord.errors.models.[model_name]
3. activerecord.errors.messages
4. errors.attributes.[attribute_name]
5. errors.messages

rails-i18nの日本語のロケールファイルにはactiverecord.errors.messageserrors.messagesが含まれています。特定のモデルのバリデーションでこれらの翻訳を使用したくないという場合、それより優先度の高いactiverecord.errors.models.[model_name].attributes.[attribute_name]などの翻訳を追加する必要があります。

タグを含む翻訳

翻訳にタグを含めることができます。末尾に_htmlのついたキーと、htmlというキーの翻訳に含まれるタグはビューでそのまま描画されます。タグも文字列として描画したいならrawキーワードを使います。

ja:
  articles:
    title_html: <h1>題名</h1>
    content:
      html: <b>本文</b>
<%= t("articles.title_html") %>
<%= t("articles.content.html") %>

<%= raw(t("articles.title_html")) %>
<%= raw(t("articles.content.html")) %>

改行を含む翻訳

翻訳に改行を含めるには以下のように記述します。

ja:
  articles:
    content: |
      本文1行目
      本文2行目

# または

ja:
  articles:
    content: >
      本文1行目
      本文2行目

次に、以下のように翻訳を呼び出します。

<%= simple_format(t("articles.content")) %>

また、上記の「タグを含む翻訳」セクションで説明した通り、<br />タグを使うことでも改行することができます。

ja:
  articles:
    content_html: "本文1行目<br />本文2行目"

翻訳の呼び出し

ロケールファイルの翻訳を呼び出すには、I18n.tメソッドとI18n.lメソッドを使うか、Railsのヘルパーメソッドtメソッドとlメソッドを使うことができます。

ビューの呼び出し

ビューでロケールファイルの翻訳を呼び出すには以下のように記述します。

<%= t("articles.index.title") %>

ビューarticles/index.html.erb内で上記を呼び出す場合、以下のようにスコープを省略して書くこともできます。

<%= t(".title") %>

モデルの呼び出し

モデルでロケールファイルの翻訳を呼び出すには以下のように記述します。

@model = Article.model_name.human
@column = Article.human_attribute_name(:title)

以下のようにスコープを使った書き方でも呼び出すことができます。

@model = I18n.t("activerecord.models.article")
@column = I18n.t("activerecord.attributes.article.title")

正直、どちらの書き方でも長さはそんなに変わりません。特別な呼び出し方を用意するのならもう少し短い名前にしても良かったんじゃないかと思います(特にhumanが謎)。

日付/時間の呼び出し

日付/時間を現地のフォーマットに変換したい場合、以下のように記述します。

<%= l(Time.now) %>

formatオプションで長い日付/時間形式や短い日付/時間形式を呼び出すこともできます(何も指定しなければデフォルト)。

<%= l(Time.now, format: :long) %>

日付/時間でフォーマットの翻訳を記述しておく必要があります。

ja:
  time:
    formats:
      default: "%Y年%m月%d日(%a) %H時%M分%S秒 %z"
      long: "%Y/%m/%d %H:%M"
      short: "%m/%d %H:%M"

まとめ

デフォルト言語を日本語に設定し、日本語のロケールファイルを用意するだけでRailsアプリの日本語化はできてしまいます。しかし、開発を進めているとそれだけでは不十分となってきて、自分でロケールファイルを書く必要が出てきます。ロケールファイルは自由に書くこともできますが、一定のルールを覚えておくとより便利に書くこともできます。

本記事を参考にして、Railsアプリの多言語対応(日本語化)を行っていただければと思います。

関連記事

【Rails】Railsアップグレードまとめ
# はじめに Ruby on Railsに限らず、何らかのフレームワークを使ってWebシステムを構築している場合、フレームワークのアップグレード作業は避けて通れません。 一般的にフレームワークはバージョン毎にEOL (End of Life [...]
2022年10月1日 14:32
【Rails】ユーザー登録時に行うメールアドレス認証機能の実装方法
# はじめに ユーザー登録/解除やログイン/ログアウトといった認証機能の導入に「devise」というGemを使っている人は多いと思います。「devise」では以下のように記述するだけで、ユーザー登録時に確認メールを送付しメールアドレス認証を行う機 [...]
2022年9月24日 14:24
【Rails】モデルに列挙型(enum)を定義し、使いこなす方法
# はじめに Railsはモデルでカラム名と同名の列挙型(enum)を定義することで、カラムと列挙型の変数を紐付けることができます。カラムと列挙型の変数を紐付けると、カラムに対して様々な便利な使い方ができるようになります。 本記事では、モデ [...]
2022年9月3日 10:29
【Rails】RailsでCORSとPreflight requestの設定を行う方法
# はじめに RailsアプリをAPIサーバーとして構築するには、CORS (Cross-Origin Resource Sharing)と Preflight requestの設定を行う必要があります。APIサーバーは外部からの要求に対して処理 [...]
2022年8月27日 10:44
【Ruby】Bundlerを使ってRubyGemsを作成/公開する方法
# はじめに Bundlerを使ってRubyGemsを作成および公開する方法について説明します。Bundlerを使わずにRubyGemsを作成/公開する方法については以下の記事を参照してください。 <iframe class="hatena [...]
2022年7月12日 23:18
【Ruby】RubyGemsを作成/公開する方法
# はじめに RubyGemsを作成および公開する方法について説明します。Bundlerを使ってRubyGemsを作成する方法については以下の記事を参照してください。 <iframe class="hatenablogcard" style [...]
2022年7月11日 21:52
【Rails】M1チップ搭載MacでRuby on Railsの開発環境構築
# はじめに M1チップ搭載MacにRuby on Railsの開発環境を構築する手順を記載します。 - MacBook Air (M1, 2020) - macOS Monterey 12.3.1 # Homebrew ## [...]
2022年5月5日 11:56
【Rails】Rakeタスクの基本情報と作成・実行方法
# はじめに Railsには標準でRakeというGemが同梱されています。RakeはRubyで実装されたMake(UNIX系のOSで使用できるコマンド)のようなビルド作業を自動化するツールです。Ruby Make、略してRakeというわけですね。 [...]
2022年3月7日 22:12