diff --git a/Meta/Lagom/Tools/CodeGenerators/LibUnicode/GenerateUnicodeLocale.cpp b/Meta/Lagom/Tools/CodeGenerators/LibUnicode/GenerateUnicodeLocale.cpp index 229d022b01..b8d2d1cb5f 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibUnicode/GenerateUnicodeLocale.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibUnicode/GenerateUnicodeLocale.cpp @@ -40,7 +40,10 @@ struct Locale { HashMap languages; HashMap territories; HashMap scripts; - HashMap currencies; + HashMap long_currencies; + HashMap short_currencies; + HashMap narrow_currencies; + HashMap numeric_currencies; HashMap keywords; Vector list_patterns; }; @@ -335,10 +338,15 @@ static void parse_locale_currencies(String numbers_path, UnicodeLocaleData& loca auto const& currencies_object = locale_numbers_object.as_object().get("currencies"sv); currencies_object.as_object().for_each_member([&](auto const& key, JsonValue const& value) { - auto const& display_name = value.as_object().get("displayName"sv); + auto const& long_name = value.as_object().get("displayName"sv); + auto const& short_name = value.as_object().get("symbol"sv); + auto const& narrow_name = value.as_object().get("symbol-alt-narrow"sv); + auto const& numeric_name = value.as_object().get("displayName-count-other"sv); - auto index = locale_data.unique_strings.ensure(display_name.as_string()); - locale.currencies.set(key, index); + locale.long_currencies.set(key, locale_data.unique_strings.ensure(long_name.as_string())); + locale.short_currencies.set(key, locale_data.unique_strings.ensure(short_name.as_string())); + locale.narrow_currencies.set(key, narrow_name.is_null() ? 0 : locale_data.unique_strings.ensure(narrow_name.as_string())); + locale.numeric_currencies.set(key, locale_data.unique_strings.ensure(numeric_name.is_null() ? long_name.as_string() : numeric_name.as_string())); if (!locale_data.currencies.contains_slow(key)) locale_data.currencies.append(key); @@ -565,7 +573,10 @@ Optional get_locale_script_tag_mapping(StringView locale, StringView Optional script_tag_from_string(StringView script_tag); Optional resolve_script_tag_alias(StringView script_tag); -Optional get_locale_currency_mapping(StringView locale, StringView currency); +Optional get_locale_long_currency_mapping(StringView locale, StringView currency); +Optional get_locale_short_currency_mapping(StringView locale, StringView currency); +Optional get_locale_narrow_currency_mapping(StringView locale, StringView currency); +Optional get_locale_numeric_currency_mapping(StringView locale, StringView currency); Optional currency_from_string(StringView currency); Optional get_locale_key_mapping(StringView locale, StringView key); @@ -700,7 +711,10 @@ static constexpr Array @name@ { {)~~~"); generate_mapping(generator, locale_data.locales, s_string_index_type, "s_languages"sv, "s_languages_{}", [&](auto const& name, auto const& value) { append_string_index_list(name, locale_data.languages, value.languages); }); generate_mapping(generator, locale_data.locales, s_string_index_type, "s_territories"sv, "s_territories_{}", [&](auto const& name, auto const& value) { append_string_index_list(name, locale_data.territories, value.territories); }); generate_mapping(generator, locale_data.locales, s_string_index_type, "s_scripts"sv, "s_scripts_{}", [&](auto const& name, auto const& value) { append_string_index_list(name, locale_data.scripts, value.scripts); }); - generate_mapping(generator, locale_data.locales, s_string_index_type, "s_currencies"sv, "s_currencies_{}", [&](auto const& name, auto const& value) { append_string_index_list(name, locale_data.currencies, value.currencies); }); + generate_mapping(generator, locale_data.locales, s_string_index_type, "s_long_currencies"sv, "s_long_currencies_{}", [&](auto const& name, auto const& value) { append_string_index_list(name, locale_data.currencies, value.long_currencies); }); + generate_mapping(generator, locale_data.locales, s_string_index_type, "s_short_currencies"sv, "s_short_currencies_{}", [&](auto const& name, auto const& value) { append_string_index_list(name, locale_data.currencies, value.short_currencies); }); + generate_mapping(generator, locale_data.locales, s_string_index_type, "s_narrow_currencies"sv, "s_narrow_currencies_{}", [&](auto const& name, auto const& value) { append_string_index_list(name, locale_data.currencies, value.narrow_currencies); }); + generate_mapping(generator, locale_data.locales, s_string_index_type, "s_numeric_currencies"sv, "s_numeric_currencies_{}", [&](auto const& name, auto const& value) { append_string_index_list(name, locale_data.currencies, value.numeric_currencies); }); generate_mapping(generator, locale_data.locales, s_string_index_type, "s_keywords"sv, "s_keywords_{}", [&](auto const& name, auto const& value) { append_string_index_list(name, locale_data.keywords, value.keywords); }); generate_mapping(generator, locale_data.locales, "Patterns"sv, "s_list_patterns"sv, "s_list_patterns_{}", [&](auto const& name, auto const& value) { append_list_patterns(name, value.list_patterns); }); @@ -884,9 +898,9 @@ static LanguageMapping const* resolve_likely_subtag(Unicode::LanguageID const& l )~~~"); - auto append_mapping_search = [&](StringView enum_title, StringView enum_snake, StringView collection_name) { - generator.set("enum_title", enum_title); + auto append_mapping_search = [&](StringView enum_snake, StringView from_string_name, StringView collection_name) { generator.set("enum_snake", enum_snake); + generator.set("from_string_name", from_string_name); generator.set("collection_name", collection_name); generator.append(R"~~~( Optional get_locale_@enum_snake@_mapping(StringView locale, StringView @enum_snake@) @@ -895,7 +909,7 @@ Optional get_locale_@enum_snake@_mapping(StringView locale, StringVi if (!locale_value.has_value()) return {}; - auto @enum_snake@_value = @enum_snake@_from_string(@enum_snake@); + auto @enum_snake@_value = @from_string_name@_from_string(@enum_snake@); if (!@enum_snake@_value.has_value()) return {}; @@ -935,22 +949,25 @@ Optional get_locale_@enum_snake@_mapping(StringView locale, StringVi append_from_string("Locale"sv, "locale"sv, locale_data.locales.keys()); - append_mapping_search("Language"sv, "language"sv, "s_languages"sv); + append_mapping_search("language"sv, "language"sv, "s_languages"sv); append_from_string("Language"sv, "language"sv, locale_data.languages); append_alias_search("language"sv, locale_data.language_aliases); - append_mapping_search("Territory"sv, "territory"sv, "s_territories"sv); + append_mapping_search("territory"sv, "territory"sv, "s_territories"sv); append_from_string("Territory"sv, "territory"sv, locale_data.territories); append_alias_search("territory"sv, locale_data.territory_aliases); - append_mapping_search("ScriptTag"sv, "script_tag"sv, "s_scripts"sv); + append_mapping_search("script_tag"sv, "script_tag"sv, "s_scripts"sv); append_from_string("ScriptTag"sv, "script_tag"sv, locale_data.scripts); append_alias_search("script_tag"sv, locale_data.script_aliases); - append_mapping_search("Currency"sv, "currency"sv, "s_currencies"sv); + append_mapping_search("long_currency"sv, "currency"sv, "s_long_currencies"sv); + append_mapping_search("short_currency"sv, "currency"sv, "s_short_currencies"sv); + append_mapping_search("narrow_currency"sv, "currency"sv, "s_narrow_currencies"sv); + append_mapping_search("numeric_currency"sv, "currency"sv, "s_numeric_currencies"sv); append_from_string("Currency"sv, "currency"sv, locale_data.currencies); - append_mapping_search("Key"sv, "key"sv, "s_keywords"sv); + append_mapping_search("key"sv, "key"sv, "s_keywords"sv); append_from_string("Key"sv, "key"sv, locale_data.keywords); append_alias_search("variant"sv, locale_data.variant_aliases); diff --git a/Userland/Libraries/LibJS/Runtime/Intl/DisplayNamesPrototype.cpp b/Userland/Libraries/LibJS/Runtime/Intl/DisplayNamesPrototype.cpp index 5370b64670..e59954919c 100644 --- a/Userland/Libraries/LibJS/Runtime/Intl/DisplayNamesPrototype.cpp +++ b/Userland/Libraries/LibJS/Runtime/Intl/DisplayNamesPrototype.cpp @@ -63,7 +63,19 @@ JS_DEFINE_NATIVE_FUNCTION(DisplayNamesPrototype::of) result = Unicode::get_locale_script_mapping(display_names->locale(), code.as_string().string()); break; case DisplayNames::Type::Currency: - result = Unicode::get_locale_currency_mapping(display_names->locale(), code.as_string().string()); + switch (display_names->style()) { + case DisplayNames::Style::Long: + result = Unicode::get_locale_currency_mapping(display_names->locale(), code.as_string().string(), Unicode::Style::Long); + break; + case DisplayNames::Style::Short: + result = Unicode::get_locale_currency_mapping(display_names->locale(), code.as_string().string(), Unicode::Style::Short); + break; + case DisplayNames::Style::Narrow: + result = Unicode::get_locale_currency_mapping(display_names->locale(), code.as_string().string(), Unicode::Style::Narrow); + break; + default: + VERIFY_NOT_REACHED(); + } break; default: VERIFY_NOT_REACHED(); diff --git a/Userland/Libraries/LibJS/Tests/builtins/Intl/DisplayNames/DisplayNames.prototype.of.js b/Userland/Libraries/LibJS/Tests/builtins/Intl/DisplayNames/DisplayNames.prototype.of.js index 7cee5637c8..3f85173188 100644 --- a/Userland/Libraries/LibJS/Tests/builtins/Intl/DisplayNames/DisplayNames.prototype.of.js +++ b/Userland/Libraries/LibJS/Tests/builtins/Intl/DisplayNames/DisplayNames.prototype.of.js @@ -74,18 +74,48 @@ describe("correct behavior", () => { expect(zhHant.of("Aaaa")).toBe("Aaaa"); }); - test("option type currency", () => { - const en = new Intl.DisplayNames("en", { type: "currency" }); + test("option type currency, style long", () => { + const en = new Intl.DisplayNames("en", { type: "currency", style: "long" }); expect(en.of("USD")).toBe("US Dollar"); - const es419 = new Intl.DisplayNames("es-419", { type: "currency" }); + const es419 = new Intl.DisplayNames("es-419", { type: "currency", style: "long" }); expect(es419.of("USD")).toBe("dólar estadounidense"); - const zhHant = new Intl.DisplayNames(["zh-Hant"], { type: "currency" }); + const zhHant = new Intl.DisplayNames(["zh-Hant"], { type: "currency", style: "long" }); expect(zhHant.of("USD")).toBe("美元"); expect(en.of("AAA")).toBe("AAA"); expect(es419.of("AAA")).toBe("AAA"); expect(zhHant.of("AAA")).toBe("AAA"); }); + + test("option type currency, style short", () => { + const en = new Intl.DisplayNames("en", { type: "currency", style: "short" }); + expect(en.of("USD")).toBe("$"); + + const es419 = new Intl.DisplayNames("es-419", { type: "currency", style: "short" }); + expect(es419.of("USD")).toBe("USD"); + + const zhHant = new Intl.DisplayNames(["zh-Hant"], { type: "currency", style: "short" }); + expect(zhHant.of("USD")).toBe("US$"); + + expect(en.of("AAA")).toBe("AAA"); + expect(es419.of("AAA")).toBe("AAA"); + expect(zhHant.of("AAA")).toBe("AAA"); + }); + + test("option type currency, style narrow", () => { + const en = new Intl.DisplayNames("en", { type: "currency", style: "narrow" }); + expect(en.of("USD")).toBe("$"); + + const es419 = new Intl.DisplayNames("es-419", { type: "currency", style: "narrow" }); + expect(es419.of("USD")).toBe("$"); + + const zhHant = new Intl.DisplayNames(["zh-Hant"], { type: "currency", style: "narrow" }); + expect(zhHant.of("USD")).toBe("$"); + + expect(en.of("AAA")).toBe("AAA"); + expect(es419.of("AAA")).toBe("AAA"); + expect(zhHant.of("AAA")).toBe("AAA"); + }); }); diff --git a/Userland/Libraries/LibUnicode/Locale.cpp b/Userland/Libraries/LibUnicode/Locale.cpp index 60cc6c7ec4..92cbd88f88 100644 --- a/Userland/Libraries/LibUnicode/Locale.cpp +++ b/Userland/Libraries/LibUnicode/Locale.cpp @@ -786,13 +786,21 @@ Optional get_locale_script_mapping([[maybe_unused]] StringView local #endif } -Optional get_locale_currency_mapping([[maybe_unused]] StringView locale, [[maybe_unused]] StringView currency) +Optional get_locale_currency_mapping([[maybe_unused]] StringView locale, [[maybe_unused]] StringView currency, [[maybe_unused]] Style style) { #if ENABLE_UNICODE_DATA - return Detail::get_locale_currency_mapping(locale, currency); -#else - return {}; + switch (style) { + case Style::Long: + return Detail::get_locale_long_currency_mapping(locale, currency); + case Style::Short: + return Detail::get_locale_short_currency_mapping(locale, currency); + case Style::Narrow: + return Detail::get_locale_narrow_currency_mapping(locale, currency); + case Style::Numeric: + return Detail::get_locale_numeric_currency_mapping(locale, currency); + } #endif + return {}; } Vector get_locale_key_mapping([[maybe_unused]] StringView locale, [[maybe_unused]] StringView keyword) diff --git a/Userland/Libraries/LibUnicode/Locale.h b/Userland/Libraries/LibUnicode/Locale.h index 3c53705a1a..504bec6dbd 100644 --- a/Userland/Libraries/LibUnicode/Locale.h +++ b/Userland/Libraries/LibUnicode/Locale.h @@ -78,6 +78,13 @@ struct LocaleID { Vector private_use_extensions {}; }; +enum class Style : u8 { + Long, + Short, + Narrow, + Numeric, +}; + enum class StandardNumberFormatType : u8 { Decimal, Currency, @@ -170,7 +177,7 @@ Optional locale_from_string(StringView locale); Optional get_locale_language_mapping(StringView locale, StringView language); Optional get_locale_territory_mapping(StringView locale, StringView territory); Optional get_locale_script_mapping(StringView locale, StringView script); -Optional get_locale_currency_mapping(StringView locale, StringView currency); +Optional get_locale_currency_mapping(StringView locale, StringView currency, Style style); Vector get_locale_key_mapping(StringView locale, StringView keyword); Optional get_number_system_symbol(StringView locale, StringView system, StringView symbol); Optional get_standard_number_system_format(StringView locale, StringView system, StandardNumberFormatType type);