前言
第一次了解到这个概念,之前在QQ群也有人聊前端国际化如何做的问题,不知道这篇对他有帮到吗?今日早读文章来自阿里@sundway分享。
正文从这开始~
何为国际化
国际化(Internationalization)通常在很多地方会用 i18n 代替,意思就是 I 加18个字母加 n。跟国际化还有一个类似的概念叫做本地化(Localization)通常用 L10n 表示。这是两个比较接近的概念,它之间有什么区别呢?W3C 的 Localization vs. Internationalization 这篇文档详细了介绍了这一点,对国际化理解还不是特别清晰的强烈建议读一下这篇文章。简单的理解就是,国际化就是为本地化做很多的前期工作,可以根据所做的事情是否属于只是为某一地区来区分国际化和本地化。国际化包含的东西很多,对于前端,最常接触到的就是将可本地化的元素与源代码或内容分开,以便可以根据需要根据用户的国际偏好来加载或选择本地化的替代。但国际化的工作远不止这些,例如国际化CDN 部署,Unicode 编码都可以算作国际化的范畴。
国际化 API
其实在 2012 年就已经拟定了国际化 API,详尽的内容可以参考 《ECMAScript Internationalization API Specification》。下面重点介绍几个 API 的使用:
Intl.Collator
Intl.Collator 是用于语言敏感字符串比较的 collators构造函数。语法:
new Intl. Collator ([ locales[, options]]) Intl. Collator. call ( this [, locales[, options]])
上述语法中,locales 是可选参数,locales 的参数必须遵从 BCP 47 规范,locales 标记必须是 "en-US" 和 "zh-Hans-CN 等,这个标记包含了语言、地区和国家。完整的列表可以查看 IANA language subtag registry。options 也是可选参数,它包含了特定比较选项的对象。
示例:
var co1 = new Intl. Collator ([ "de-DE-u-co-phonebk" ]); var co2 = new Intl. Collator ([ "de-DE" ]); var co3 = new Intl. Collator ([ "en-US" ]); var arr = [ "ä" , "ad" , "af" , "a" ]; if ( console && console. log) { console. log ( arr. sort ( co1. compare)); console. log ( arr. sort ( co2. compare)); console. log ( arr. sort ( co3. compare)); }
Intl.DateTimeFormat
Intl.DateTimeFormat是根据语言来格式化日期和时间的类的构造器类。
new Intl. DateTimeFormat ([ locales[, options]]) Intl. DateTimeFormat. call ( this [, locales[, options]])
Intl.DateTimeFormat是根据语言来格式化日期和时间的类的构造器类。可以使用 options 参数来自定义 日期时间格式化方法返回的字符串。
var date = new Date ( Date. UTC ( 2012 , 11 , 20 , 3 , 0 , 0 )); console. log ( new Intl. DateTimeFormat ( 'en-US' ). format ( date)); console. log ( new Intl. DateTimeFormat ( 'en-GB' ). format ( date)); console. log ( new Intl. DateTimeFormat ( 'ko-KR' ). format ( date)); console. log ( new Intl. DateTimeFormat ( 'ar-EG' ). format ( date)); console. log ( new Intl. DateTimeFormat ( 'ja-JP-u-ca-japanese' ). format ( date)); console. log ( new Intl. DateTimeFormat ([ 'ban' , 'id' ]). format ( date));
Intl.NumberFormat
Intl.NumberFormat是对语言敏感的格式化数字类的构造器类。
new Intl. NumberFormat ([ locales[, options]]) Intl. NumberFormat. call ( this [, locales[, options]])
示例:
var number = 123456.789 ; console. log ( new Intl. NumberFormat ( 'de-DE' ). format ( number)); console. log ( new Intl. NumberFormat ( 'ar-EG' ). format ( number)); console. log ( new Intl. NumberFormat ( 'en-IN' ). format ( number)); console. log ( new Intl. NumberFormat ( 'zh-Hans-CN-u-nu-hanidec' ). format ( number)); console. log ( new Intl. NumberFormat ([ 'ban' , 'id' ]). format ( number));
这个例子显示了一些本地化的数字格式的一些变化。为了获得用于您的应用程序的用户界面的语言格式,请确保设定了语言(可能还有一些回退语言)参数。
以下各浏览器的支持情况:
可以看到个浏览器对 Intl API 的支持已经相当不错了。对于一些不兼容的浏览器,我们可以引入 Intl polyfill。
生产环境中的应用
在生产环境中我们一般会引用第三方库,不同的技术方案引入的库也会不同。以下是几个主流的库/框架的解决方案:
下面以 react 为例,这里建议直接可以使用阿里开源的 react-intl-universal,相比于 Yahoo react-intl API,它不仅支持 react 组件,同时也支持原生 js。
import intl from 'react-intl-universal' ; const locales = { "en-US" : require ( './locales/en-US.js' ), "zh-CN" : require ( './locales/zh-CN.js' ), }; class App extends Component { state = { initDone: false } componentDidMount () { this . loadLocales (); } loadLocales () { intl. init ({ currentLocale: 'en-US' , locales, }) . then (() => { this . setState ({ initDone: true }); }); } render () { return ( this . state. initDone && < div> { intl. get ( 'SIMPLE' )} div> ); } }
当然有些项目没有使用上面任何一个库/框架,例如阿里小蜜。也有相应地方案去解决。主要思路:
通过构建工具去完成样式, 图片替换, class属性等的替换工作。
通用的翻译函数去完成静态文案及动态文案的翻译工作。
阿里小蜜中使用的是 nunjucks 模版引擎,那么这里可以使用 nunjucks-intl。如果是其他模版工具,也可以自己在 polyfill 上写一个简单的实现。
最后,推荐一下 Yahoo 的 FormatJS,官方给出的解释是一系列 JavaScript 库的集合,主要用来格式化数字,日期和字符串。它包含一系列核心代码,而这些代码建立在 JS 原生 Intl 以及各种 i18n 标准之上的。
关于本文
作者:@sundway
原文:https://github.com/sundway/blog/issues/9