JavaScript 国际化字符串
在开发面向全球用户的web应用时,处理不同语言和地区的文本格式化是一项重要挑战。JavaScript提供了Intl
对象,它是ECMAScript国际化API的命名空间,可以帮助我们轻松地实现字符串、日期、数字等内容的国际化处理。
什么是国际化(i18n)?
国际化(Internationalization,简称i18n,因为首尾字母i和n之间有18个字母)是指设计和开发软件时考虑不同语言和地区的需求,使软件能够适应不同的语言和文化环境,而不需要进行工程上的修改。
i18n是"internationalization"的缩写,因为这个单词首字母i和末字母n之间有18个字母,因此缩写为"i18n"。
Intl对象简介
JavaScript的Intl
对象提供了一系列构造函数,用于格式化数字、日期时间和字符串比较等操作,让你的应用能够支持世界各地的用户语言习惯。
主要的Intl
构造函数包括:
Intl.DateTimeFormat
- 用于日期和时间的格式化Intl.NumberFormat
- 用于数字的格式化Intl.Collator
- 用于字符串比较Intl.RelativeTimeFormat
- 用于相对时间格式化Intl.ListFormat
- 用于列表格式化Intl.DisplayNames
- 用于显示语言、地区、脚本和货币的本地化名称
接下来我们将一一介绍这些功能的使用方法。
日期和时间格式化:Intl.DateTimeFormat
Intl.DateTimeFormat
可以根据不同国家和地区的习惯来格式化日期和时间。
基本用法
const date = new Date();
// 使用默认语言环境格式化日期
const defaultFormatter = new Intl.DateTimeFormat();
console.log(defaultFormatter.format(date));
// 输出(美国): 7/15/2023
// 输出(中国): 2023/7/15
// 使用中文格式化日期
const chineseFormatter = new Intl.DateTimeFormat('zh-CN');
console.log(chineseFormatter.format(date));
// 输出: 2023/7/15
// 使用英文格式化日期
const englishFormatter = new Intl.DateTimeFormat('en-US');
console.log(englishFormatter.format(date));
// 输出: 7/15/2023
// 使用德文格式化日期
const germanFormatter = new Intl.DateTimeFormat('de-DE');
console.log(germanFormatter.format(date));
// 输出: 15.7.2023
自定义格式化选项
Intl.DateTimeFormat
构造函数接受第二个参数,允许你指定更多格式化选项:
const date = new Date();
// 显示完整的日期和时间
const fullDateTime = new Intl.DateTimeFormat('zh-CN', {
dateStyle: 'full',
timeStyle: 'full'
});
console.log(fullDateTime.format(date));
// 输出: 2023年7月15日星期六 中国标准时间 上午10:30:15
// 仅显示年月日
const dateOnly = new Intl.DateTimeFormat('zh-CN', {
year: 'numeric',
month: 'long',
day: 'numeric'
});
console.log(dateOnly.format(date));
// 输出: 2023年7月15日
// 仅显示时间
const timeOnly = new Intl.DateTimeFormat('zh-CN', {
hour: 'numeric',
minute: 'numeric',
second: 'numeric'
});
console.log(timeOnly.format(date));
// 输出: 上午10:30:15
数字格式化:Intl.NumberFormat
Intl.NumberFormat
可以按照各国习惯格式化数字,包括货币、百分比等。
基本用法
const number = 123456.789;
// 使用默认语言环境格式化数字
const defaultNumberFormat = new Intl.NumberFormat();
console.log(defaultNumberFormat.format(number));
// 输出(美国): 123,456.789
// 输出(中国): 123,456.789
// 使用中文格式化数字
const chineseNumberFormat = new Intl.NumberFormat('zh-CN');
console.log(chineseNumberFormat.format(number));
// 输出: 123,456.789
// 使用德文格式化数字
const germanNumberFormat = new Intl.NumberFormat('de-DE');
console.log(germanNumberFormat.format(number));
// 输出: 123.456,789
格式化货币
const amount = 123456.789;
// 格式化为人民币
const cnyFormatter = new Intl.NumberFormat('zh-CN', {
style: 'currency',
currency: 'CNY'
});
console.log(cnyFormatter.format(amount));
// 输出: ¥123,456.79
// 格式化为美元
const usdFormatter = new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD'
});
console.log(usdFormatter.format(amount));
// 输出: $123,456.79
// 格式化为欧元
const eurFormatter = new Intl.NumberFormat('de-DE', {
style: 'currency',
currency: 'EUR'
});
console.log(eurFormatter.format(amount));
// 输出: 123.456,79 €
格式化百分比
const percentage = 0.2345;
// 格式化为百分比
const percentFormatter = new Intl.NumberFormat('zh-CN', {
style: 'percent',
minimumFractionDigits: 1,
maximumFractionDigits: 2
});
console.log(percentFormatter.format(percentage));
// 输出: 23.5%
字符串比较:Intl.Collator
Intl.Collator
提供了根据不同语言规则进行字符串比较的功能,这在排序操作中非常有用。
// 创建一个英文排序器
const englishCollator = new Intl.Collator('en');
// 比较两个字符串
console.log(englishCollator.compare('a', 'b')); // 输出: -1 (a 在 b 之前)
console.log(englishCollator.compare('b', 'a')); // 输出: 1 (b 在 a 之后)
console.log(englishCollator.compare('a', 'a')); // 输出: 0 (相等)
// 使用排序器对数组进行排序
const fruits = ['苹果', '香蕉', '橙子', '葡萄'];
fruits.sort(new Intl.Collator('zh-CN').compare);
console.log(fruits);
// 按照中文拼音顺序排序
// 不区分大小写的排序
const names = ['Adam', 'abby', 'Bob', 'bella'];
names.sort(new Intl.Collator('en', { sensitivity: 'base' }).compare);
console.log(names);
// 输出: ['abby', 'Adam', 'bella', 'Bob']
相对时间格式化:Intl.RelativeTimeFormat
Intl.RelativeTimeFormat
用于以人性化的方式表示相对时间(例如"3天前"、"5分钟后")。
// 创建一个中文相对时间格式化器
const rtf = new Intl.RelativeTimeFormat('zh-CN', { numeric: 'auto' });
console.log(rtf.format(-1, 'day')); // 输出: 昨天
console.log(rtf.format(1, 'day')); // 输出: 明天
console.log(rtf.format(-3, 'month')); // 输出: 3个月前
console.log(rtf.format(5, 'year')); // 输出: 5年后
// 创建一个英文相对时间格式化器
const rtfEn = new Intl.RelativeTimeFormat('en', { numeric: 'auto' });
console.log(rtfEn.format(-1, 'day')); // 输出: yesterday
console.log(rtfEn.format(1, 'day')); // 输出: tomorrow
console.log(rtfEn.format(-3, 'month')); // 输出: 3 months ago
console.log(rtfEn.format(5, 'year')); // 输出: in 5 years
列表格式化:Intl.ListFormat
Intl.ListFormat
可以根据语言规则将数组中的元素格式化为一个列表字符串。
// 创建一个中文列表格式化器
const listFormatter = new Intl.ListFormat('zh-CN', { style: 'long', type: 'conjunction' });
const fruits = ['苹果', '香蕉', '橙子'];
console.log(listFormatter.format(fruits));
// 输出: 苹果、香蕉和橙子
// 创建一个英文列表格式化器
const listFormatterEn = new Intl.ListFormat('en', { style: 'long', type: 'conjunction' });
const fruitsEn = ['apple', 'banana', 'orange'];
console.log(listFormatterEn.format(fruitsEn));
// 输出: apple, banana, and orange
本地化名称显示:Intl.DisplayNames
Intl.DisplayNames
用于显示语言、地区、脚本和货币的本地化名称。
// 显示语言名称
const languageNames = new Intl.DisplayNames(['zh-CN'], { type: 'language' });
console.log(languageNames.of('en-US')); // 输出: 美国英语
console.log(languageNames.of('ja')); // 输出: 日语
// 显示地区名称
const regionNames = new Intl.DisplayNames(['zh-CN'], { type: 'region' });
console.log(regionNames.of('US')); // 输出: 美国
console.log(regionNames.of('JP')); // 输出: 日本
// 显示货币名称
const currencyNames = new Intl.DisplayNames(['zh-CN'], { type: 'currency' });
console.log(currencyNames.of('USD')); // 输出: 美元
console.log(currencyNames.of('JPY')); // 输出: 日元
实际案例:多语言日期选择器
以下是一个实际案例,展示如何创建一个支持多种语言的日期选择器界面:
function createDatePicker(locale = navigator.language) {
const today = new Date();
// 创建日期格式化器
const dateFormatter = new Intl.DateTimeFormat(locale, {
year: 'numeric',
month: 'long',
day: 'numeric',
weekday: 'long'
});
// 创建月份名称格式化器
const monthFormatter = new Intl.DateTimeFormat(locale, { month: 'long' });
// 创建星期名称格式化器
const weekdayFormatter = new Intl.DateTimeFormat(locale, { weekday: 'short' });
// 获取当前月份的所有日期
const currentDate = new Date(today.getFullYear(), today.getMonth(), 1);
const month = today.getMonth();
const days = [];
// 获取星期名称
const weekdays = Array.from({ length: 7 }, (_, i) => {
const date = new Date(2021, 0, i + 3); // 从周日开始
return weekdayFormatter.format(date);
});
// 显示日历头部信息
console.log(`====== ${monthFormatter.format(today)} ${today.getFullYear()} ======`);
console.log(weekdays.join('\t'));
// 生成日历
let weekRow = Array(7).fill(' ');
const firstDay = currentDate.getDay();
while (currentDate.getMonth() === month) {
const day = currentDate.getDate();
const dayStr = day < 10 ? ` ${day}` : `${day}`;
weekRow[currentDate.getDay()] = dayStr;
// 如果是周六或月末,打印当前周
if (currentDate.getDay() === 6 ||
currentDate.getMonth() !== month) {
console.log(weekRow.join('\t'));
weekRow = Array(7).fill(' ');
}
currentDate.setDate(currentDate.getDate() + 1);
}
// 显示今天的完整日期
console.log(`\n今天是: ${dateFormatter.format(today)}`);
}
// 使用不同语言显示日期选择器
createDatePicker('zh-CN'); // 中文
// createDatePicker('en-US'); // 英文
// createDatePicker('ja-JP'); // 日语
// createDatePicker('de-DE'); // 德语
总结
JavaScript的国际化API Intl
为开发者提供了丰富的工具,使得创建多语言支持的应用变得更加容易。通过使用Intl
对象的各种构造函数,你可以:
- 根据不同地区格式化日期时间
- 按照各国习惯格式化数字、货币和百分比
- 使用语言特定规则比较和排序字符串
- 以人性化方式显示相对时间
- 格式化列表
- 显示地区化的语言、国家和货币名称
在开发国际化应用时,使用Intl
API不仅可以减少代码量,还能确保你的应用符合各地区用户的使用习惯。
练习
-
创建一个页面,显示当前时间,并允许用户切换不同的语言(如中文、英文、日语、法语等)来查看不同格式的时间表示。
-
实现一个货币转换器,允许用户输入金额,并选择不同的货币和语言环境来查看格式化后的结果。
-
创建一个排序功能,对包含多种语言字符的数组进行排序,并比较使用
Array.sort()
和Intl.Collator
的区别。