聊聊什么是 i18n?JavaScript 中的 i18n 基本概念

简介: 聊聊什么是 i18n?JavaScript 中的 i18n 基本概念

为什么需要 i18n?


英语是世界上使用最广泛的语言,但只有七分之一的人会说英语。它是 3.79 亿人的第一(母语)语言,但有 9.17 亿人说中文普通话,4.6 亿人说西班牙语,3.41 亿人说印地语。

在互联网呈指数级增长的新兴市场,存在大量非英语用户。如果你的网站可以在全球范围内进行翻译,那么你的潜在目标市场可能会增加 700%!

i18n 全称 Internationalization,也就是国际化的意思,因为单词太长,所以中间的 18 个字母被缩写为 18,再加上开头和结尾的字母,就组成了 i18n。

JavaScript i18n API 可以帮助我们对网站进行多语言翻译,让它们可以轻松适应使用不同语言用户的需求。

在本文中,我将介绍 i18n API 提供的各种方法,以及如何在实际项目中实现 i18n 来覆盖更广泛、更国际化的用户。


i18n 其实很难


从上面的描述中,i18n 看起来很容易,但是当你尝试去做的时候,又发现它并不简单。

基于拉丁语的语言可能表面上相似。比如,请求姓名、电子邮件和日期的表单翻译如下:

英语 name email date
西班牙语 nombre email fecha
法语 nom e-mail date
德语 name email datum

Gettext 是一种在类 Unix 计算机操作系统上实现国际化和本地化程序的系统,它已经存在了几十年,而且这个库可以用在大多数编程语言中,在 nodejs 也可用。

在最简单的场景下,我们可以使用某种形式的标记来实现它。比如下面这段 HTML 模板:


<label for="name">{{ NAME }}</label>

当用户将英语设置为主要语言时,NAME 会被动态替换。

但是只是最简单的案例,实际情况中会有很多问题:

  1. 同一种语言可以有不同的变体。在西班牙使用的西班牙语与在南美洲使用的西班牙语不同。
  2. 一种语言中的单词在其他语言中可能会更长。例如,“电子邮件”在俄语中翻译为“электронное письмо”。
  3. 文本并不总是从左到右。有些语言是从右向左书写的,例如阿拉伯语、希伯来语、库尔德语和意第绪语。也有一些语言是可以从上到下书写的,比如中文、韩文、日文和闽南文。


更糟糕的问题


除了上面提到的问题,还有更糟糕的情况。

当我们需要显示日期、时间、数字、货币或单位时,会出现进一步的复杂问题。

在英文中显示其日,通常是 12/03/24 这种格式。但是在其他语言中:

  • 使用 MDY 格式的美国居民会使用 3 December 2024。
  • 使用 DMY 格式的欧洲、南美和亚洲居民会使用 12 March 2024
  • 加拿大、中国、日本和匈牙利居民会使用 2012 年 3 月 24 日,他们选择了实用得多的 YMD 格式。

英文中的数字 1,000,在其他语言中:

  • 美国、英国、加拿大、中国和日本会以千为单位,表示为一千。
  • 西班牙、法国、德国和俄罗斯会表示为一个零点,其中数字的小数部分用逗号分隔。


JavaScript Intl API


其实很多人不知道,在 JavaScript 中存在 Intl 对象

在大多数现代浏览器和运行时中都实现了 ECMAScript 国际化 API,并且兼容性还不错。甚至在 IE11 中也有很多比较有用的方法。

对于较旧的浏览器,还有一个 polyfill 可以用。

Intl API 有点不寻常。它为日期、时间、数字和列表分别提供了几个构造函数,它们会接收一个语言环境和一个包含配置参数的可选对象。

比如,指定美国英语的 DateTime 对象:


const dateFormatter = new Intl.DateTimeFormat('en-US');

这个对象可以被多次调用,传递一个 Date 实例,或者是一个 ES6 Temporal,如果它被支持的话。

format 是最常用也是最实用的方法。它的用法如下:


const valentinesDay = dateFormatter.format(new Date('2022-02-14')); 
// "2/14/2022" 
const starwarsDay = dateFormatter.format(new Date('2022-05-04')); 
// "5/4/2022"

你也可以这么用:


const starwarsDay = new Intl
  .DateTimeFormat('en-US')
  .format(new Date('2022-05-04'));

除了 format() 方法之外,某些对象还支持这些:

  • formatToParts():返回一个包含格式化字符串的对象数组,例如 { type: 'weekday', value: 'Monday' }
  • resolvedOptions(): 返回一个新对象,其属性反映所使用的语言环境和格式选项,例如 dateFormatter.resolvedOptions().locale。


定义语言环境


所有 Intl 对象都需要一个语言环境参数。它是一个字符串,它可以表示以下含义:

  • 语言子标签
  • 脚本子标签(可选)
  • 地区(或国家)子标签(可选)
  • 一个或多个变体子标签(可选)
  • 一个或多个 BCP 47 扩展序列(可选)
  • 私人使用的扩展序列(可选)

通常来说,只需要指定语言和地区就足够了。例如,"en-US"、"fr-FR"等。

除了使用字符串外,Intl.locale 对象还可用于构造语言环境,例如具有 12 小时时间格式的美国英语:


const us = new Intl.Locale('en', {
  region: 'US', hourCycle: 'h12', calendar: 'gregory'
});

这也可以在另一个 Intl 构造函数中使用。


new Intl
  .DateTimeFormat(us, { timeStyle: 'medium' })   
  .format( new Date('2022-05-04T13:00:00') ); 
// "1:00:00 PM"

如果没定义区域设置,则使用设备的当前语言和区域设置。


new Intl
  .DateTimeFormat()
  .format( new Date('2022-05-04') );

I18n 的 API 其实比较多,在这里就不再多赘述,更加详细的内容可以参考 MDN 文档

我会在下一篇文章中详细聊聊更详细的业界解决方案。

下一篇:前端 i18n 最佳实践:在 React 中使用 i18next



相关文章
|
4月前
|
自然语言处理 JavaScript 前端开发
JavaScript中闭包:概念、用途与潜在问题
【4月更文挑战第22天】JavaScript中的闭包是函数及其相关词法环境的组合,允许访问外部作用域,常用于数据封装、回调函数和装饰器。然而,不恰当使用可能导致内存泄漏和性能下降。为避免问题,需及时解除引用,减少不必要的闭包,以及优化闭包使用。理解并慎用闭包是关键。
|
4月前
|
存储 JavaScript 前端开发
解释 JavaScript 中的作用域和作用域链的概念。
【4月更文挑战第4天】JavaScript作用域定义了变量和函数的可见范围,静态决定于编码时。每个函数作为对象拥有`scope`属性,关联运行期上下文集合。执行上下文在函数执行时创建,定义执行环境,每次调用函数都会生成独特上下文。作用域链是按层级组织的作用域集合,自内向外查找变量。变量查找遵循从当前执行上下文到全局上下文的顺序,若找不到则抛出异常。
46 6
|
3月前
|
设计模式 JavaScript 前端开发
在JavaScript中,继承是一个重要的概念,它允许我们基于现有的类(或构造函数)创建新的类
【6月更文挑战第15天】JavaScript继承促进代码复用与扩展,创建类层次结构,但过深的继承链导致复杂性增加,紧密耦合增加维护成本,单继承限制灵活性,方法覆盖可能隐藏父类功能,且可能影响性能。设计时需谨慎权衡并考虑使用组合等替代方案。
44 7
|
15天前
|
自然语言处理 JavaScript 前端开发
探索JavaScript中的闭包:从基础概念到实际应用
本文深入探讨了JavaScript中闭包的概念,从定义、作用域链和实际应用等方面进行了详细阐述。通过生动的比喻和实例代码,帮助读者理解闭包在函数执行上下文中的重要性,以及如何在实际开发中有效利用闭包解决复杂问题。同时,文章也指出了过度使用闭包可能导致的潜在问题,并给出了相应的优化建议。
|
1月前
|
JavaScript 前端开发
js bom的概念
js bom的概念
29 1
|
1月前
|
JavaScript 前端开发
JavaScript BOM 的概念(浏览器对象模型)
JavaScript BOM 的概念(浏览器对象模型)
31 1
|
1月前
|
JavaScript 前端开发
JavaScript 事件的概念
JavaScript 事件的概念
52 1
|
1月前
|
JavaScript 前端开发 Java
JavaScript中的闭包概念讲解
闭包是指函数内部嵌套另一个函数,并且内部函数引用了外部函数的数据(如变量或函数)。这样的内部函数被称为闭包。以示例代码为例,`fn1` 中有两个闭包函数 `fn2` 和 `fn3`,它们都可以访问并修改 `fn1` 中的变量 `a`。
15 1
|
3月前
|
JSON JavaScript 前端开发
【JavaScript】JavaScript中的深拷贝与浅拷贝详解:基础概念与区别
JavaScript 中,理解数据拷贝的深浅至关重要。浅拷贝(如扩展运算符`...`、`Object.assign()`)仅复制对象第一层,共享内部引用,导致修改时产生意外联动。深拷贝(如自定义递归函数、`_.cloneDeep`或`JSON.parse(JSON.stringify())`)创建独立副本,确保数据隔离。选择哪种取决于性能、数据独立性和资源需求。深拷贝虽慢,但确保安全;浅拷贝快,但需小心引用共享。在面试中,理解这些概念及其应用场景是关键。
60 4
【JavaScript】JavaScript中的深拷贝与浅拷贝详解:基础概念与区别
|
3月前
|
JavaScript 前端开发
JavaScript函数核心概念:用于代码复用与管理。
【6月更文挑战第25天】JavaScript函数核心概念:用于代码复用与管理。示例包括定义(无参、有参、有返回值)与调用,参数按值传递。函数内修改参数不影响外部变量。
26 1