# 6.4 I18n
## 概要:
本課時講解如何設置和使用 I18n 語言包。
## 知識點:
1. i18n
1. helper
## 正文
在 [4.4.5 使用中文的校驗信息] 一節中,我們簡單的應用了 I18n,這里我們詳細的擴展一下。
### 6.4.1 I18n
因為 Internationalization 的 I 和 N 之間有18個字母,所以它簡稱 I18n。Rails 通過 I18n 為項目提供多語言包支持,這也要求我們在開發過程中,按照 I18n 的方式處理顯示文字。
Rails 默認使用一個單一的 I18n 文件,它在 `config/locales/en.yml`,這對于中型以上,以及使用多個 Gem 的應用是不足的,我們將整個文件夾下的所有內容,都加在到 i18n 的路徑中:
`config/application.rb`
~~~
config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**/*.{rb,yml}').to_s]
~~~
這樣做的好處是,我們可以把一些 gem 的語言包,放到我們自己項目中維護。比如一些 gem 的 zh-CN 語言包缺失,或者翻譯不準確的語言包。
然后設定我們默認的語言包。
~~~
config.i18n.default_locale = :"zh-CN"
~~~
### 6.4.2 顯示語言
#### 6.4.2.1 t 和 l
I18n 有兩個常用的顯示方法:
| 使用方法 | 簡寫方法 | 含義 | 例子 |
|-----|-----|-----|-----|
| I18n.translate | I18n.t | 顯示語言 | I18n.t "name" |
| I18n.localize | I18n.l | 按照語言包定義顯示 Date 和 Time | I18n.l Time.zone.now |
I18n.t 有三種使用方法,查找語言包:
<table class="calibre15"><tbody class="calibre16"><tr class="calibre17"><td class="calibre20">查找方法</td><td class="calibre20">對應語言包結構</td><td class="calibre20">含義</td></tr><tr class="calibre19"><td class="calibre20">I18n.t("name")</td><td class="calibre20">zh-CN:<br class="calibre29"/>??name: "姓名"</td><td class="calibre20">從根節點開始查找</td></tr><tr class="calibre17"><td class="calibre20">I18n.t(".name")</td><td class="calibre20">zh-CN:<br class="calibre29"/>?? users:<br class="calibre29"/>???? show:<br class="calibre29"/>???????? name: "姓名"<br class="calibre29"/></td><td class="calibre20">根據視圖路徑查找:views/users/show.html.erb </td></tr><tr class="calibre19"><td class="calibre20">I18n.t("name", scope: "users.show")</td><td class="calibre20">zh-CN:<br class="calibre29"/>?? users:<br class="calibre29"/>???? show:<br class="calibre29"/>???????? name: "姓名"<br class="calibre29"/></td><td class="calibre20">指定從哪個節點開始查找</td></tr></tbody></table>
I18n.l 會按照語言包中定義的時間格式來顯示,為了方便編輯,我將它放到了 `config/locales/defaults/zh-CN.yml` 中,它來自 [這里](https://github.com/svenfuchs/rails-i18n/blob/master/rails/locale/zh-CN.yml)。
#### 6.4.2.2 使用變量
我們在語言包中可以定義變量:
~~~
zh-CN:
hello: "你好, %{name}"
~~~
顯示時,傳入該變量:
~~~
I18n.t("hello", name: "Ruby")
~~~
#### 6.4.2.3 使用復數
在我們的語言里,`你` 和 `你們` 是 不一樣的含義,而英語里都是 `You`,在語言包里可以定義單復數:
~~~
zh-CN:
hello:
one: "你好"
other: "你們好"
~~~
調用時:
~~~
I18n.t("hello", count: 1)
=> "你好"
I18n.t("hello", count: 2)
=> "你們好"
~~~
#### 6.4.2.4 使用HTML
如果 key 帶有 _html,或者定義了 html 的 key,會認為它是 安全的 HTML,否則輸出將被 escape:
`config/locales/en.yml`
~~~
en:
welcome: <b>welcome!</b>
hello_html: <b>hello!</b>
title:
html: <b>title!</b>
~~~
`app/views/home/index.html.erb`
~~~
<%= t('welcome') %>
<%= raw t('welcome') %>
<%= t('hello_html') %>
<%= t('title.html') %>
~~~

這個例子來自[這里](http://guides.rubyonrails.org/i18n.html#using-safe-html-translations)。
#### 6.4.2.4 顯示 Model 屬性
~~~
Model.human_attribute_name(attribute)
~~~
會顯示我們定義在語言包中的屬性名稱,
~~~
Model.model_name.human
~~~
則會顯示該類的名稱。為了方便維護每一個 Model,我們在 locales 目錄下,為每個 Model 建立了自己的文件夾,放置單獨的語言包。
這是我們Order 的語言包,它在 `config/locales/models/order/zh-CN.yml`:
~~~
zh-CN:
activerecord:
models:
order: 訂單
attributes:
order:
number: 訂單號
~~~
對于一些屬性,可能有兩種不同的情況,比如性別:
~~~
en:
activerecord:
attributes:
user/gender:
female: "Female"
male: "Male"
~~~
我們顯示的時候,需要這樣調用:
~~~
User.human_attribute_name("gender.female")
~~~
### 6.4.3 切換顯示語言
我們在 `config/application.rb` 已經設置了默認語言包,但是有些網站需要在多個語言包間切換,我們已經將語言包管理進行了細分,這樣方便我們維護多個語言包,并且做一個簡單設置,就可以在這之間切換:
~~~
before_action :set_locale
def set_locale
I18n.locale = params[:locale] || I18n.default_locale
end
~~~
我們可以將選擇的語言包名稱儲存在 session 中(雖然手冊上步推薦這樣做),也可以通過地址參數,比如 `?local=zh-CN&....`,或者使用 routes 來設定地址規則,比如 `/zh-CN/products/...` 來修改顯示的語言包。(手冊推薦后兩種方式)
- 寫在前面
- 第一章 Ruby on Rails 概述
- Ruby on Rails 開發環境介紹
- Rails 文件簡介
- 用戶界面(UI)設計
- 第二章 Rails 中的資源
- 應用 scaffold 命令創建資源
- REST 架構
- 深入路由(routes)
- 第三章 Rails 中的視圖
- 布局和輔助方法
- 表單
- 視圖中的 AJAX 交互
- 模板引擎的使用
- 第四章 Rails 中的模型
- 模型的基礎操作
- 深入模型查詢
- 模型中的關聯關系
- 模型中的校驗
- 模型中的回調
- 第五章 Rails 中的控制器
- 控制器中的方法
- 控制器中的邏輯
- 第六章 Rails 的配置及部署
- Assets 管理
- 緩存及緩存服務
- 異步任務及郵件發送
- I18n
- 生產環境部署
- 常用 Gem
- 寫在后面