diff --git a/shell/platform/linux/fl_engine.cc b/shell/platform/linux/fl_engine.cc index 896eef701fc8e..a15e81672881f 100644 --- a/shell/platform/linux/fl_engine.cc +++ b/shell/platform/linux/fl_engine.cc @@ -86,29 +86,37 @@ static void parse_locale(const gchar* locale, // Locales are in the form "language[_territory][.codeset][@modifier]" gchar* match = strrchr(l, '@'); if (match != nullptr) { - *modifier = g_strdup(match + 1); + if (modifier != nullptr) { + *modifier = g_strdup(match + 1); + } *match = '\0'; - } else { + } else if (modifier != nullptr) { *modifier = nullptr; } match = strrchr(l, '.'); if (match != nullptr) { - *codeset = g_strdup(match + 1); + if (codeset != nullptr) { + *codeset = g_strdup(match + 1); + } *match = '\0'; - } else { + } else if (codeset != nullptr) { *codeset = nullptr; } match = strrchr(l, '_'); if (match != nullptr) { - *territory = g_strdup(match + 1); + if (territory != nullptr) { + *territory = g_strdup(match + 1); + } *match = '\0'; - } else { + } else if (territory != nullptr) { *territory = nullptr; } - *language = l; + if (language != nullptr) { + *language = l; + } } // Passes locale information to the Flutter engine. @@ -118,20 +126,14 @@ static void setup_locales(FlEngine* self) { // 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); + gchar *language, *territory; + parse_locale(languages[i], &language, &territory, nullptr, nullptr); 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))); @@ -139,8 +141,8 @@ static void setup_locales(FlEngine* self) { locale->struct_size = sizeof(FlutterLocale); locale->language_code = language; locale->country_code = territory; - locale->script_code = codeset; - locale->variant_code = modifier; + locale->script_code = nullptr; + locale->variant_code = nullptr; } FlutterLocale** locales = reinterpret_cast(locales_array->pdata); diff --git a/shell/platform/linux/fl_engine_test.cc b/shell/platform/linux/fl_engine_test.cc index 6bbc699195d5e..727f76d61a902 100644 --- a/shell/platform/linux/fl_engine_test.cc +++ b/shell/platform/linux/fl_engine_test.cc @@ -359,4 +359,57 @@ TEST(FlEngineTest, DartEntrypointArgs) { EXPECT_TRUE(called); } +TEST(FlEngineTest, Locales) { + gchar* initial_language = g_strdup(g_getenv("LANGUAGE")); + g_setenv("LANGUAGE", "de:en_US", TRUE); + g_autoptr(FlDartProject) project = fl_dart_project_new(); + + g_autoptr(FlEngine) engine = make_mock_engine_with_project(project); + FlutterEngineProcTable* embedder_api = fl_engine_get_embedder_api(engine); + + bool called = false; + embedder_api->UpdateLocales = MOCK_ENGINE_PROC( + UpdateLocales, ([&called](auto engine, const FlutterLocale** locales, + size_t locales_count) { + called = true; + + EXPECT_EQ(locales_count, static_cast(4)); + + EXPECT_STREQ(locales[0]->language_code, "de"); + EXPECT_STREQ(locales[0]->country_code, nullptr); + EXPECT_STREQ(locales[0]->script_code, nullptr); + EXPECT_STREQ(locales[0]->variant_code, nullptr); + + EXPECT_STREQ(locales[1]->language_code, "en"); + EXPECT_STREQ(locales[1]->country_code, "US"); + EXPECT_STREQ(locales[1]->script_code, nullptr); + EXPECT_STREQ(locales[1]->variant_code, nullptr); + + EXPECT_STREQ(locales[2]->language_code, "en"); + EXPECT_STREQ(locales[2]->country_code, nullptr); + EXPECT_STREQ(locales[2]->script_code, nullptr); + EXPECT_STREQ(locales[2]->variant_code, nullptr); + + EXPECT_STREQ(locales[3]->language_code, "C"); + EXPECT_STREQ(locales[3]->country_code, nullptr); + EXPECT_STREQ(locales[3]->script_code, nullptr); + EXPECT_STREQ(locales[3]->variant_code, nullptr); + + return kSuccess; + })); + + g_autoptr(GError) error = nullptr; + EXPECT_TRUE(fl_engine_start(engine, &error)); + EXPECT_EQ(error, nullptr); + + EXPECT_TRUE(called); + + if (initial_language) { + g_setenv("LANGUAGE", initial_language, TRUE); + } else { + g_unsetenv("LANGUAGE"); + } + g_free(initial_language); +} + // NOLINTEND(clang-analyzer-core.StackAddressEscape)