在线文档教程

国际化与本地化

国际化与本地化

概述

国际化与本地化,或者说全球化,其目的是让你的站点支持多个国家和区域。其中国际化是指功能和代码设计能处理多种语言和文化习俗,能够在创建不同语言版本时,不需要重新设计源程序代码。国际化的英文单词是 Internationalization ,简称 I18N。 本地化是将站点按照特定国家、地区或语言市场的需要进行加工,使之满足特定用户对语言和文化的特殊要求。本地化的英文对应Localization,缩写为L10N。举例 Moment,其支持 setLocale 方法切换语言就是国际化,每一个 locale 的配置文件定义了具体区域时间格式就是本地化。

think-i18n

think-i18n 是 ThinkJS 3.0 国际化方案的实现, 基于 Jed, MomentNumeral.

安装

npm install think-i18n --save

配置 extends.js

// ThinkJS config/extend.js const createI18n = require('think-i18n' const path = require('path' module.exports = [ createI18n{ app: think.app, // 如果为空,__ 就不会被自动 `assign` 到 `think-view` 实例 i18nFolder: path.resolve(__dirname, '../i18n'), localesMapping(locales) {return 'en';} }) ];

查看完整配置

配置 locale 文件

每个 locale 一个文件,放在 i18nFolder 目录下。

  • dateFormat 会应用到 moment.local(localeId, dateFormat 如果不提供配置,默认使用 en

查看配置详情

Controller 和 View (nunjucks)

Controller

如果需要再controller 里面获取 I18n 的实例或者当前的 locale,可以调用

async indexAction(){ const __ = this.getI18n(/*forceLocale*/) const locale = this.getLocale( }

View

如果使用了 think-view 模块并配置了 app 参数, think-i18n 会自动调用注入一个实例到当前模板实例里,类似: this.assign('__', this.getI18n()), 这样在模板里面就可以使用直接使用 i18n 暴露的接口。

{{ __('some key') }} {{ __.jed.dgettext('domain', 'some key') }} {{ __.moment().format('llll') }} {{ __.numeral(1000).format('currency') }}numberFormat.formats)

完整配置

  • app:think.app 如果配置了此参数,则会监听 viewInit 事件并把 i18n 实例注入到模板的 __ 参数里面。

Object.assign(jedOptions, {locale_data: <your locale translation>})

背后的思考

  • 你可能会觉得这个方案太复杂,但是 i18n 本来就很复杂,要想实现的好,你可能需要的只会更多。

// locale setting of en-CH.js module.exports = { localeId: 'en_CH', translation: require('../english.po.json'), dateFormat: require('../moment/en.json'), numeralFormat: require('../numeral/en.json') };

其中 ../moment/en.json 是一个json,格式参考 moment 的i18n文件,一模一样。

其中 ../numeral/en.json 是一个json,格式参考 numeral, 需要指出的是,额外的你可以在 numeral 的配置里面设置自定义的格式,并且这个是跟着locale走的,这个实现是个小小的黑魔法,但是对于 i18n 的最佳实践非常重要。

{ localeId: cn, ... formats: [{name: 'currency', format: '000.00$'}] }

最佳实践

总是使用自定义的格式,这样就可以通过配置定制不用locale下有不同的输出格式。同时也方便后期的维护,比如某天我们需要把所有长日期显示修改格式,不用到每个文件里面取修改,只需要改配置就好,相当于一层抽象。

  • 使用 __.moment().format('llll') 而不是 moment().format('YYYY-MM-dd HH:mm').

如果定义了 en locale, 会覆盖 Numeral 默认的配置。

调试某个 locale

默认情况下,是通过读取 header['accept-language'] 的值,然后通过 localesMapping 转换后作为某一时刻采纳的 locale。如果需要调试,在 view 配置里面设置 debugLocal =