本課時(shí)講解如何設(shè)置和使用 I18n 語(yǔ)言包。
在 [4.4.5 使用中文的校驗(yàn)信息] 一節(jié)中,我們簡(jiǎn)單的應(yīng)用了 I18n,這里我們?cè)敿?xì)的擴(kuò)展一下。
因?yàn)?Internationalization 的 I 和 N 之間有18個(gè)字母,所以它簡(jiǎn)稱 I18n。Rails 通過(guò) I18n 為項(xiàng)目提供多語(yǔ)言包支持,這也要求我們?cè)陂_(kāi)發(fā)過(guò)程中,按照 I18n 的方式處理顯示文字。
Rails 默認(rèn)使用一個(gè)單一的 I18n 文件,它在 config/locales/en.yml,這對(duì)于中型以上,以及使用多個(gè) Gem 的應(yīng)用是不足的,我們將整個(gè)文件夾下的所有內(nèi)容,都加在到 i18n 的路徑中:
config/application.rb
config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**/*.{rb,yml}').to_s]
這樣做的好處是,我們可以把一些 gem 的語(yǔ)言包,放到我們自己項(xiàng)目中維護(hù)。比如一些 gem 的 zh-CN 語(yǔ)言包缺失,或者翻譯不準(zhǔn)確的語(yǔ)言包。
然后設(shè)定我們默認(rèn)的語(yǔ)言包。
config.i18n.default_locale = :"zh-CN"
I18n 有兩個(gè)常用的顯示方法:
| 使用方法 | 簡(jiǎn)寫方法 | 含義 | 例子 |
|---|---|---|---|
| I18n.translate | I18n.t | 顯示語(yǔ)言 | I18n.t "name" |
| I18n.localize | I18n.l | 按照語(yǔ)言包定義顯示 Date 和 Time | I18n.l Time.zone.now |
I18n.t 有三種使用方法,查找語(yǔ)言包:
| 查找方法 | 對(duì)應(yīng)語(yǔ)言包結(jié)構(gòu) | 含義 |
| I18n.t("name") |
zh-CN:
??name: "姓名" |
從根節(jié)點(diǎn)開(kāi)始查找 |
| I18n.t(".name") |
zh-CN: ?? users: ???? show: ???????? name: "姓名" |
根據(jù)視圖路徑查找:views/users/show.html.erb |
| I18n.t("name", scope: "users.show") |
zh-CN: ?? users: ???? show: ???????? name: "姓名" |
指定從哪個(gè)節(jié)點(diǎn)開(kāi)始查找 |
I18n.l 會(huì)按照語(yǔ)言包中定義的時(shí)間格式來(lái)顯示,為了方便編輯,我將它放到了 config/locales/defaults/zh-CN.yml 中,它來(lái)自 這里。
我們?cè)谡Z(yǔ)言包中可以定義變量:
zh-CN:
hello: "你好, %{name}"
顯示時(shí),傳入該變量:
I18n.t("hello", name: "Ruby")
在我們的語(yǔ)言里,你 和 你們 是 不一樣的含義,而英語(yǔ)里都是 You,在語(yǔ)言包里可以定義單復(fù)數(shù):
zh-CN:
hello:
one: "你好"
other: "你們好"
調(diào)用時(shí):
I18n.t("hello", count: 1)
=> "你好"
I18n.t("hello", count: 2)
=> "你們好"
如果 key 帶有 _html,或者定義了 html 的 key,會(huì)認(rèn)為它是 安全的 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') %>

這個(gè)例子來(lái)自這里。
Model.human_attribute_name(attribute)
會(huì)顯示我們定義在語(yǔ)言包中的屬性名稱,
Model.model_name.human
則會(huì)顯示該類的名稱。為了方便維護(hù)每一個(gè) Model,我們?cè)?locales 目錄下,為每個(gè) Model 建立了自己的文件夾,放置單獨(dú)的語(yǔ)言包。
這是我們Order 的語(yǔ)言包,它在 config/locales/models/order/zh-CN.yml:
zh-CN:
activerecord:
models:
order: 訂單
attributes:
order:
number: 訂單號(hào)
對(duì)于一些屬性,可能有兩種不同的情況,比如性別:
en:
activerecord:
attributes:
user/gender:
female: "Female"
male: "Male"
我們顯示的時(shí)候,需要這樣調(diào)用:
User.human_attribute_name("gender.female")
我們?cè)?config/application.rb 已經(jīng)設(shè)置了默認(rèn)語(yǔ)言包,但是有些網(wǎng)站需要在多個(gè)語(yǔ)言包間切換,我們已經(jīng)將語(yǔ)言包管理進(jìn)行了細(xì)分,這樣方便我們維護(hù)多個(gè)語(yǔ)言包,并且做一個(gè)簡(jiǎn)單設(shè)置,就可以在這之間切換:
before_action :set_locale
def set_locale
I18n.locale = params[:locale] || I18n.default_locale
end
我們可以將選擇的語(yǔ)言包名稱儲(chǔ)存在 session 中(雖然手冊(cè)上步推薦這樣做),也可以通過(guò)地址參數(shù),比如 ?local=zh-CN&....,或者使用 routes 來(lái)設(shè)定地址規(guī)則,比如 /zh-CN/products/... 來(lái)修改顯示的語(yǔ)言包。(手冊(cè)推薦后兩種方式)