國際化很困難。處理複數形式是許多問題中的一個,看起來很簡單,直到你發現每種語言都有自己的複數形式規則。
對於英文複數形式,只有兩種可能的結果。我們以「cat」這個字為例
- 1 cat,也就是
'one'
形式,在英文中稱為單數 - 2 cats,還有 42 cats、0.5 cats 等,也就是
'other'
形式(唯一的其他形式),在英文中稱為複數。
全新的 Intl.PluralRules
API 會根據給定的數字告訴你哪個形式適用於你選擇的語言。
const pr = new Intl.PluralRules('en-US');
pr.select(0); // 'other' (e.g. '0 cats')
pr.select(0.5); // 'other' (e.g. '0.5 cats')
pr.select(1); // 'one' (e.g. '1 cat')
pr.select(1.5); // 'other' (e.g. '0.5 cats')
pr.select(2); // 'other' (e.g. '0.5 cats')
與其他國際化 API 不同,Intl.PluralRules
是一個低階 API,本身不會執行任何格式化。相反地,你可以建立自己的格式化器。
const suffixes = new Map([
// Note: in real-world scenarios, you wouldn’t hardcode the plurals
// like this; they’d be part of your translation files.
['one', 'cat'],
['other', 'cats'],
]);
const pr = new Intl.PluralRules('en-US');
const formatCats = (n) => {
const rule = pr.select(n);
const suffix = suffixes.get(rule);
return `${n} ${suffix}`;
};
formatCats(1); // '1 cat'
formatCats(0); // '0 cats'
formatCats(0.5); // '0.5 cats'
formatCats(1.5); // '1.5 cats'
formatCats(2); // '2 cats'
對於相對簡單的英文複數形式規則,這似乎有點小題大作;但是,並非所有語言都遵循相同的規則。有些語言只有一個複數形式,有些語言則有多個形式。例如,威爾斯語就有六種不同的複數形式!
const suffixes = new Map([
['zero', 'cathod'],
['one', 'gath'],
// Note: the `two` form happens to be the same as the `'one'`
// form for this word specifically, but that is not true for
// all words in Welsh.
['two', 'gath'],
['few', 'cath'],
['many', 'chath'],
['other', 'cath'],
]);
const pr = new Intl.PluralRules('cy');
const formatWelshCats = (n) => {
const rule = pr.select(n);
const suffix = suffixes.get(rule);
return `${n} ${suffix}`;
};
formatWelshCats(0); // '0 cathod'
formatWelshCats(1); // '1 gath'
formatWelshCats(1.5); // '1.5 cath'
formatWelshCats(2); // '2 gath'
formatWelshCats(3); // '3 cath'
formatWelshCats(6); // '6 chath'
formatWelshCats(42); // '42 cath'
要在支援多種語言的同時實作正確的複數形式,需要一個語言及其複數形式規則的資料庫。Unicode CLDR 包含這些資料,但要在 JavaScript 中使用它,必須將它嵌入並與其他 JavaScript 程式碼一起傳送,這會增加載入時間、解析時間和記憶體使用量。Intl.PluralRules
API 將這個負擔轉移到 JavaScript 引擎,讓國際化的複數形式更具效能。
注意:雖然 CLDR 資料包含每個語言的形式對應,但它沒有提供個別字詞的單數/複數形式清單。你仍然必須自己翻譯並提供這些形式,就像以前一樣。
序數 #
Intl.PluralRules
API 支援透過選項引數上的 type
屬性進行各種選取規則。其隱含預設值(如上述範例中所使用)為 'cardinal'
。若要找出給定數字的序數指標(例如 1
→ 1st
、2
→ 2nd
等),請使用 { type: 'ordinal' }
const pr = new Intl.PluralRules('en-US', {
type: 'ordinal'
});
const suffixes = new Map([
['one', 'st'],
['two', 'nd'],
['few', 'rd'],
['other', 'th'],
]);
const formatOrdinals = (n) => {
const rule = pr.select(n);
const suffix = suffixes.get(rule);
return `${n}${suffix}`;
};
formatOrdinals(0); // '0th'
formatOrdinals(1); // '1st'
formatOrdinals(2); // '2nd'
formatOrdinals(3); // '3rd'
formatOrdinals(4); // '4th'
formatOrdinals(11); // '11th'
formatOrdinals(21); // '21st'
formatOrdinals(42); // '42nd'
formatOrdinals(103); // '103rd'
Intl.PluralRules
是一個低階 API,特別是與其他國際化功能相比時。因此,即使你沒有直接使用它,你可能正在使用依賴它的函式庫或架構。
隨著這個 API 變得更廣泛可用,你會發現像 Globalize 這樣的函式庫會放棄對硬編碼 CLDR 資料庫的依賴,轉而採用原生功能,從而改善載入時間效能、解析時間效能、執行時間效能和記憶體使用量。
Intl.PluralRules
支援 #
- Chrome: 自版本 63 開始支援
- Firefox: 自版本 58 開始支援
- Safari: 自版本 13 開始支援
- Node.js: 自版本 10 開始支援
- Babel: 不支援