Rails6 のちょい足しな新機能を試す23（I18n fallbacks編）

# はじめに

Rails 6 に追加されそうな新機能を試す第23段。 今回のちょい足し機能は、 `I18n fallbacks` 編です。
Rails 6.0 では、 `config.i18n.fallbacks` の設定で、明示的に I18n.default_locale を fallback として指定していないとDEPRECATION WARNING が出ます。fallbacks の挙動は、Rails 6.0 と Rails 6.1 で違いがあると思われます。

Ruby 2.6.3, Rails 6.0.0.rc1 で確認しました。Rails 6.0.0.rc1 は `gem install rails --prerelease` でインストールできます。

```shell
$  rails --version
Rails 6.0.0.rc1
```

# Rails プロジェクトを作る

```shell
$ rails new rails6_0_0rc1
$ cd rails6_0_0rc1
```

# Controller と View を作る

今回はモデルなしで、試します。

```shell
$ bin/rails g controller i18n_fallbacks index
```

# db:create をしておく

```shell
$ bin/rails db:create
```

# `development.rb` に fallbacks の設定を追加する

`config/environments/development.rb` に fallbacks を設定します。

```ruby:config/environments/development.rb
Rails.application.configure do
  ...
  config.i18n.fallbacks = [{de: :ja}]
end
```

# locale 変換用のファイルを用意する

英語(en)、日本語(ja)、ドイツ語(de) の3つを用意します。
1つの yml ファイルに全部の訳語が揃ってしまうと fallbacks の動作を確認できないので、揃わないようにします。


```yaml:config/locales/en.yml
en:
  morning: "Good Morning"
```

```yaml:config/locales/ja.yml
ja:
  afternoon: こんにちは
```

```yaml:config/locales/de.yml
de:
  night: Gute Nacht
```

# `index.html.erb` を編集する

本来、 with_locale は、ApplicationController で使うべきだと思いますが、今回は手抜きで View だけでやります。

```erb:app/views/i18n_fallbacks/index.html.erb
<% I18n.with_locale(:de) do %>
  <h1>I18n Fallbacks Test</h1>
  <h2>I18n settings</h2>
  <ul>
    <li>I18n.default_locale = <%= I18n.default_locale %></li>
    <li>I18n.locale = <%= I18n.locale %></li>
    <li>I18n.fallbacks = <%= I18n.fallbacks %></li>
  </ul>

  <h2>I18n translations</h2>
  <ul>
    <li>morning=<%= t(:morning) %></li>
    <li>afternoon=<%= t(:afternoon) %></li>
    <li>night=<%= t(:night) %></li>
  </ul>
<% end %>
```

# `rails server` を実行してブラウザで表示する

`rails server` を実行して、 http://localhost:3000/i18n_fallbacks/index にアクセスします。
ログに DEPRECATION WARNING が表示されます。

```
DEPRECATION WARNING: Using I18n fallbacks with an empty `defaults` sets the defaults to include
the `default_locale`. This behavior will change in Rails 6.1. If you desire the default locale 
to be included in the defaults, please explicitly configure it with `config.i18n.fallbacks.defaults 
= [I18n.default_locale]` or `config.i18n.fallbacks = [I18n.default_locale, {...}]`. If you want 
to opt-in to the new behavior, use `config.i18n.fallbacks.defaults = [nil, {...}]`. 
(called from <main> at /app/config/environment.rb:5)
```

ブラウザの表示はこんな感じになります
![2019-05-24-083631_383x299_scrot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209941/4129e676-e217-3aa7-d560-300bc41e6693.png)


# fallbacks の設定を変更する

fallbacks の設定を変更してみます。明示的に `I18n.default_locale` を追加します。

```ruby:config/environments/development.rb
Rails.application.configure do
  ...
  config.i18n.fallbacks = [I18n.default_locale, {de: :ja}]
end
```

再度 `rails server` を起動し直して、ブラウザでページを表示すると今度は、 `DEPRECATION WARNING` が表示されません。
ブラウザの表示内容は変わりません。
DEPRECATION WARNING の意味するところは、「 `I18n.default_locale` を設定していなくても、Rails 6.0 では、 Rails内部で `I18n.default_locale` を追加するけど、Rails6.1 では挙動が変わるので、明示的に `I18n.default_locale` を追加するようにしてね」ということみたいです。

# fallbacks の設定を再度変更する

DEPRECATION WARNING の最後に

> If you want to opt-in to the new behavior, use `config.i18n.fallbacks.defaults = [nil, {...}]

とありますので、恐らくこれが、Rails 6.1 での挙動になると思われます。設定を変更して試してみます。

```ruby:config/environments/development.rb
Rails.application.configure do
  ...
  config.i18n.fallbacks = [nil, {de: :ja}]
end
```

ブラウザの表示内容が以下のように変わります。
en (I18n.default_locale) が fallback のリストから消えています。
また、 `morning` が `Goog Morning` に変換されていません。
![2019-05-24-090101_369x290_scrot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209941/44e765ca-1cd0-a058-14ec-b7d460820ed2.png)

# fallbacks の設定を再度変更する

自動生成された `config/environments/production.rb` では、

```ruby:config/environments/production.rb
  config.i18n.fallbacks = true
```

となっているので、 fallbacks が true のときにどうなるのか確認します。

このときは、  `I18n.default_locale` が fallbacks に含まれています。
![2019-05-24-090406_349x282_scrot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/209941/b3d4d986-599f-11e2-be87-b8575cee87a1.png)

# まとめ

Rails 6.0 で DEPRECATION WARNING が出た場合は、 `I18n.default_locale` を設定するのが良さそうです。

# 試したソース

試したソースは以下にあります。
https://github.com/suketa/rails6_0_0rc1/tree/try023_i18n_fallbacks

# 参考情報

* [What is new in Rails 6.0](https://bogdanvlviv.com/posts/ruby/rails/what-is-new-in-rails-6_0.html)
* [update I18n fallbacks configuration to be compatible with i18n 1.1.0](https://github.com/rails/rails/pull/33574)
* [Describe how to silence the deprecation warning about empty I18n fallbacks](https://github.com/rails/rails/pull/35052)
* [2.2 Managing the Locale across Requests](https://edgeguides.rubyonrails.org/i18n.html#managing-the-locale-across-requests)