# 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') %>
~~~
![](https://box.kancloud.cn/2015-08-18_55d2e4810137e.png)
这个例子来自[这里](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
- 写在后面