rails での config/locales 配下の扱い

[Okinawa.rb Advent Calendar 2016](http://qiita.com/advent-calendar/2016/okinawarb) 15日目。 :bell:
最近はまったくと言っていいほど meet up に参加できていません。来年からはちょいちょい参加するつもりです。

Rails の config/locales 配下の扱い方を備忘録がてらまとめてみました。

# rails new 直後 (en.yml)
`rails new hoge` すると以下のファイルがあるだけです。

```ruby:config/locales/en.yml
en:
  hello: "Hello world"
```

# gemの導入 (translation_ja.yml)

次に i18n_generators の導入が王道だと思います。

```ruby:Gemfile
gem 'i18n_generators'
```

して、 `rails g i18n ja` を実行すると

config/locales/ja.yml
と
config/locales/translation_ja.yml

が生成されます。後者はモデルに対応したファイルで、モデルに変更があった場合、こちらもメンテすることになると思います。
ちなみに私はこのファイルはドキュメントを作る上で用語集として参考として利用してたりします。


普通に開発していくと config/locales/translation_ja.yml を常にメンテする状態が続くと思います。
ja.yml の方はほとんどいじったことがありません。

# ギュッと詰め
以下は色々な書き方を詰め込んでみました。
`I18n.locale = :ja` していることを前提に各々を解説します。
尚、色々な要素を詰め込んでいるのでわざとファイル名は hoge としています。

```ruby:config/locales/hoge.yml
     1  ja:
     2    date:
     3      abbr_day_names:
     4      - 日
     5      - 月
     6      - 火
     7      - 水
     8      - 木
     9      - 金
    10      - 土
    11    hello: 'こんにちは'
    12    world_html: '<b>世界</b>'  # HTML 書きたいなら key名に _html の suffix を付与すれば良い
    13    title: The book(%{published}) # 変数渡したいならこう書く
    14    activerecord:
    15      models:
    16        user: '会員'
    17        blog: 'ブログ'
    18      attributes:
    19        user:
    20          id: '会員番号'
    21        blog:
    22          user: :activerecord.models.user
    23          user_id: :activerecord.attributes.user.id
```

## 3行目～10行目: 配列
普通の配列です。これは rails ではなく yaml の話ですね。
一応、基本ということで。

```ruby
irb> I18n.t('date.abbr_day_names')
=> ["日", "月", "火", "水", "木", "金", "土"]
irb> I18n.t('date.abbr_day_names').class
=> Array
```
11行目は基本なので割愛。

## 12行目: HTML
HTML 書きたいなら key名に _html の suffix を付与すれば良いです。
以下の例では単なる文字列ですが、view で使うとよしなにエスケープしてくれます。
view helper 側の機能だそうです。

```ruby
irb> I18n.t(:world_html)
=> "<b>世界</b>"
```

## 13行目: 式展開
```ruby:config/locales/hoge.yml
    13    title: The book(%{published}) # 変数渡したいならこう書く
```

tメソッドに引数で渡せばOKです。

```ruby
irb> I18n.t(:title, published: 'hoge') # hash 渡すよ
=> "The book(hoge)"

irb> I18n.t(:title)
=> "The book(%{published})" # 引数渡さないとこうなっちゃう
```

## 14行目～20行目: ActiveRecord
```ruby:config/locales/hoge.yml
    14    activerecord:
    15      models:
    16        user: '会員'
    17        blog: 'ブログ'
    18      attributes:
    19        user:
    20          id: '会員番号'
```


普通に i18n_generators で transration_ja.yml が生成されるのと同じです。
ActiveRecord の User モデルや Blog モデルが存在すれば以下のように参照することも可能です。

```ruby
irb> User.model_name.human
=> "会員"
irb> User.human_attribute_name(:id)
=> "会員番号"
```

もちろんモデルが無くても

```ruby
irb> I18n.t('activerecord.models.user')
=> "会員"

irb> I18n.t('activerecord.attributes.user.id')
=> "会員番号"
```

で参照できます。

## 22行目～23行目
```ruby:config/locales/hoge.yml
    21        blog:
    22          user: :activerecord.models.user
    23          user_id: :activerecord.attributes.user.id
```

yml ファイル内で参照したい場合は以下のように記述して DRY にできます。

```ruby
irb> I18n.t('activerecord.attributes.blog.user')
=> "会員"

irb> I18n.t('activerecord.attributes.blog.user_id')
=> "会員番号"
```

# view との連携

モデルではなくビューを翻訳してみましょう。
t メソッドに長ったらしい key を書くのは面倒なので省略できます。

```html+erb:app/views/projects/index.html.erb
<h1><%= t('.title') %></h1> <%# 冗長な書き方だと右記になる。 t('projects.index.title') %>
```
上記のように view のファイル内にて `.title` と記述します。
翻訳ファイルは以下のようにします。ファイルの階層と yaml の階層が一致している事に着目してください。

```yaml
ja:
  projects: # app/views/projectsを表す
    index:  # app/views/projects/index.html.erb
      title: "プロジェクト一覧"
```

ちなみに rails console では以下のようになります。

```ruby
irb> I18n.t '.title' # エラー
=> "translation missing: ja.title"

irb> I18n.t 'projects.index.title' # 絶対パス指定
=> "プロジェクト一覧"

irb> I18n.t '.title', scope: 'projects.index' # カラクリは scope オプションだったのだ
=> "プロジェクト一覧"
```

ルールとしては**「階層はファイル名と対応」**と覚えるようにしています。

## partial ファイルの場合
**「階層はファイル名と対応」**と覚えていれば大丈夫。

```html+erb:app/views/projects/index.html.erb
<h1><%= t('.title') %></h1> <%# 冗長な書き方だと右記になる。 t('projects.index.title') %>

<%= render partial: "hoge" %>
```

```html+erb:app/views/projects/_hoge.html.erb
<h2><%= t('.fuga') %></h2>
```

上記のビューに対し...

```yaml
ja:
  projects: # app/views/projectsを表す
    index:  # app/views/projects/index.html.erb
      title: "プロジェクト一覧"
    hoge:
      fuga: 'ふがーーーー'
```

partialファイル名の先頭のアンダーバーは無視して構いません。

# 参考
- [Rails国際化(I18n) API](http://railsguides.jp/i18n.html)
- [ソフトウェア/rails/国際化](http://dora.bk.tsukuba.ac.jp/~takeuchi/?%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%2Frails%2F%E5%9B%BD%E9%9A%9B%E5%8C%96)
- [Railsの多言語化対応 I18nのやり方を整理してみた！【国際化/英語化】](http://morizyun.github.io/blog/i18n-english-rails-ruby-many-languages/)
- [Railsのi18nの基本的な使い方まとめ](http://ruby-rails.hatenadiary.com/entry/20150226/1424937175)

# 最後に
rails4.2 や rails5 で動作確認しました。
このページを見て理解が深まったり、気づきがあったり、チートシート的に見てもらえれば幸いです。