iorange(IORANGES)

JavaScript 国际化 API(也称为 I18n)允许您设计网页和应用程序,以便它们可以轻松适应使用不同语言的用户的需求。

在本文中,我们将了解 API 提供的各种方法,以及如何在代码中实现它们以覆盖更广泛、更国际化的受众。

国际化 (I18n) 可能很棘手

国际化看起来很容易……除非你尝试去做

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

  • 西班牙语: nombre, email, fecha
  • 法语:nom,电子邮件,日期
  • 德语:姓名、电子邮件、数据

Gettext国际化和本地化系统已经存在了几十年,并且库可用于大多数编程语言。

在更简单的情况下,您可以使用某种形式的标记化。例如,采用包含以下内容的 HTML 模板:

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

当用户将英语设置为其主要语言时,这将被“名称”动态替换。不幸的是,这就是您的用户界面问题开始的地方:

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

许多问题可以通过将文本保持在最低限度并采用 CSS 属性(例如direction、writing-mode和逻辑尺寸进行布局)来解决。

术语混乱

当您的应用程序需要显示日期、时间、数字、货币或单位时,将会出现进一步的混乱。

考虑显示为“12/03/24”的日期。它将被读作:

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

(请注意,日期分隔符斜线并非在所有语言中都很常见!)

数字“1,000”将被解读为:

  • 美国、英国、加拿大、中国和日本的“一千”,以及
  • 西班牙、法国、德国和俄罗斯的“一个(零点)”,其中数字的小数部分用逗号分隔。

仅用英语,情况甚至可能很复杂。术语“1,000 米”是指:

  • 1 公里(或 0.62 英里)到美国居民
  • 向英国、加拿大和澳大利亚的测量仪器收集一千件!

JavaScript 国际 API

鲜为人知的 JavaScriptIntl对象在大多数现代浏览器和运行时中实现了 ECMAScript 国际化 API。支持一般都不错,甚至IE11也有很多比较有用的方法。对于较旧的浏览器,有一个polyfill,可以像这样检测 API:

if (window.Intl) {
  // Intl supported
}

API 有点不寻常。它为日期、时间、数字和列表提供了几个对象构造函数,它们被传递一个语言环境和一个包含配置参数的可选对象。例如,这是一个DateTime指定美国英语的对象:

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

这个对象可以被多次使用来调用传递一个Date()值的各种方法(或者一个ES6 Temporal,如果可用)。该format方法通常是最实用的选择。例如:

const valentinesDay = dateFormatter.format( new Date('2022-02-14') );
// returns US format "2/14/2022"

const starwarsDay = dateFormatter.format( new Date('2022-05-04') );
// returns US format "5/4/2022"

或者,您可以Intl在一行代码中创建对象并运行方法:

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') );

这会"5/4/2022"在具有美国设置"04/05/2022"的设备和具有英国设置的设备上返回。

日期和时间

以下工具显示了使用格式的日期和时间示例(如果您的语言或地区未列出,请致歉!):Intl.DateTimeFormat()

构造函数被传递了语言环境和一个选项对象。这有许多可能的属性,尽管您很少需要超过dateStyle和/或timeStyle:

财产

描述

dateStyle

日期样式:"full" "long" "medium" "short"

timeStyle

时间风格:"full" "long" "medium" "short"

calendar

选项包括: "chinese" "gregory" "hebrew" "indian" "islamic"等。

dayPeriod

时期表达:"narrow" "short" "long"

numberingSystem

编号系统:"arab" "beng" "fullwide" "latn"

localeMatcher

语言环境匹配算法:"lookup" "best fit"

timeZone

时区:"America/New_York" "Europe/Paris"

hour12

设置true为使用 12 小时制时间表示法

hourCycle

小时周期:"h11" "h12" "h23" "h24"

formatMatcher

格式匹配算法:"basic" "best fit"

weekday

工作日格式:"long" "short" "narrow"

era

时代格式:"long" "short" "narrow"

year

年份格式:"numeric" "2-digit"

month

月份格式:"numeric" "2-digit" "long" "short" "narrow"

day

日格式:"numeric" "2-digit"

hour

小时格式:"numeric" "2-digit"

minute

分钟格式:"numeric" "2-digit"

second

第二种格式:"numeric" "2-digit"

timeZoneName

任何一个:"long" "short"

例子:

// Japanese short date, no time: "2022/05/04"
new Intl.DateTimeFormat("ja-JP", { dateStyle: "short" })
  .format( new Date("2022-05-04T13:00") );

// US short date and time: "5/4/22, 1:00 PM"
new Intl.DateTimeFormat("en-US", { dateStyle: "short", timeStyle: "short" })
  .format( new Date("2022-05-04T13:00") );

// UK long date, short time: "4 May 2022 at 13:00"
new Intl.DateTimeFormat("en-GB", { dateStyle: "long", timeStyle: "short" })
  .format( new Date("2022-05-04T13:00") );

// Spanish full date and time (dependent on your local time zone)
// "miércoles, 4 de mayo de 2022, 13:00:00 (hora de verano británica)"
new Intl.DateTimeFormat("es-ES", { dateStyle: "full", timeStyle: "full" })
  .format( new Date("2022-05-04T13:00") );

日期范围

一种formatRange()方法需要两个日期,并根据语言环境和选项以最简洁的方式格式化句点。例如:

// result: "4 May 2022, 13:00–14:00"
new Intl.DateTimeFormat("en-US", { dateStyle: "long", timeStyle: "short" })
  .formatRange(new Date("2022-05-04T13:00"), new Date("2022-05-04T14:00"))

此方法对浏览器的支持更有限,但在 Chrome 76 中实现。

相对时期

该Intl.RelativeTimeFormat()对象可以显示与该时刻相关的周期。options 对象的选项较少:

财产

描述

localeMatcher

语言环境匹配算法:"lookup" "best fit"

numeric

要么"always",例如,"1 day ago"要么"auto",例如"yesterday"

style

格式:"long" "short" "narrow"

该format()方法传递一个数值和一个单位:"year", "quarter", "month", "week", "day", "hour", "minute", or "second"。例子:

// US 1 day ago, numeric: "1 day ago"
new Intl.RelativeTimeFormat("en-US")
  .format( -1, "day" );

// US in one 1 day, auto: "tomorrow"
new Intl.RelativeTimeFormat("en-US", { numeric: "auto" })
  .format( -1, "day" );

// German, next month auto: "n?chsten Monat"
new Intl.RelativeTimeFormat("de-DE", { numeric: "auto" })
  .format( 1, "month" );

数字、货币、百分比和单位

以下工具显示了Intl.NumberFormat()用于格式化数字、货币、百分比和度量单位的示例:

构造函数被传递了语言环境和一个选项对象:

财产

描述

numberingSystem

选项包括"arab" "beng" "deva" "fullwide" "latn"等。

notation

类型:"standard" "scientific" "engineering" "compact"

style

格式化:"decimal" "currency" "percent" "unit"——这决定了可以设置哪些其他选项

currency

货币代码:"USD" "EUR" "GBP"

currencyDisplay

货币格式:"symbol" "narrowSymbol" "code" "name"

currencySign

对于负货币值、"standard"减号或"accounting"括号

unit

单位类型:等"centimeter" "inch" "hour"

unitDisplay

单位格式:"long" "short" "narrow"

useGrouping

设置 false 以禁用千位分隔符

minimumIntegerDigits

最小整数位数

minimumFractionDigits

最小小数位数

maximumFractionDigits

最大小数位数

minimumSignificantDigits

最小有效位数

maximumSignificantDigits

最大有效位数

例子:

// US number rounded to 2 decimal places: "12,345.68"
new Intl.NumberFormat("en-US", { maximumSignificantDigits: 2 })
  .format( 12345.6789 );

// French number rounded to 3 decimal places: "12?345,689"
new Intl.NumberFormat("fr-FR", { maximumSignificantDigits: 3 })
  .format( 12345.6789 );

// US compact number, 0 decimal places: "12K"
new Intl.NumberFormat("en-US", { notation: "compact", maximumSignificantDigits: 0 })
  .format( 12345.6789 );

// Spanish US dollar value: "12.345,68 US$"
new Intl.NumberFormat("es-ES", {
  style: "currency",
  currency: "USD",
  currencyDisplay: "symbol"
})
  .format( 12345.6789 );

// UK meters in long format, 0 decimal places: "12,346 metres"
new Intl.NumberFormat("en-GB", {
  maximumSignificantDigits: 0,
  style: "unit",
  unit: "meter",
  unitDisplay: "long"
})
  .format( 12345.6789 );

列表

一个Intl.ListFormat()对象可以将一组项目格式化为一个语言敏感的列表。在英语中,这通常需要在最后一项之前使用“and”“or” 。

选项对象可以设置以下属性:

财产

描述

type

输出格式:基于"conjunction"for和 –的列表,基于"disjunction"for-的列表

style

格式化:"long" "short" "narrow"

例子:

const browsers = ['Chrome', 'Firefox', 'Edge', 'Safari'];

// US English: "Chrome, Firefox, Edge, and Safari"
new Intl.ListFormat("en-US", { type: "conjunction" }).format(browsers);

// US English: "Chrome, Firefox, Edge, or Safari"
new Intl.ListFormat("en-US", { type: "disjunction" }).format(browsers);

// French: "Chrome, Firefox, Edge, et Safari"
new Intl.ListFormat("fr-FR", { type: "conjunction" }).format(browsers);

// French: "Chrome, Firefox, Edge, ou Safari"
new Intl.ListFormat("fr-FR", { type: "disjunction" }).format(browsers);

复数

稍微奇怪的Intl.PluralRules()对象启用复数敏感的语言规则,其中您有许多项目。options 对象可以将属性设置type为:

  • cardinal:事物的数量(默认),或
  • ordinal: 事物的排名,如1st, 2nd, 或3rd英文

该select()方法返回一个表示数字复数类别的英文字符串:every zero, one, two, few, many, or other。

例子:

// US English zero cardinal: "other"
new Intl.PluralRules("en-US", { type: "cardinal" }).select(0);

// US English zero ordinal: "other"
new Intl.PluralRules("en-US", { type: "ordinal" }).select(0);

// US English 1 cardinal: "one"
new Intl.PluralRules("en-US", { type: "cardinal" }).select(1);

// US English 1 ordinal: "one"
new Intl.PluralRules("en-US", { type: "ordinal" }).select(1);

// US English 2 cardinal: "other"
new Intl.PluralRules("en-US", { type: "cardinal" }).select(2);

// US English 2 ordinal: "two"
new Intl.PluralRules("en-US", { type: "ordinal" }).select(2);

// US English 3 cardinal: "other"
new Intl.PluralRules("en-US", { type: "cardinal" }).select(3);

// US English 3 ordinal: "few"
new Intl.PluralRules("en-US", { type: "ordinal" }).select(3);

字符串比较

最后,该Intl.Collator()对象启用对语言敏感的字符串比较。它的选项对象可以设置以下属性:

财产

描述

collation

某些语言环境的变体排序规则

numeric

设置true数字排序规则,其中“1”<“2”<“10”

caseFirst

要么"upper""lower"案例优先

usage

字符串"sort"(默认)或"search"

sensitivity

"base" "accent" "case" "variant"比较

ignorePunctuation

设置true为忽略标点符号

该compare()方法比较两个字符串。例如:

// German: returns 1
new Intl.Collator('de').compare('z', '?');

利润!

如果您使用 JavaScript 显示数据,那么使用用户的本地格式显示信息应该很简单。例如,以下代码定义了一个dateFormat()使用Intl短日期格式的函数,或者在不受支持时回退到YYYY-MM-DD :

// date formatting function
const dateFormat = (Intl && Intl.DateTimeFormat ?
  date => new Intl.DateTimeFormat({ dateStyle: 'short' }).format(date) :
  date => date.toISOString().slice(0, 10)
);

// insert today's date into DOM #today element
document.getElementById('today').textContent = dateFormat( new Date() );

仅这一点并不能让您的应用程序易于为国际用户所接受,但它离全球发行更近了一步。

    
本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 cloud@ksuyun.com 举报,一经查实,本站将立刻删除。
如若转载,请注明出处:https://www.daxuejiayuan.com/19992.html