This repository was archived by the owner on Feb 25, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 6k
Send locale information in the Windows embedding #20455
Merged
stuartmorgan-g
merged 3 commits into
flutter-team-archive:master
from
stuartmorgan-g:windows-locale
Aug 17, 2020
Merged
Changes from 2 commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,93 @@ | ||
| // Copyright 2013 The Flutter Authors. All rights reserved. | ||
| // Use of this source code is governed by a BSD-style license that can be | ||
| // found in the LICENSE file. | ||
|
|
||
| #include "flutter/shell/platform/windows/system_utils.h" | ||
|
|
||
| #include <Windows.h> | ||
|
|
||
| #include <sstream> | ||
|
|
||
| #include "flutter/shell/platform/windows/string_conversion.h" | ||
|
|
||
| namespace flutter { | ||
|
|
||
| std::vector<LanguageInfo> GetPreferredLanguageInfo() { | ||
| std::vector<std::wstring> languages = GetPreferredLanguages(); | ||
| std::vector<LanguageInfo> language_info; | ||
| language_info.reserve(languages.size()); | ||
|
|
||
| for (auto language : languages) { | ||
| language_info.push_back(ParseLanguageName(language)); | ||
| } | ||
| return language_info; | ||
| } | ||
|
|
||
| std::vector<std::wstring> GetPreferredLanguages() { | ||
| std::vector<std::wstring> languages; | ||
| DWORD flags = MUI_LANGUAGE_NAME | MUI_UI_FALLBACK; | ||
|
|
||
| // Get buffer length. | ||
| ULONG count = 0; | ||
| ULONG buffer_size = 0; | ||
| if (!::GetThreadPreferredUILanguages(flags, &count, nullptr, &buffer_size)) { | ||
| return languages; | ||
| } | ||
|
|
||
| // Get the list of null-separated languages. | ||
| std::wstring buffer(buffer_size, '\0'); | ||
| if (!::GetThreadPreferredUILanguages(flags, &count, buffer.data(), | ||
| &buffer_size)) { | ||
| return languages; | ||
| } | ||
|
|
||
| // Extract the individual languages from the buffer. | ||
| size_t start = 0; | ||
| while (true) { | ||
| // The buffer is terminated by an empty string (i.e., a double null). | ||
| if (buffer[start] == L'\0') { | ||
| break; | ||
| } | ||
| // Read the next null-terminated language. | ||
| std::wstring language(buffer.c_str() + start); | ||
| if (language.size() == 0) { | ||
| break; | ||
| } | ||
| languages.push_back(language); | ||
| // Skip past that language and its terminating null in the buffer. | ||
| start += language.size() + 1; | ||
| } | ||
| return languages; | ||
| } | ||
|
|
||
| LanguageInfo ParseLanguageName(std::wstring language_name) { | ||
| LanguageInfo info; | ||
|
|
||
| // Split by '-', discarding any suplemental language info (-x-foo). | ||
| std::vector<std::string> components; | ||
| std::istringstream stream(Utf8FromUtf16(language_name)); | ||
| std::string component; | ||
| while (getline(stream, component, '-')) { | ||
| if (component == "x") { | ||
| break; | ||
| } | ||
| components.push_back(component); | ||
| } | ||
|
|
||
| // Determine which components are which. | ||
| info.language = components[0]; | ||
| if (components.size() == 3) { | ||
| info.script = components[1]; | ||
| info.region = components[2]; | ||
| } else if (components.size() == 2) { | ||
| // A script code will always be four characters long. | ||
| if (components[1].size() == 4) { | ||
| info.script = components[1]; | ||
| } else { | ||
| info.region = components[1]; | ||
| } | ||
| } | ||
| return info; | ||
| } | ||
|
|
||
| } // namespace flutter | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| // Copyright 2013 The Flutter Authors. All rights reserved. | ||
| // Use of this source code is governed by a BSD-style license that can be | ||
| // found in the LICENSE file. | ||
|
|
||
| // This file contains utilities for system-level information/settings. | ||
|
|
||
| #ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_SYSTEM_UTILS_H_ | ||
| #define FLUTTER_SHELL_PLATFORM_WINDOWS_SYSTEM_UTILS_H_ | ||
|
|
||
| #include <string> | ||
| #include <vector> | ||
|
|
||
| namespace flutter { | ||
|
|
||
| // Components of a system language/locale. | ||
| struct LanguageInfo { | ||
| std::string language; | ||
| std::string region; | ||
| std::string script; | ||
| }; | ||
|
|
||
| // Returns the list of user-preferred languages, in preference order, | ||
| // parsed into LanguageInfo structures. | ||
| std::vector<LanguageInfo> GetPreferredLanguageInfo(); | ||
|
|
||
| // Returns the list of user-preferred languages, in preference order. | ||
| // The language names are as described at: | ||
| // https://docs.microsoft.com/en-us/windows/win32/intl/language-names | ||
| std::vector<std::wstring> GetPreferredLanguages(); | ||
|
|
||
| // Parses a Windows language name into its components. | ||
| LanguageInfo ParseLanguageName(std::wstring language_name); | ||
|
|
||
| } // namespace flutter | ||
|
|
||
| #endif // FLUTTER_SHELL_PLATFORM_WINDOWS_SYSTEM_UTILS_H_ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,75 @@ | ||
| // Copyright 2013 The Flutter Authors. All rights reserved. | ||
| // Use of this source code is governed by a BSD-style license that can be | ||
| // found in the LICENSE file. | ||
|
|
||
| #include <wchar.h> | ||
|
|
||
| #include "flutter/shell/platform/windows/system_utils.h" | ||
| #include "gtest/gtest.h" | ||
|
|
||
| namespace flutter { | ||
| namespace testing { | ||
|
|
||
| TEST(SystemUtils, GetPreferredLanguageInfo) { | ||
| std::vector<LanguageInfo> languages = GetPreferredLanguageInfo(); | ||
| // There should be at least one language. | ||
| ASSERT_GE(languages.size(), 1); | ||
| // The info should have a valid languge. | ||
| EXPECT_GE(languages[0].language.size(), 2); | ||
| } | ||
|
|
||
| TEST(SystemUtils, GetPreferredLanguages) { | ||
| std::vector<std::wstring> languages = GetPreferredLanguages(); | ||
| // There should be at least one language. | ||
| ASSERT_GE(languages.size(), 1); | ||
| // The language should be non-empty. | ||
| EXPECT_FALSE(languages[0].empty()); | ||
| // There should not be a trailing null from the parsing step. | ||
| EXPECT_EQ(languages[0].size(), wcslen(languages[0].c_str())); | ||
| } | ||
|
|
||
| TEST(SystemUtils, ParseLanguageNameGeneric) { | ||
| LanguageInfo info = ParseLanguageName(L"en"); | ||
| EXPECT_EQ(info.language, "en"); | ||
| EXPECT_TRUE(info.region.empty()); | ||
| EXPECT_TRUE(info.script.empty()); | ||
| } | ||
|
|
||
| TEST(SystemUtils, ParseLanguageNameWithRegion) { | ||
| LanguageInfo info = ParseLanguageName(L"hu-HU"); | ||
| EXPECT_EQ(info.language, "hu"); | ||
| EXPECT_EQ(info.region, "HU"); | ||
| EXPECT_TRUE(info.script.empty()); | ||
| } | ||
|
|
||
| TEST(SystemUtils, ParseLanguageNameWithScript) { | ||
| LanguageInfo info = ParseLanguageName(L"us-Latn"); | ||
| EXPECT_EQ(info.language, "us"); | ||
| EXPECT_TRUE(info.region.empty()); | ||
| EXPECT_EQ(info.script, "Latn"); | ||
| } | ||
|
|
||
| TEST(SystemUtils, ParseLanguageNameWithRegionAndScript) { | ||
| LanguageInfo info = ParseLanguageName(L"uz-Latn-UZ"); | ||
| EXPECT_EQ(info.language, "uz"); | ||
| EXPECT_EQ(info.region, "UZ"); | ||
| EXPECT_EQ(info.script, "Latn"); | ||
| } | ||
|
|
||
| TEST(SystemUtils, ParseLanguageNameWithSuplementalLanguage) { | ||
| LanguageInfo info = ParseLanguageName(L"en-US-x-fabricam"); | ||
| EXPECT_EQ(info.language, "en"); | ||
| EXPECT_EQ(info.region, "US"); | ||
| EXPECT_TRUE(info.script.empty()); | ||
| } | ||
|
|
||
| // Ensure that ISO 639-2/T codes are handled. | ||
| TEST(SystemUtils, ParseLanguageNameWithThreeCharacterLanguage) { | ||
| LanguageInfo info = ParseLanguageName(L"ale-ZZ"); | ||
| EXPECT_EQ(info.language, "ale"); | ||
| EXPECT_EQ(info.region, "ZZ"); | ||
| EXPECT_TRUE(info.script.empty()); | ||
| } | ||
|
|
||
| } // namespace testing | ||
| } // namespace flutter |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.