diff --git a/shell/platform/linux/fl_engine.cc b/shell/platform/linux/fl_engine.cc index fe399749cfc20..13e5c22088d7c 100644 --- a/shell/platform/linux/fl_engine.cc +++ b/shell/platform/linux/fl_engine.cc @@ -55,6 +55,75 @@ typedef struct { FlutterTask task; } FlutterSource; +// Parse a locale into its components. +static void parse_locale(const gchar* locale, + gchar** language, + gchar** territory, + gchar** codeset, + gchar** modifier) { + gchar* l = g_strdup(locale); + + // Locales are in the form "language[_territory][.codeset][@modifier]" + gchar* match = strrchr(l, '@'); + if (match != nullptr) { + *modifier = g_strdup(match + 1); + *match = '\0'; + } else { + *modifier = nullptr; + } + + match = strrchr(l, '.'); + if (match != nullptr) { + *codeset = g_strdup(match + 1); + *match = '\0'; + } else { + *codeset = nullptr; + } + + match = strrchr(l, '_'); + if (match != nullptr) { + *territory = g_strdup(match + 1); + *match = '\0'; + } else { + *territory = nullptr; + } + + *language = l; +} + +// Passes locale information to the Flutter engine. +static void setup_locales(FlEngine* self) { + const gchar* const* languages = g_get_language_names(); + g_autoptr(GPtrArray) locales = g_ptr_array_new_with_free_func(g_free); + // Helper array to take ownership of the strings passed to Flutter. + g_autoptr(GPtrArray) locale_strings = g_ptr_array_new_with_free_func(g_free); + for (int i = 0; languages[i] != nullptr; i++) { + gchar *language, *territory, *codeset, *modifier; + parse_locale(languages[i], &language, &territory, &codeset, &modifier); + if (language != nullptr) + g_ptr_array_add(locale_strings, language); + if (territory != nullptr) + g_ptr_array_add(locale_strings, territory); + if (codeset != nullptr) + g_ptr_array_add(locale_strings, codeset); + if (modifier != nullptr) + g_ptr_array_add(locale_strings, modifier); + + FlutterLocale* locale = + static_cast(g_malloc0(sizeof(FlutterLocale))); + g_ptr_array_add(locales, locale); + locale->struct_size = sizeof(FlutterLocale); + locale->language_code = language; + locale->country_code = territory; + locale->script_code = codeset; + locale->variant_code = modifier; + } + FlutterEngineResult result = FlutterEngineUpdateLocales( + self->engine, (const FlutterLocale**)locales->pdata, locales->len); + if (result != kSuccess) + g_warning("Failed to set up Flutter locales"); +} + // Callback to run a Flutter task in the GLib main loop. static gboolean flutter_source_dispatch(GSource* source, GSourceFunc callback, @@ -323,6 +392,8 @@ gboolean fl_engine_start(FlEngine* self, GError** error) { return FALSE; } + setup_locales(self); + return TRUE; } diff --git a/shell/platform/linux/testing/mock_engine.cc b/shell/platform/linux/testing/mock_engine.cc index 8759553765dca..f82394bdd4ca3 100644 --- a/shell/platform/linux/testing/mock_engine.cc +++ b/shell/platform/linux/testing/mock_engine.cc @@ -382,3 +382,10 @@ FlutterEngineResult FlutterEngineRunTask(FLUTTER_API_SYMBOL(FlutterEngine) bool FlutterEngineRunsAOTCompiledDartCode() { return false; } + +FlutterEngineResult FlutterEngineUpdateLocales(FLUTTER_API_SYMBOL(FlutterEngine) + engine, + const FlutterLocale** locales, + size_t locales_count) { + return kSuccess; +}