diff options
author | Timothy Flynn <trflynn89@pm.me> | 2022-07-14 13:55:13 -0400 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-07-15 12:31:43 +0200 |
commit | aafcdc4c72a7d1d4583ea6eac673a52879b043f4 (patch) | |
tree | 56537ca46b447388c646c3cd9423ea80c815e04e /Userland | |
parent | b24b9c0a656629bc6e01ca57bbf861b0a7870bc3 (diff) | |
download | serenity-aafcdc4c72a7d1d4583ea6eac673a52879b043f4.zip |
LibJS: Allow specifying keyword values not directly defined for a locale
For example, consider the locales "en-u-nu-fullwide" or "en-u-nu-arab".
The CLDR only declares the "latn" numbering system for the "en" locale,
thus ResolveLocale would change the locale to "en-u-nu-latn". This patch
allows using non-latn numbering systems digits.
Diffstat (limited to 'Userland')
6 files changed, 42 insertions, 12 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/Intl/AbstractOperations.cpp b/Userland/Libraries/LibJS/Runtime/Intl/AbstractOperations.cpp index b22bf44c7c..de552b5f7e 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/AbstractOperations.cpp +++ b/Userland/Libraries/LibJS/Runtime/Intl/AbstractOperations.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Tim Flynn <trflynn89@serenityos.org> + * Copyright (c) 2021-2022, Tim Flynn <trflynn89@serenityos.org> * * SPDX-License-Identifier: BSD-2-Clause */ @@ -425,13 +425,15 @@ LocaleResult resolve_locale(Vector<String> const& requested_locales, LocaleOptio // b. Assert: Type(foundLocaleData) is Record. // c. Let keyLocaleData be foundLocaleData.[[<key>]]. // d. Assert: Type(keyLocaleData) is List. - auto key_locale_data = Unicode::get_keywords_for_locale(found_locale, key); + auto key_locale_data = Unicode::get_available_keyword_values(key); // e. Let value be keyLocaleData[0]. // f. Assert: Type(value) is either String or Null. + // NOTE: ECMA-402 assumes keyLocaleData is sorted by locale preference. Our list is sorted + // alphabetically, so we get the locale's preferred value from LibUnicode. Optional<String> value; - if (!key_locale_data.is_empty()) - value = key_locale_data[0]; + if (auto preference = Unicode::get_preferred_keyword_value_for_locale(found_locale, key); preference.has_value()) + value = *preference; // g. Let supportedExtensionAddition be "". Optional<Unicode::Keyword> supported_extension_addition {}; diff --git a/Userland/Libraries/LibJS/Tests/builtins/Intl/DateTimeFormat/DateTimeFormat.prototype.resolvedOptions.js b/Userland/Libraries/LibJS/Tests/builtins/Intl/DateTimeFormat/DateTimeFormat.prototype.resolvedOptions.js index 0546b115bd..44096a858b 100644 --- a/Userland/Libraries/LibJS/Tests/builtins/Intl/DateTimeFormat/DateTimeFormat.prototype.resolvedOptions.js +++ b/Userland/Libraries/LibJS/Tests/builtins/Intl/DateTimeFormat/DateTimeFormat.prototype.resolvedOptions.js @@ -64,12 +64,12 @@ describe("correct behavior", () => { }); test("numberingSystem option limited to known 'nu' values", () => { - ["latn", "arab"].forEach(numberingSystem => { + ["latn", "foo"].forEach(numberingSystem => { const en = Intl.DateTimeFormat("en", { numberingSystem: numberingSystem }); expect(en.resolvedOptions().numberingSystem).toBe("latn"); }); - ["latn", "arab"].forEach(numberingSystem => { + ["latn", "foo"].forEach(numberingSystem => { const en = Intl.DateTimeFormat(`en-u-nu-${numberingSystem}`); expect(en.resolvedOptions().numberingSystem).toBe("latn"); }); diff --git a/Userland/Libraries/LibJS/Tests/builtins/Intl/DurationFormat/DurationFormat.prototype.resolvedOptions.js b/Userland/Libraries/LibJS/Tests/builtins/Intl/DurationFormat/DurationFormat.prototype.resolvedOptions.js index 2678782770..bfd6e10083 100644 --- a/Userland/Libraries/LibJS/Tests/builtins/Intl/DurationFormat/DurationFormat.prototype.resolvedOptions.js +++ b/Userland/Libraries/LibJS/Tests/builtins/Intl/DurationFormat/DurationFormat.prototype.resolvedOptions.js @@ -33,12 +33,12 @@ describe("correct behavior", () => { }); test("numberingSystem option limited to known 'nu' values", () => { - ["latn", "arab"].forEach(numberingSystem => { + ["latn", "foo"].forEach(numberingSystem => { const en = new Intl.DurationFormat("en", { numberingSystem: numberingSystem }); expect(en.resolvedOptions().numberingSystem).toBe("latn"); }); - ["latn", "arab"].forEach(numberingSystem => { + ["latn", "foo"].forEach(numberingSystem => { const en = new Intl.DurationFormat(`en-u-nu-${numberingSystem}`); expect(en.resolvedOptions().numberingSystem).toBe("latn"); }); diff --git a/Userland/Libraries/LibJS/Tests/builtins/Intl/NumberFormat/NumberFormat.prototype.format.js b/Userland/Libraries/LibJS/Tests/builtins/Intl/NumberFormat/NumberFormat.prototype.format.js index 1d1d7d3c9c..897ac1a422 100644 --- a/Userland/Libraries/LibJS/Tests/builtins/Intl/NumberFormat/NumberFormat.prototype.format.js +++ b/Userland/Libraries/LibJS/Tests/builtins/Intl/NumberFormat/NumberFormat.prototype.format.js @@ -207,6 +207,21 @@ describe("style=decimal", () => { expect(en.format(12000000)).toBe("12 million"); expect(en.format(12900000)).toBe("13 million"); + const enFullwide = new Intl.NumberFormat("en", { + notation: "compact", + compactDisplay: "long", + numberingSystem: "fullwide", + }); + expect(enFullwide.format(1)).toBe("1"); + expect(enFullwide.format(1200)).toBe("1.2 thousand"); + expect(enFullwide.format(1290)).toBe("1.3 thousand"); + expect(enFullwide.format(12000)).toBe("12 thousand"); + expect(enFullwide.format(12900)).toBe("13 thousand"); + expect(enFullwide.format(1200000)).toBe("1.2 million"); + expect(enFullwide.format(1290000)).toBe("1.3 million"); + expect(enFullwide.format(12000000)).toBe("12 million"); + expect(enFullwide.format(12900000)).toBe("13 million"); + const ar = new Intl.NumberFormat("ar", { notation: "compact", compactDisplay: "long" }); expect(ar.format(1)).toBe("\u0661"); expect(ar.format(1200)).toBe("\u0661\u066b\u0662 ألف"); @@ -579,6 +594,19 @@ describe("style=percent", () => { expect(en.format(0.123)).toBe("12%"); expect(en.format(0.1234)).toBe("12%"); + const enFullwide = new Intl.NumberFormat("en", { + style: "percent", + notation: "compact", + numberingSystem: "fullwide", + }); + expect(enFullwide.format(0.01)).toBe("1%"); + expect(enFullwide.format(0.012)).toBe("1.2%"); + expect(enFullwide.format(0.0123)).toBe("1.2%"); + expect(enFullwide.format(0.0129)).toBe("1.3%"); + expect(enFullwide.format(0.12)).toBe("12%"); + expect(enFullwide.format(0.123)).toBe("12%"); + expect(enFullwide.format(0.1234)).toBe("12%"); + const ar = new Intl.NumberFormat("ar", { style: "percent", notation: "compact" }); expect(ar.format(0.01)).toBe("\u0661\u066a\u061c"); expect(ar.format(0.012)).toBe("\u0661\u066b\u0662\u066a\u061c"); diff --git a/Userland/Libraries/LibJS/Tests/builtins/Intl/NumberFormat/NumberFormat.prototype.resolvedOptions.js b/Userland/Libraries/LibJS/Tests/builtins/Intl/NumberFormat/NumberFormat.prototype.resolvedOptions.js index 8dafec921c..e8ee8db9ac 100644 --- a/Userland/Libraries/LibJS/Tests/builtins/Intl/NumberFormat/NumberFormat.prototype.resolvedOptions.js +++ b/Userland/Libraries/LibJS/Tests/builtins/Intl/NumberFormat/NumberFormat.prototype.resolvedOptions.js @@ -36,12 +36,12 @@ describe("correct behavior", () => { }); test("numberingSystem option limited to known 'nu' values", () => { - ["latn", "arab"].forEach(numberingSystem => { + ["latn", "foo"].forEach(numberingSystem => { const en = Intl.NumberFormat("en", { numberingSystem: numberingSystem }); expect(en.resolvedOptions().numberingSystem).toBe("latn"); }); - ["latn", "arab"].forEach(numberingSystem => { + ["latn", "foo"].forEach(numberingSystem => { const en = Intl.NumberFormat(`en-u-nu-${numberingSystem}`); expect(en.resolvedOptions().numberingSystem).toBe("latn"); }); diff --git a/Userland/Libraries/LibJS/Tests/builtins/Intl/RelativeTimeFormat/RelativeTimeFormat.prototype.resolvedOptions.js b/Userland/Libraries/LibJS/Tests/builtins/Intl/RelativeTimeFormat/RelativeTimeFormat.prototype.resolvedOptions.js index 913901855a..ff7986a52e 100644 --- a/Userland/Libraries/LibJS/Tests/builtins/Intl/RelativeTimeFormat/RelativeTimeFormat.prototype.resolvedOptions.js +++ b/Userland/Libraries/LibJS/Tests/builtins/Intl/RelativeTimeFormat/RelativeTimeFormat.prototype.resolvedOptions.js @@ -36,12 +36,12 @@ describe("correct behavior", () => { }); test("numberingSystem option limited to known 'nu' values", () => { - ["latn", "arab"].forEach(numberingSystem => { + ["latn", "foo"].forEach(numberingSystem => { const en = new Intl.RelativeTimeFormat("en", { numberingSystem: numberingSystem }); expect(en.resolvedOptions().numberingSystem).toBe("latn"); }); - ["latn", "arab"].forEach(numberingSystem => { + ["latn", "foo"].forEach(numberingSystem => { const en = new Intl.RelativeTimeFormat(`en-u-nu-${numberingSystem}`); expect(en.resolvedOptions().numberingSystem).toBe("latn"); }); |