Rails 中 I18n 的使用

最近开始着手自己的一个小项目的国际化工作,虽然其实根本没个外国的用户,但是本着学习的原则还是严格的 来进行了一次,而在这过程中也对 Rails 中国际化有了一个较为全面的认识。

当我们建立一个新的项目之后,默认的会在 config/locales/en.yml 目录下有一个 en.yml 的文件, 这个文件是用来做英文的国际化的。打开文件后我们看到里面的内容很少,只有下面这几行:

en:
  hello: Hello

而关于 locales 的配置文件则是在 config/application.erb 中,默认的情况下我们看到的是这样的:

# ...
config.i18n.default_locale = :en
# ...

即默认使用的是 en.yml 这个文件的,下来我们开始根据自己的需要来配置,我的项目中使用了简体中文和英文 两种语言,因此首先添加 config/locales/zh-CN.yml 文件,接着在 config/application.rb 中的 config.i18n.available_locales 中加入 "zh-CN" 这个选项。

下来我们就开始在两个 yaml 文件中来进行我们的国际化之旅了。首先是我们创建的一些ActiveRecorduser,他们有name,email,password等等之类的属性,我们先来对他们进行国际化。

# en.yml
en:
  activerecord:
    attributes:
      user:
        name: Name
        email: Email
        password: Password
        password_confirmation: Password confirmation
# zh-CN.yml
zh-CN:
  activerecord:
    attributes:
      user:
        name: "用户名"
        email: "邮箱"
        password: "密码"
        password_confirmation: "密码确认"

而这些属性的使用,我们常在注册用户的表单中使用到,他们的使用方式很简单,类似于下面这样的表单

<%= form_for @user do |f| %>
  <%= f.label :name %>
  <%= f.text_field, :name %>

  <%= f.label :email %>
  <%= f.text_field, :email %>
<%= end %>

这些 ActiveRecord 的属性会自动国际化。

接着是关于 View 中输出的内容的国际化,以views/users/new.html.erb为例,假设我们要配置页面的 title,那么它在两个 yaml 文 件中的配置就是像下面这样:

# en.yml
en:
  users:
    new:
      title: Too young too simple
# zh-CN.yml
zh-CN:
  users:
    new:
      title: "图样图森破"

下来我们打开views/users/new.html.erb,在 title 的 HTML element 下输入 <%= t('.title') %> 即可,可见视图所在的路径和 yaml 文件中 key 的嵌套是对应的。

而在 controller 中有时我们会返回一些 flash 内容,这时我们输入的是直接的路径,比如 app/controllers/users_controller.rb 中的 create 方法,我们需要放回一个成功的 flash,那么 可以像下面这样:

def create
  # ...
  flash[:success] = I18n.t('flashes.users.create_success')
end
# en.yml
en:
  flashes:
    users:
      create_success: Successfully create a new user

国际化中,我们还会遇到这样的问题,就是中文、英文翻译不一致的情况。比如每个用户可以番表文章,那么显示 文章的时候就中文是0篇文章、1篇文章、2篇文章,而英文则是0 article, 1 article, 2 articles ,这时我们需要处理复数的问题。其实通过在 yaml 文件中配置也可以很轻松的解决:

# en.yml
en:
  misc:
    article:
      zero: 0 article
      one: 1 article
      other: "%{count} articles"

# zh-CN.yml
zh-CN:
  misc:
    article:
      zero: "0篇文章"
      one: "1篇文章"
      other: "%{count}篇文章"

在视图中,我们这样写就可以啦:<%= t('misc.article', count: current_user.articles.count) %>

还有就是一些 error 信息,比如我们在填写表单的时候,一些不能为空或者限制长度的属性,我们没有按照它的要求 来的话,页面会显示错误信息。这些信息 Rails 是会自己进行 I18n 的,但是我们也可以根据自己的需求再去 调整,比如我们有一个 user 的 model,然后我们需要对它的 format 进行验证,当不符合我们所要的 format 的时候会弹出错误信息。

我们可以像下面这样配置:

# en.yml
en:
  activerecord:
    errors:
      user:
        attributes:
          name:
            format: "may only contain alphanumeric characters or dashes and cannot begin with a dash"
          email:
            format: invalid email format

# zh-CN.yml
zh-CN:
  activerecord:
    errors:
      user:
        attributes:
          name:
            format: "只能使用字母、数字或 - 号,并且不能以 - 号开头"
          email:
            format: "无效的邮件格式"

这样当用户的邮箱或者用户名格式不正确的时候,我们可以这样输出错误信息<%= @user.errors.generate_message :email, :format %>

关于 Rails 的国际化大概常用的就这这么多,我认为尽早的开始国际化是一个好的习惯,这样可以较早的将一些 展示的内容集中在一个文件中,也方便我们以后的修改。