国际化

使用场景

为了方便开发多语言应用,框架内置了国际化(I18n)支持,由 egg-i18n 插件提供。

i18ninternationalization 的缩写,代表 in 之间有 18 个字母。

  • 开发者需定义多个 locale 多语言文件。
  • 开发者在 ControllerView 中使用对应的语法糖渲染字符串。
  • 插件会根据约定,渲染指定的多语言字符串。

定义 locale

目录规范

多种语言的配置是独立的,统一存放在 config/locale/*.js 下。

showcase
└── config
    ├── plugin.js
    ├── config.default.js
    └── locale
        ├── en-US.js
        └── zh-CN.js

不仅对于应用目录生效,在框架,插件的 config/locale 目录下同样生效。

友情提示

注意单词拼写,是 locale 不是 locals。

文件格式

支持 jsJSON 两种格式:

// config/locale/zh-CN.js
module.exports = {
  Email: '邮箱',
};

// config/locale/zh-CN.json
{
  "Email": "邮箱"
}

占位符

支持类似 util.format()%s%j 等占位符语法。

// config/locale/zh-CN.js
module.exports = {
  'Welcome back, %s!': '欢迎回来,%s!',
};

ctx.__('Welcome back, %s!', 'Shawn');
// zh-CN => 欢迎回来,Shawn!
// en-US => Welcome back, Shawn!

同时支持数组下标占位符方式,例如:

// config/locale/zh-CN.js
module.exports = {
  'Hello {0}! My name is {1}.': '你好 {0}! 我的名字叫 {1}。',
};

ctx.__('Hello {0}! My name is {1}.', [ 'foo', 'bar' ]);
// zh-CN => 你好 foo!我的名字叫 bar。
// en-US => Hello foo! My name is bar.

使用 i18n

ctx.__(key, ...values)

插件提供了 ctx.__(key, ...values) 来获取语言配置。

它等价于 ctx.gettext(key, ...values)

class HomeController extends Controller {
  async index() {
    const ctx = this.ctx;
    ctx.body = {
      // zh-CN => 邮箱
      // en-US => Email
      email: ctx.__('Email'),

      // zh-CN => 欢迎回来,Shawn!
      // en-US => Welcome back, Shawn!
      message: ctx.__('Welcome back, %s!', 'Shawn'),

      // zh-CN => 你好 foo!我的名字叫 bar。
      // en-US => Hello foo! My name is bar.
      descriptions: ctx.__('Hello {0}! My name is {1}.', [ 'foo', 'bar' ]),
    };
  }
}

在 View 中使用

插件也同时把对应的语法糖注入到 ctx.locals 上,因此也可以直接在模板引擎里面使用:

<li>{{ __('Email') }}: {{ user.email }}</li>
<li>
  {{ __('Welcome back, %s!', user.name) }}
</li>
<li>
  {{ __('Hello {0}! My name is {1}.', ['foo', 'bar']) }}
</li>

切换语言

默认语言

默认语言是 en-US。假设我们想修改默认语言为简体中文:

// config/config.default.js
exports.i18n = {
  defaultLocale: 'zh-CN',
};

切换语言

插件也会根据请求参数不同,自动选择指定的语言。

修改后会记录到 locale 这个 Cookie,下次请求直接用设定好的语言。

优先级从高到低:

  1. Query: /?locale=en-US
  2. Cookie: locale=zh-TW
  3. Header: Accept-Language: zh-CN,zh;q=0.5

如果想修改 Query 或者 Cookie 参数名称:

// config/config.default.js
exports.i18n = {
  queryField: 'locale',
  cookieField: 'locale',
  // Cookie 默认一年后过期, 如果设置为 Number,则单位为 ms
  cookieMaxAge: '1y',
};

局限性

一般来说,国际化是需要有配套的运营后台的,该插件只是一个简化的实现,开发者根据具体情况选择使用。