diff --git a/Libraries/LibJS/Tests/builtins/Intl/Collator/Collator.prototype.resolvedOptions.js b/Libraries/LibJS/Tests/builtins/Intl/Collator/Collator.prototype.resolvedOptions.js index 7f16fe19df9..225e05b5889 100644 --- a/Libraries/LibJS/Tests/builtins/Intl/Collator/Collator.prototype.resolvedOptions.js +++ b/Libraries/LibJS/Tests/builtins/Intl/Collator/Collator.prototype.resolvedOptions.js @@ -54,12 +54,21 @@ describe("correct behavior", () => { }); test("collation", () => { - // Only "default" collation is parsed for now. - const en = new Intl.Collator("en"); - expect(en.resolvedOptions().collation).toBe("default"); + const en1 = new Intl.Collator("en"); + expect(en1.resolvedOptions().locale).toBe("en"); + expect(en1.resolvedOptions().collation).toBe("default"); + + const en2 = new Intl.Collator("en-u-co-phonebk", { collation: "pinyin" }); + expect(en2.resolvedOptions().locale).toBe("en"); + expect(en2.resolvedOptions().collation).toBe("default"); const el = new Intl.Collator("el", { collation: "foo" }); + expect(el.resolvedOptions().locale).toBe("el"); expect(el.resolvedOptions().collation).toBe("default"); + + const de = new Intl.Collator("de-u-co-phonebk", { collation: "pinyin" }); + expect(de.resolvedOptions().locale).toBe("de-u-co-phonebk"); + expect(de.resolvedOptions().collation).toBe("phonebk"); }); test("numeric may be set by locale extension", () => { diff --git a/Libraries/LibJS/Tests/builtins/Intl/Intl.supportedValuesOf.js b/Libraries/LibJS/Tests/builtins/Intl/Intl.supportedValuesOf.js index 74d5550d5f2..a75dc2067af 100644 --- a/Libraries/LibJS/Tests/builtins/Intl/Intl.supportedValuesOf.js +++ b/Libraries/LibJS/Tests/builtins/Intl/Intl.supportedValuesOf.js @@ -26,7 +26,7 @@ describe("normal behavior", () => { const values = Intl.supportedValuesOf("collation"); expect(isSorted(values)).toBeTrue(); - expect(values.indexOf("default")).not.toBe(-1); + expect(values.indexOf("emoji")).not.toBe(-1); }); test("currency", () => { diff --git a/Libraries/LibUnicode/UnicodeKeywords.cpp b/Libraries/LibUnicode/UnicodeKeywords.cpp index fec6d4a006d..b582cdef966 100644 --- a/Libraries/LibUnicode/UnicodeKeywords.cpp +++ b/Libraries/LibUnicode/UnicodeKeywords.cpp @@ -110,15 +110,48 @@ Vector const& available_collation_numeric_orderings() Vector const& available_collations() { - // FIXME: Implement this when we fully support Intl.Collator. - static Vector collations { "default"_string }; + static auto collations = []() -> Vector { + UErrorCode status = U_ZERO_ERROR; + + auto keywords = adopt_own_if_nonnull(icu::Collator::getKeywordValues("collation", status)); + if (icu_failure(status)) + return {}; + + auto collations = icu_string_enumeration_to_list(move(keywords), "co", [](char const* value, size_t value_length) { + // https://tc39.es/ecma402/#sec-properties-of-intl-collator-instances + // the values "standard" and "search" are not allowed + return !StringView { value, value_length }.is_one_of("standard"sv, "search"sv); + }); + + quick_sort(collations); + return collations; + }(); + return collations; } -Vector available_collations(StringView) +Vector available_collations(StringView locale) { - // FIXME: Implement this when we fully support Intl.Collator. - return available_collations(); + UErrorCode status = U_ZERO_ERROR; + + auto locale_data = LocaleData::for_locale(locale); + if (!locale_data.has_value()) + return {}; + + auto keywords = adopt_own_if_nonnull(icu::Collator::getKeywordValuesForLocale("collation", locale_data->locale(), true, status)); + if (icu_failure(status)) + return {}; + + auto collations = icu_string_enumeration_to_list(move(keywords), "co", [](char const* value, size_t value_length) { + // https://tc39.es/ecma402/#sec-properties-of-intl-collator-instances + // the values "standard" and "search" are not allowed + return !StringView { value, value_length }.is_one_of("standard"sv, "search"sv); + }); + + if (!collations.contains_slow("default"sv)) + collations.prepend("default"_string); + + return collations; } Vector const& available_hour_cycles()