Railsでi18n化した時は本番環境の設定にも注意が必要


Railsでi18n化した際、開発環境と本番環境で翻訳文に差異が出てしまったので、その解消法メモ。

環境

  • Ruby 2.4.1
  • Rails 5.1.4

概要

Railsガイドの2.3 ロケールの設定と受け渡しに従いi18n化し、ローカルの開発環境では実装通りの英語表記がされるようになった。
しかし本番環境のHerokuにデプロイ後、例えばブログ一覧画面において、下記のようになぜか中途半端な英語表記になってしまった。

ローカルでの表示 本番環境(Heroku)での表示

Viewの記述

ブログ一覧を表示する index.html.erb の記述は以下の通り。
文言に関する部分をtメソッドで記述し、具体的な文言をja.ymlen.ymlで定義する、という感じ。

<h1 class="title"><%=t :blog_list %></h1>
<div class="container">
  <div class="row">
    <% @blogs.each do |blog| %>
      <div class="col-xs-12 col-md-6 blog-panel">
        <h2><%= blog.title %></h2>
        <p><%= blog.content %></p>
        <p><%=t :author %>:<%= blog.user.name %></p>
        <p><%=t :created_at %>:<%= blog.created_at %></p>
        <div class="blog-link">
          <%= link_to t(:detail), blog_path(blog.id), class: "btn btn-default" %>
          <% if blog.user == current_user %>
            <%= link_to t(:edit), edit_blog_path(blog.id), class: "btn btn-info" %>
            <%= link_to t(:delete), blog_path(blog.id), method: :delete, data: { confirm: "削除しますか?" }, class: "btn btn-danger" %>
          <% else %>
            <%= link_to t(:edit), '', class: "btn btn-info", disabled: "disabled" %>
            <%= link_to t(:delete), '', class: "btn btn-danger", disabled: "disabled" %>
          <% end %>
        </div>
      </div>
    <% end %>
  </div>
</div>

I18n.load_pathしてみた結果、返って来た配列の要素に以下が含まれているため、ロケール設定のymlファイルは正しく読み込めている様子。

"/app/config/locales/en.yml", "/app/config/locales/ja.yml", "/app/config/locales/model.en.yml", "/ap p/config/locales/model.ja.yml"

結果

config/environments/production.rbconfig.i18n.fallbacksの値をtrueからfalseに変更することで解決した。

# Enable locale fallbacks for I18n (makes lookups for any locale fall back to
# the I18n.default_locale when a translation cannot be found). |
config.i18n.fallbacks = false

デフォルトコメントの上2行にヒントが隠されていて、fallbacks = trueの時は、
en.ymlから翻訳文が見つからない場合は、検索対象をデフォルトのロケール(この場合はja)に戻していた模様。

私の場合、en.ymlには最低限の訳文しか書いておらず、例えば「ブログ一覧」のような見出しの英訳が見つからず、デフォルトである日本語の見出しが表示されていた…ということだと思われる。

fallbacks = falseとすると、en.ymlで指定がない限りはtメソッドの引数を(snake_case)->(Camel Case)に変換した文字列が表示されるため狙い通りの表記となるようです。

上記の仕様を把握していればen.ymlに余計な訳文を書く必要はないが、理解が曖昧なままであれば大人しくen.ymlにもきっちり訳文を記述しておいた方がいいでしょう。