summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
authorTimothy Flynn <trflynn89@pm.me>2022-07-14 13:55:13 -0400
committerAndreas Kling <kling@serenityos.org>2022-07-15 12:31:43 +0200
commitaafcdc4c72a7d1d4583ea6eac673a52879b043f4 (patch)
tree56537ca46b447388c646c3cd9423ea80c815e04e /Userland
parentb24b9c0a656629bc6e01ca57bbf861b0a7870bc3 (diff)
downloadserenity-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')
-rw-r--r--Userland/Libraries/LibJS/Runtime/Intl/AbstractOperations.cpp10
-rw-r--r--Userland/Libraries/LibJS/Tests/builtins/Intl/DateTimeFormat/DateTimeFormat.prototype.resolvedOptions.js4
-rw-r--r--Userland/Libraries/LibJS/Tests/builtins/Intl/DurationFormat/DurationFormat.prototype.resolvedOptions.js4
-rw-r--r--Userland/Libraries/LibJS/Tests/builtins/Intl/NumberFormat/NumberFormat.prototype.format.js28
-rw-r--r--Userland/Libraries/LibJS/Tests/builtins/Intl/NumberFormat/NumberFormat.prototype.resolvedOptions.js4
-rw-r--r--Userland/Libraries/LibJS/Tests/builtins/Intl/RelativeTimeFormat/RelativeTimeFormat.prototype.resolvedOptions.js4
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");
});