Devise を使えば、Rails アプリにユーザー登録・認証の機能を少ない工数で追加できる。筆者もよくお世話になっているgemの一つ。
Devise そのものには日本語などの翻訳は含まれていないが、devise-i18n gem を追加することで、翻訳が利用可能になる。
しかし、Devise で複数の scope(User
と Admin
で分けるケースなど)を使っていると、devise-i18n で生成したビューはそのままでは translation missing
になってしまう。これをうまく回避する。
translation missingの原因
たとえば、以下のコマンドでビューを生成して、
$ bin/rails g devise:i18n:views users
/users/sign_in
などを見ると、以下のように(一部が)翻訳されていないことがわかる。
これは、devise-i18n で生成されるビューが、t
の引数に相対指定をしているのが原因1。
<h2><%= t(".sign_in") %></h2><%# ←❗️こことか %>
<%= simple_form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
<div class="form-inputs">
<%= f.input :email, required: false, autofocus: true %>
<%= f.input :password, required: false %>
<%= f.input :remember_me, as: :boolean if devise_mapping.rememberable? %>
</div>
<div class="form-actions">
<%= f.button :submit, t(".sign_in") %><%# ←❗️このあたり %>
</div>
<% end %>
<%= render "users/shared/links" %>
これをなんとかしたい。
解決策
採れうる策は2つある。
-
t
の引数を、相対指定から絶対指定にすべて書き換える - 翻訳の YAML に、当該のビューに対応するキーを追加して、その下に一通りの翻訳をコピーする
1.は書き換えるファイルが多く面倒だし、せっかく自動生成しているメリットをあまり生かせない。2.は単純にコピーすると二重管理になってしまって良くないが、YAML のアンカーとエイリアスを使えば回避できる。今回は2.の方法を使う。
※ YAML のアンカーとエイリアスについては、この記事などが詳しい: プログラマーのための YAML 入門 (初級編)
エイリアスで翻訳を共有
まず、以下のコマンドで翻訳ファイルを生成する。
$ bin/rails g devise:i18n:locale ja
config/locales/devise.views.ja.yml
に翻訳ファイルが生成されるので、このファイルを以下のように変更する。
ja:
activerecord:
attributes:
user:
confirmation_sent_at: パスワード確認送信時刻
# ...(略)...
models:
user: ユーザ
devise: &devise # ←❗️①
confirmations:
confirmed: メールアドレスが確認できました。
# ...(略)...
users: *devise # ←❗️②
admins: *devise # ← ❗️②
① まず、生成された翻訳ファイルの devise
というキーに YAML のアンカーを設定する。アンカーは &
記号を使う。
devise: &devise
② 次に、ファイルの末尾あたりに、スコープと同名のキー(例: User
モデルなら users
、Admin
なら admins
)をそれぞれ作り、先程のアンカーをエイリアスで参照する。エイリアスは *
記号を使う。
# インデントはdevise:と同じレベルに合わせる
users: *devise
admins: *devise
もしスコープが増えたら、同じようにキーとエイリアスを追加する。
これで、翻訳されるようになる
-
たとえばこのケースであれば、ビューのファイルが位置する
users/sessions/
ディレクトリを元に、users.sessions.sign_in
というキーの翻訳を探しにいく。 ↩