summaryrefslogtreecommitdiff
path: root/Meta/Lagom/Tools
diff options
context:
space:
mode:
authorTimothy Flynn <trflynn89@pm.me>2022-01-13 13:10:24 -0500
committerLinus Groh <mail@linusgroh.de>2022-01-13 23:05:31 +0100
commit91acc2e9c541e26d4a729294906840bd23b1ff5a (patch)
tree767396856df845a301781203b5af58556438a13c /Meta/Lagom/Tools
parentcfb9f889ac92383c527b578797241469f3d5f8d1 (diff)
downloadserenity-91acc2e9c541e26d4a729294906840bd23b1ff5a.zip
LibUnicode: Parse and generate locale display patterns
These patterns indicate how to display locale strings when that locale contains multiple subtags. For example, "en-US" would be displayed as "English (United States)".
Diffstat (limited to 'Meta/Lagom/Tools')
-rw-r--r--Meta/Lagom/Tools/CodeGenerators/LibUnicode/GenerateUnicodeLocale.cpp95
1 files changed, 94 insertions, 1 deletions
diff --git a/Meta/Lagom/Tools/CodeGenerators/LibUnicode/GenerateUnicodeLocale.cpp b/Meta/Lagom/Tools/CodeGenerators/LibUnicode/GenerateUnicodeLocale.cpp
index 0304eb9890..f40df36282 100644
--- a/Meta/Lagom/Tools/CodeGenerators/LibUnicode/GenerateUnicodeLocale.cpp
+++ b/Meta/Lagom/Tools/CodeGenerators/LibUnicode/GenerateUnicodeLocale.cpp
@@ -24,6 +24,9 @@
using StringIndexType = u16;
constexpr auto s_string_index_type = "u16"sv;
+using DisplayPatternIndexType = u8;
+constexpr auto s_display_pattern_index_type = "u8"sv;
+
using LanguageListIndexType = u8;
constexpr auto s_language_list_index_type = "u8"sv;
@@ -62,6 +65,38 @@ static String format_identifier(StringView owner, String identifier)
return identifier;
}
+struct DisplayPattern {
+ unsigned hash() const
+ {
+ return pair_int_hash(locale_pattern, locale_separator);
+ }
+
+ bool operator==(DisplayPattern const& other) const
+ {
+ return (locale_pattern == other.locale_pattern)
+ && (locale_separator == other.locale_separator);
+ }
+
+ StringIndexType locale_pattern { 0 };
+ StringIndexType locale_separator { 0 };
+};
+
+template<>
+struct AK::Formatter<DisplayPattern> : Formatter<FormatString> {
+ ErrorOr<void> format(FormatBuilder& builder, DisplayPattern const& patterns)
+ {
+ return Formatter<FormatString>::format(builder,
+ "{{ {}, {} }}",
+ patterns.locale_pattern,
+ patterns.locale_separator);
+ }
+};
+
+template<>
+struct AK::Traits<DisplayPattern> : public GenericTraits<DisplayPattern> {
+ static unsigned hash(DisplayPattern const& p) { return p.hash(); }
+};
+
struct ListPatterns {
unsigned hash() const
{
@@ -124,6 +159,7 @@ struct Locale {
String language;
Optional<String> territory;
Optional<String> variant;
+ DisplayPatternIndexType display_patterns { 0 };
LanguageListIndexType languages { 0 };
TerritoryListIndexType territories { 0 };
ScriptListIndexType scripts { 0 };
@@ -146,6 +182,7 @@ struct LanguageMapping {
struct UnicodeLocaleData {
UniqueStringStorage<StringIndexType> unique_strings;
+ UniqueStorage<DisplayPattern, DisplayPatternIndexType> unique_display_patterns;
UniqueStorage<LanguageList, LanguageListIndexType> unique_language_lists;
UniqueStorage<TerritoryList, TerritoryListIndexType> unique_territory_lists;
UniqueStorage<ScriptList, ScriptListIndexType> unique_script_lists;
@@ -306,6 +343,29 @@ static ErrorOr<void> parse_identity(String locale_path, UnicodeLocaleData& local
return {};
}
+static ErrorOr<void> parse_locale_display_patterns(String locale_path, UnicodeLocaleData& locale_data, Locale& locale)
+{
+ LexicalPath locale_display_names_path(move(locale_path));
+ locale_display_names_path = locale_display_names_path.append("localeDisplayNames.json"sv);
+
+ auto locale_display_names_file = TRY(Core::File::open(locale_display_names_path.string(), Core::OpenMode::ReadOnly));
+ auto locale_display_names = TRY(JsonValue::from_string(locale_display_names_file->read_all()));
+
+ auto const& main_object = locale_display_names.as_object().get("main"sv);
+ auto const& locale_object = main_object.as_object().get(locale_display_names_path.parent().basename());
+ auto const& locale_display_names_object = locale_object.as_object().get("localeDisplayNames"sv);
+ auto const& locale_display_patterns_object = locale_display_names_object.as_object().get("localeDisplayPattern"sv);
+ auto const& locale_pattern = locale_display_patterns_object.as_object().get("localePattern"sv);
+ auto const& locale_separator = locale_display_patterns_object.as_object().get("localeSeparator"sv);
+
+ DisplayPattern patterns {};
+ patterns.locale_pattern = locale_data.unique_strings.ensure(locale_pattern.as_string());
+ patterns.locale_separator = locale_data.unique_strings.ensure(locale_separator.as_string());
+
+ locale.display_patterns = locale_data.unique_display_patterns.ensure(move(patterns));
+ return {};
+}
+
static ErrorOr<void> parse_locale_languages(String locale_path, UnicodeLocaleData& locale_data, Locale& locale)
{
LexicalPath languages_path(move(locale_path));
@@ -793,6 +853,7 @@ static ErrorOr<void> parse_all_locales(String core_path, String locale_names_pat
auto language = TRY(remove_variants_from_path(locale_path));
auto& locale = locale_data.locales.ensure(language);
+ TRY(parse_locale_display_patterns(locale_path, locale_data, locale));
TRY(parse_locale_languages(locale_path, locale_data, locale));
TRY(parse_locale_territories(locale_path, locale_data, locale));
TRY(parse_locale_scripts(locale_path, locale_data, locale));
@@ -893,6 +954,24 @@ static void generate_unicode_locale_implementation(Core::File& file, UnicodeLoca
#include <LibUnicode/UnicodeLocale.h>
namespace Unicode {
+)~~~");
+
+ locale_data.unique_strings.generate(generator);
+
+ generator.append(R"~~~(
+struct DisplayPatternImpl {
+ DisplayPattern to_display_pattern() const
+ {
+ DisplayPattern display_patterns {};
+ display_patterns.locale_pattern = s_string_list[locale_pattern];
+ display_patterns.locale_separator = s_string_list[locale_separator];
+
+ return display_patterns;
+ }
+
+ @string_index_type@ locale_pattern { 0 };
+ @string_index_type@ locale_separator { 0 };
+};
struct Patterns {
ListPatternType type;
@@ -904,7 +983,7 @@ struct Patterns {
};
)~~~");
- locale_data.unique_strings.generate(generator);
+ locale_data.unique_display_patterns.generate(generator, "DisplayPatternImpl"sv, "s_display_patterns"sv, 30);
locale_data.unique_language_lists.generate(generator, s_string_index_type, "s_language_lists"sv);
locale_data.unique_territory_lists.generate(generator, s_string_index_type, "s_territory_lists"sv);
locale_data.unique_script_lists.generate(generator, s_string_index_type, "s_script_lists"sv);
@@ -959,6 +1038,7 @@ static constexpr Array<@type@, @size@> @name@ { {)~~~");
auto locales = locale_data.locales.keys();
quick_sort(locales);
+ append_mapping(locales, locale_data.locales, s_display_pattern_index_type, "s_locale_display_patterns"sv, [&](auto const& locale) { return locale.display_patterns; });
append_mapping(locales, locale_data.locales, s_language_list_index_type, "s_languages"sv, [&](auto const& locale) { return locale.languages; });
append_mapping(locales, locale_data.locales, s_territory_list_index_type, "s_territories"sv, [&](auto const& locale) { return locale.territories; });
append_mapping(locales, locale_data.locales, s_script_list_index_type, "s_scripts"sv, [&](auto const& locale) { return locale.scripts; });
@@ -1251,6 +1331,19 @@ Optional<StringView> get_locale_@enum_snake@_mapping(StringView locale, StringVi
append_from_string("ListPatternStyle"sv, "list_pattern_style"sv, locale_data.list_pattern_styles);
generator.append(R"~~~(
+Optional<DisplayPattern> get_locale_display_patterns(StringView locale)
+{
+ auto locale_value = locale_from_string(locale);
+ if (!locale_value.has_value())
+ return {};
+
+ auto locale_index = to_underlying(*locale_value) - 1; // Subtract 1 because 0 == Locale::None.
+ auto display_patterns_index = s_locale_display_patterns.at(locale_index);
+
+ auto const& display_patterns = s_display_patterns.at(display_patterns_index);
+ return display_patterns.to_display_pattern();
+}
+
Optional<ListPatterns> get_locale_list_patterns(StringView locale, StringView list_pattern_type, StringView list_pattern_style)
{
auto locale_value = locale_from_string(locale);