【Rails】i18n化する時のymlファイルの構成について

## はじめに

現在、プログラミングスクールRUNTEQで未経験からWebエンジニア転職を目指して学習中のyushiと申します。

Railsについて学ぶ中でi18n対応をするためのymlファイルの構成について腑に落ちない部分があったので詳しく調べてみました。

:::note warn
プログラミング初学者のため、内容に誤りがある可能性がございます。
もし間違いがあればご指摘いただけると幸いです。
:::


まずはざっくりとi18nについて抑えておきたいと思います。

## i18nとは？

アプリケーション内で使われる文字列を抽象化して言語ごとに訳文を定義してあげることで、動作する言語環境に応じてアプリケーション側で自動で翻訳するための仕組みです。

ビューに記載する文字列が特定の言語に依存せずに済むようになり、複数言語での開発や実行環境による差分を用意する手間を減らすことができます。

「internationalization」という単語が語源になっていて、最初の「i」と最後の「n」の間に18文字あることから「i18n」と呼ばれているそうです。

Railsにはデフォルトでi18nの機能が備わっていますが、`rails-i18n`というgemと組み合わせることでアプリケーションの国際化・地域化が容易になります。
[rails-i18nに用意してあるja.yml](https://github.com/svenfuchs/rails-i18n/blob/master/rails/locale/ja.yml)については自分で記述せずに利用できるようになります。



### 翻訳の仕組み

`config/locales`以下にあるすべての`.rb`ファイルと`.yml`ファイルは、自動的に訳文読み込みパスに追加されます。（以下、まとめて翻訳ファイルと呼びます）

一般的に`翻訳先の言語.yml`のように命名されます。（`en.yml`、`ja.yml`）

翻訳ファイルは複数に分割することもできます。
規模の大きいプロジェクトになると翻訳ファイルの行数が膨大になるので、役割ごとに翻訳ファイルを分割するのが一般的なようです。

翻訳する際にはビューヘルパーメソッドである`translate`メソッド、もしくはエイリアスの`t`メソッドを使います。
```erb:app/views
<%= translate('users.new.title') %>
<%= t('users.new.title') %>
```

また、`enum_help`や`simple_form`などgemがi18nに対応している場合は、それぞれの形式で訳文を追加できるようになります。

1つ注意点としては、デフォルトのロケールが英語（`:en`）に設定されているので、デフォルトを日本語にしたい場合は`config/application.rb`の記述を変更する必要があります。
```ruby:config/application.rb
module App
  class Application < Rails::Application

    ...
    
    # この部分の:enを:jaに変更する
    config.i18n.default_locale = :en 
    
  end
end

```

### ymlファイルの構成について

ymlファイルの書き方として、基本的にインデントを利用して階層構造を表現します。
訳文を追加する際には、`キー: 値`のペアになるようにします。
多層構造になっている訳文を呼び出したい場合は`:`を`.`に読み替えて、繋げて呼び出します。

まず、一行目にどの言語の翻訳ファイルなのかということを明記します。
ここの情報とアプリケーションの実行環境を照らし合わせて、どの翻訳ファイルから訳文を呼び出すかが決まります。

この下に訳文を記述していくのですが、いくつかルールがあります。
例を見ながら説明していきましょう。

```yml:config/locales/ja.yml
ja:
  helpers:
　　　　　　submit:
     create: 登録
     update: 更新
　　　　　　label:
     email: メールアドレス
     password: パスワード
  defaults:
    flash_message:
      success: "%{item}の作成に成功しました"
      failure: "%{item}の作成に失敗しました"
  activerecord:
    models:
      user: ユーザー
    attributes:
      user:
        name: ユーザー名
        age: 年齢
        height: 身長
  users:
    index:
      title: ユーザー一覧ページ
    new:
      title: ユーザー新規登録ページ
  header:
　　　　　　　　login: ログイン
　　　　　　　　logout: ログアウト
```

1.　モデルの訳文は`activerecord`以下に記述する
これによって`モデル名.model_name.human`メソッドと`モデル名.human_attribute_name(attribute)`が使えるようになります。
また、バリデーションエラーのメッセージなどで表示されるカラム名が翻訳されるようになります。

    

2.　ビューはビューを格納しているフォルダ名を起点にして、ファイル毎に記述する
対応するビューで呼び出す時にツリーを省略できるようになります。（遅延探索）
```erb:app/views/users/new.html.erb
<%= t('users.new.title') %>

<%# 上の翻訳ファイルのusers以下とビューファイルのパスが一致しているため、以下の呼び出しも可能 %>
<%= t('.title') %>
```

3.　ヘルパーメソッドの訳文は`helpers`以下に記載する
例えば、`form_with`メソッドで生成したフォームの中で使うヘルパーメソッド（`f.label`や`f.submit`）などの訳文はここで定義します。

下の例では、ユーザーの新規登録処理を行なっているので、翻訳ファイルの`helpers: submit: create:`が呼び出されて`f.submit`で生成されるボタンのテキストが「登録」になります。
ここは`form_with`メソッドと同様に`model`オプションにセットしたインスタンスの状態によって参照する訳文が変わります。
```erb:app/views/users/new.html.erb
<%= form_with model:@user %>
  <%= f.label :email %>
  <%= f.text_field :email %>
  <%= f.label :password %>
  <%= f.password_field :password %>
  <%= f.submit %>
```

4.　引数を渡して表示する訳文を動的に変える
訳文にエスケープ文字を記述することで、動的に文面を変えることもできます。
訳文を`""`で囲むこととエスケープ文字`%{}`の記述に注意してください。
```ruby:app/controllers/users_controller.rb
def create
  @user = user.new(user_params)
  if @user 
    redirect_to root_path
  else
    flash.new[:danger] = t('defaults.flash_message.failure', item: 'ユーザー')
    render :new, status: :unprocessable_entity
  end
end
```

5.`defaults`オプションについて
1. アプリケーション内の複数箇所で共通して使用される文言をまとめて指定する
2. 特定の言語に対する翻訳が見つからなかった場合に、ここで設定した値で代替される

6.　これらのルールに当てはまらない場合
例えば、ヘッダーやフッターなど部分テンプレートで使うテキストの訳文を指定したい場合は、ymlファイルで定義した階層構造を`.`で読み替えて呼び出します。
```erb:app/views/shared/_header.html.erb
<%# ヘッダーにログインページへのリンクを置く場合 %>
<%# ymlファイルでheader: login: と定義しているので、これに従って呼び出す %>
<%= link_to t('header.login'), login_path %>
```



### 最後に

というわけでi18nに使うymlファイルの構成について整理してみました。

最初に触れた時は見よう見真似で済ませてしまっていましたが、改めて整理してみるとどういう理屈で訳文が呼び出されているのか理解が深まったように思います。

今回調べていても翻訳ファイルからどういうルールで呼び出しているかを詳しく書いた記事があまり見つからなかったので、後学の方の参考になると嬉しいです！

## 参考文献
- [Railsガイド: Rails 国際化（I18n）API](https://railsguides.jp/i18n.html)
- [GitHub： rails-i18n](https://github.com/svenfuchs/rails-i18n)
- [Ruby on RailsのI18nで使用する名前空間に関してのまとめと、ベストプラクティスの検討。](https://alfa.hatenablog.jp/entry/2013/12/03/221308)
- [【Rails】I18nを使用した多言語対応（日本語化）](https://autovice.jp/articles/126)
- [i18nロケールファイルの書き方小技集](https://qiita.com/tomomomo1217/items/858f290a0dc1a817985c)
- [【Rails】I18n.tはtに省略できるんじゃない、省略したほうが良い](https://qiita.com/masa_ito/items/c40d2fa76c8a0e364642)
- [.ymlや.yaml(ヤムル)とは何か？書き方や記号 &, *, <<, #, ~ の意味や使い方を実例で解説｜jsonとの違い（初心者向け、わかりやすい）](https://prograshi.com/language/json/what-are-yaml-and-yml/)