Rails
devise
9
どのような問題がありますか?

この記事は最終更新日から1年以上が経過しています。

投稿日

更新日

Organization

【Rails】devise-i18nでscopedなビューを翻訳するワザ

Devise を使えば、Rails アプリにユーザー登録・認証の機能を少ない工数で追加できる。筆者もよくお世話になっているgemの一つ。

Devise そのものには日本語などの翻訳は含まれていないが、devise-i18n gem を追加することで、翻訳が利用可能になる。

しかし、Devise で複数の scope(UserAdmin で分けるケースなど)を使っていると、devise-i18n で生成したビューはそのままでは translation missing になってしまう。これをうまく回避する。

translation missingの原因

たとえば、以下のコマンドでビューを生成して、

$ bin/rails g devise:i18n:views users

/users/sign_in などを見ると、以下のように(一部が)翻訳されていないことがわかる。

image.png

これは、devise-i18n で生成されるビューが、t の引数に相対指定をしているのが原因1

app/views/users/sessions/new.html.erb
<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つある。

  1. t の引数を、相対指定から絶対指定にすべて書き換える
  2. 翻訳の YAML に、当該のビューに対応するキーを追加して、その下に一通りの翻訳をコピーする

1.は書き換えるファイルが多く面倒だし、せっかく自動生成しているメリットをあまり生かせない。2.は単純にコピーすると二重管理になってしまって良くないが、YAML のアンカーとエイリアスを使えば回避できる。今回は2.の方法を使う。

※ YAML のアンカーとエイリアスについては、この記事などが詳しい: プログラマーのための YAML 入門 (初級編)

エイリアスで翻訳を共有

まず、以下のコマンドで翻訳ファイルを生成する。

$ bin/rails g devise:i18n:locale ja

config/locales/devise.views.ja.yml に翻訳ファイルが生成されるので、このファイルを以下のように変更する。

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 モデルなら usersAdmin なら admins)をそれぞれ作り、先程のアンカーをエイリアスで参照する。エイリアスは * 記号を使う。

  # インデントはdevise:と同じレベルに合わせる
  users: *devise
  admins: *devise

もしスコープが増えたら、同じようにキーとエイリアスを追加する。

これで、翻訳されるようになる:tada:

image.png


  1. たとえばこのケースであれば、ビューのファイルが位置するusers/sessions/ディレクトリを元に、users.sessions.sign_inというキーの翻訳を探しにいく。 

ユーザー登録して、Qiitaをもっと便利に使ってみませんか。
  1. あなたにマッチした記事をお届けします
    ユーザーやタグをフォローすることで、あなたが興味を持つ技術分野の情報をまとめてキャッチアップできます
  2. 便利な情報をあとで効率的に読み返せます
    気に入った記事を「ストック」することで、あとからすぐに検索できます
ユーザー登録ログイン
notozeki
ソフトウェアエンジニア

コメント

この記事にコメントはありません。
あなたもコメントしてみませんか :)
ユーザー登録
すでにアカウントを持っている方はログイン
記事投稿イベント開催中
React 18、あなたならどう使いこなす?
~
Zoom API/SDKを使ってみよう!
~
9
どのような問題がありますか?
ユーザー登録して、Qiitaをもっと便利に使ってみませんか

この機能を利用するにはログインする必要があります。ログインするとさらに下記の機能が使えます。

  1. ユーザーやタグのフォロー機能であなたにマッチした記事をお届け
  2. ストック機能で便利な情報を後から効率的に読み返せる
ユーザー登録ログイン
ストックするカテゴリー