Commit e127c423 authored by Scott Little's avatar Scott Little Committed by Commit Bot

Clean up locale_utils to use base::StringPiece.

This cleanup CL changes no functionality, it just cleans up some
functions in components/language/core/common/locale_util.cc to use
base::StringPiece instead of std::string where needed, as well as
updating the callers of these methods accordingly.

This CL also moves language::ContainsSameBaseLanguage into an
anonymous namespace in the single file that it's called from.

Change-Id: Ia2f8be1361b976e96aba95d78c59b88697343729
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2316811
Auto-Submit: Scott Little <sclittle@chromium.org>
Commit-Queue: anthonyvd <anthonyvd@chromium.org>
Reviewed-by: default avataranthonyvd <anthonyvd@chromium.org>
Reviewed-by: default avatarMegan Jablonski <megjablon@chromium.org>
Cr-Commit-Position: refs/heads/master@{#792838}
parent 1d41ef06
...@@ -6,12 +6,16 @@ ...@@ -6,12 +6,16 @@
#include <stddef.h> #include <stddef.h>
#include <algorithm> #include <algorithm>
#include <tuple>
#include "base/stl_util.h" #include "base/strings/strcat.h"
#include "base/strings/string_piece.h"
#include "components/language/core/common/locale_util.h" #include "components/language/core/common/locale_util.h"
namespace language { namespace language {
namespace {
struct LanguageCodePair { struct LanguageCodePair {
// Code used in supporting list of Translate. // Code used in supporting list of Translate.
const char* const translate_language; const char* const translate_language;
...@@ -54,17 +58,17 @@ const LanguageCodePair kLanguageCodeChineseCompatiblePairs[] = { ...@@ -54,17 +58,17 @@ const LanguageCodePair kLanguageCodeChineseCompatiblePairs[] = {
{"zh-CN", "zh-SG"}, {"zh-CN", "zh-SG"},
}; };
} // namespace
void ToTranslateLanguageSynonym(std::string* language) { void ToTranslateLanguageSynonym(std::string* language) {
for (size_t i = 0; i < base::size(kChromeToTranslateLanguageMap); ++i) { for (const auto& language_pair : kChromeToTranslateLanguageMap) {
if (*language == kChromeToTranslateLanguageMap[i].chrome_language) { if (*language == language_pair.chrome_language) {
*language = *language = language_pair.translate_language;
std::string(kChromeToTranslateLanguageMap[i].translate_language);
return; return;
} }
} }
std::string main_part, tail_part; base::StringPiece main_part = language::SplitIntoMainAndTail(*language).first;
language::SplitIntoMainAndTail(*language, &main_part, &tail_part);
if (main_part.empty()) if (main_part.empty())
return; return;
...@@ -75,9 +79,9 @@ void ToTranslateLanguageSynonym(std::string* language) { ...@@ -75,9 +79,9 @@ void ToTranslateLanguageSynonym(std::string* language) {
// instead of the main_part. // instead of the main_part.
// Note that "zh" does not have any mapping and as such we leave it as is. See // Note that "zh" does not have any mapping and as such we leave it as is. See
// https://crbug/798512 for more info. // https://crbug/798512 for more info.
for (size_t i = 0; i < base::size(kLanguageCodeChineseCompatiblePairs); ++i) { for (const auto& language_pair : kLanguageCodeChineseCompatiblePairs) {
if (*language == kLanguageCodeChineseCompatiblePairs[i].chrome_language) { if (*language == language_pair.chrome_language) {
*language = kLanguageCodeChineseCompatiblePairs[i].translate_language; *language = language_pair.translate_language;
return; return;
} }
} }
...@@ -86,37 +90,38 @@ void ToTranslateLanguageSynonym(std::string* language) { ...@@ -86,37 +90,38 @@ void ToTranslateLanguageSynonym(std::string* language) {
} }
// Apply linear search here because number of items in the list is just four. // Apply linear search here because number of items in the list is just four.
for (size_t i = 0; i < base::size(kLanguageCodeSynonyms); ++i) { for (const auto& language_pair : kLanguageCodeSynonyms) {
if (main_part == kLanguageCodeSynonyms[i].chrome_language) { if (main_part == language_pair.chrome_language) {
main_part = std::string(kLanguageCodeSynonyms[i].translate_language); main_part = language_pair.translate_language;
break; break;
} }
} }
*language = main_part; *language = std::string(main_part);
} }
void ToChromeLanguageSynonym(std::string* language) { void ToChromeLanguageSynonym(std::string* language) {
for (size_t i = 0; i < base::size(kTranslateToChromeLanguageMap); ++i) { for (const auto& language_pair : kTranslateToChromeLanguageMap) {
if (*language == kTranslateToChromeLanguageMap[i].translate_language) { if (*language == language_pair.translate_language) {
*language = std::string(kTranslateToChromeLanguageMap[i].chrome_language); *language = language_pair.chrome_language;
return; return;
} }
} }
std::string main_part, tail_part; base::StringPiece main_part, tail_part;
language::SplitIntoMainAndTail(*language, &main_part, &tail_part); std::tie(main_part, tail_part) = language::SplitIntoMainAndTail(*language);
if (main_part.empty()) if (main_part.empty())
return; return;
// Apply liner search here because number of items in the list is just four. // Apply linear search here because number of items in the list is just four.
for (size_t i = 0; i < base::size(kLanguageCodeSynonyms); ++i) { for (const auto& language_pair : kLanguageCodeSynonyms) {
if (main_part == kLanguageCodeSynonyms[i].translate_language) { if (main_part == language_pair.translate_language) {
main_part = std::string(kLanguageCodeSynonyms[i].chrome_language); main_part = language_pair.chrome_language;
break; break;
} }
} }
*language = main_part + tail_part; *language = base::StrCat({main_part, tail_part});
} }
} // namespace language } // namespace language
...@@ -4,13 +4,10 @@ ...@@ -4,13 +4,10 @@
#include "components/language/core/common/locale_util.h" #include "components/language/core/common/locale_util.h"
#include <stddef.h>
#include <algorithm> #include <algorithm>
#include <set>
#include <vector>
#include "base/command_line.h"
#include "base/macros.h"
#include "base/strings/string_split.h"
#include "ui/base/l10n/l10n_util.h" #include "ui/base/l10n/l10n_util.h"
namespace language { namespace language {
...@@ -52,87 +49,61 @@ const LocaleUIFallbackPair kLocaleUIFallbackTable[] = { ...@@ -52,87 +49,61 @@ const LocaleUIFallbackPair kLocaleUIFallbackTable[] = {
// clang-format on // clang-format on
}; };
bool LocaleCompare(const LocaleUIFallbackPair& p1, const std::string& p2) { base::StringPiece GetUIFallbackLocale(base::StringPiece input) {
return p1.chosen_locale < p2; const auto* it = std::lower_bound(
} std::begin(kLocaleUIFallbackTable), std::end(kLocaleUIFallbackTable),
input, [](const LocaleUIFallbackPair& p1, base::StringPiece p2) {
bool GetUIFallbackLocale(const std::string& input, std::string* const output) { return p1.chosen_locale < p2;
*output = input; });
const auto* it = if (it != std::end(kLocaleUIFallbackTable) && it->chosen_locale == input)
std::lower_bound(std::begin(kLocaleUIFallbackTable), return it->fallback_locale;
std::end(kLocaleUIFallbackTable), input, LocaleCompare); return input;
if (it != std::end(kLocaleUIFallbackTable) && it->chosen_locale == input) {
*output = it->fallback_locale;
return true;
}
return false;
} }
// Checks if |locale| is one of the actual locales supported as a UI languages. // Checks if |locale| is one of the actual locales supported as a UI languages.
bool IsAvailableUILocale(const std::string& locale) { bool IsAvailableUILocale(base::StringPiece locale) {
const std::vector<std::string>& ui_locales = l10n_util::GetAvailableLocales(); for (const auto& ui_locale : l10n_util::GetAvailableLocales()) {
return std::find(ui_locales.begin(), ui_locales.end(), locale) != if (ui_locale == locale)
ui_locales.end();
}
} // namespace
void SplitIntoMainAndTail(const std::string& locale,
std::string* main_part,
std::string* tail_part) {
DCHECK(main_part);
DCHECK(tail_part);
std::vector<base::StringPiece> chunks = base::SplitStringPiece(
locale, "-", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
if (chunks.empty())
return;
main_part->assign(chunks[0].data(), chunks[0].size());
*tail_part = locale.substr(main_part->size());
}
std::string ExtractBaseLanguage(const std::string& language_code) {
std::string base;
std::string tail;
SplitIntoMainAndTail(language_code, &base, &tail);
return base;
}
bool ContainsSameBaseLanguage(const std::vector<std::string>& list,
const std::string& language_code) {
const std::string base_language = ExtractBaseLanguage(language_code);
for (const auto& item : list) {
const std::string compare_base = ExtractBaseLanguage(item);
if (compare_base == base_language)
return true; return true;
} }
return false; return false;
} }
bool ConvertToFallbackUILocale(std::string* input_locale) { bool ConvertToFallbackUILocale(std::string* input_locale) {
// 1) Convert input to a fallback, if available. // 1) Convert input to a fallback, if available.
std::string fallback; base::StringPiece fallback = GetUIFallbackLocale(*input_locale);
GetUIFallbackLocale(*input_locale, &fallback);
// 2) Check if input is part of the UI languages. // 2) Check if input is part of the UI languages.
if (IsAvailableUILocale(fallback)) { if (IsAvailableUILocale(fallback)) {
*input_locale = fallback; *input_locale = std::string(fallback);
return true; return true;
} }
return false; return false;
} }
} // namespace
std::pair<base::StringPiece, base::StringPiece> SplitIntoMainAndTail(
base::StringPiece locale) {
size_t hyphen_pos = static_cast<size_t>(
std::find(locale.begin(), locale.end(), '-') - locale.begin());
return std::make_pair(locale.substr(0U, hyphen_pos),
locale.substr(hyphen_pos));
}
base::StringPiece ExtractBaseLanguage(base::StringPiece language_code) {
return SplitIntoMainAndTail(language_code).first;
}
bool ConvertToActualUILocale(std::string* input_locale) { bool ConvertToActualUILocale(std::string* input_locale) {
if (ConvertToFallbackUILocale(input_locale)) if (ConvertToFallbackUILocale(input_locale))
return true; return true;
// Check if the base language of the input is part of the UI languages. // Check if the base language of the input is part of the UI languages.
const std::string base = ExtractBaseLanguage(*input_locale); base::StringPiece base = ExtractBaseLanguage(*input_locale);
if (base != *input_locale && IsAvailableUILocale(base)) { if (base != *input_locale && IsAvailableUILocale(base)) {
*input_locale = base; *input_locale = std::string(base);
return true; return true;
} }
......
...@@ -6,29 +6,20 @@ ...@@ -6,29 +6,20 @@
#define COMPONENTS_LANGUAGE_CORE_COMMON_LOCALE_UTIL_H_ #define COMPONENTS_LANGUAGE_CORE_COMMON_LOCALE_UTIL_H_
#include <string> #include <string>
#include <vector> #include <utility>
#include "base/strings/string_piece.h"
namespace language { namespace language {
// Split the |locale| into two parts. For example, if |locale| is 'en-US', // Split the |locale| into two parts. For example, if |locale| is 'en-US',
// this will be split into the main part 'en' and the tail part '-US'. // this will be split into the main part 'en' and the tail part '-US'.
void SplitIntoMainAndTail(const std::string& locale, std::pair<base::StringPiece, base::StringPiece> SplitIntoMainAndTail(
std::string* main_part, base::StringPiece locale);
std::string* tail_part);
// Given a language code, extract the base language only. // Given a language code, extract the base language only.
// Example: from "en-US", extract "en". // Example: from "en-US", extract "en".
std::string ExtractBaseLanguage(const std::string& language_code); base::StringPiece ExtractBaseLanguage(base::StringPiece language_code);
// Returns whether or not the given list includes at least one language with
// the same base as the input language.
// For example: "en-US" and "en-UK" share the same base "en".
bool ContainsSameBaseLanguage(const std::vector<std::string>& list,
const std::string& language_code);
// Converts |input_locale| to a fallback if needed and checks that the
// resulting locale is supported as a UI locale.
bool ConvertToFallbackUILocale(std::string* input_locale);
// Converts the input locale into its corresponding actual UI locale that // Converts the input locale into its corresponding actual UI locale that
// Chrome should use for display and returns whether such locale exist. // Chrome should use for display and returns whether such locale exist.
......
...@@ -8,90 +8,22 @@ ...@@ -8,90 +8,22 @@
#include "build/build_config.h" #include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
namespace language {
namespace {
typedef testing::Test LocaleUtilTest; typedef testing::Test LocaleUtilTest;
TEST_F(LocaleUtilTest, SplitIntoMainAndTail) { TEST_F(LocaleUtilTest, SplitIntoMainAndTail) {
std::string locale; typedef std::pair<base::StringPiece, base::StringPiece> StringPiecePair;
std::string main;
std::string tail; EXPECT_EQ(StringPiecePair("", ""), SplitIntoMainAndTail(""));
EXPECT_EQ(StringPiecePair("en", ""), SplitIntoMainAndTail("en"));
locale = ""; EXPECT_EQ(StringPiecePair("ogard543i", ""),
language::SplitIntoMainAndTail(locale, &main, &tail); SplitIntoMainAndTail("ogard543i"));
EXPECT_TRUE(main.empty()); EXPECT_EQ(StringPiecePair("en", "-AU"), SplitIntoMainAndTail("en-AU"));
EXPECT_TRUE(tail.empty()); EXPECT_EQ(StringPiecePair("es", "-419"), SplitIntoMainAndTail("es-419"));
EXPECT_EQ(StringPiecePair("en", "-AU-2009"),
locale = "en"; SplitIntoMainAndTail("en-AU-2009"));
main.clear();
tail.clear();
language::SplitIntoMainAndTail(locale, &main, &tail);
EXPECT_EQ("en", main);
EXPECT_TRUE(tail.empty());
locale = "ogard543i";
main.clear();
tail.clear();
language::SplitIntoMainAndTail(locale, &main, &tail);
EXPECT_EQ("ogard543i", main);
EXPECT_TRUE(tail.empty());
locale = "en-AU";
main.clear();
tail.clear();
language::SplitIntoMainAndTail(locale, &main, &tail);
EXPECT_EQ("en", main);
EXPECT_EQ("-AU", tail);
locale = "es-419";
main.clear();
tail.clear();
language::SplitIntoMainAndTail(locale, &main, &tail);
EXPECT_EQ("es", main);
EXPECT_EQ("-419", tail);
locale = "en-AU-2009";
main.clear();
tail.clear();
language::SplitIntoMainAndTail(locale, &main, &tail);
EXPECT_EQ("en", main);
EXPECT_EQ("-AU-2009", tail);
}
TEST_F(LocaleUtilTest, ContainsSameBaseLanguage) {
std::vector<std::string> list;
// Empty input.
EXPECT_EQ(false, language::ContainsSameBaseLanguage(list, ""));
// Empty list.
EXPECT_EQ(false, language::ContainsSameBaseLanguage(list, "fr-FR"));
// Empty language.
list = {"en-US"};
EXPECT_EQ(false, language::ContainsSameBaseLanguage(list, ""));
// One element, no match.
list = {"en-US"};
EXPECT_EQ(false, language::ContainsSameBaseLanguage(list, "fr-FR"));
// One element, with match.
list = {"fr-CA"};
EXPECT_EQ(true, language::ContainsSameBaseLanguage(list, "fr-FR"));
// Multiple elements, no match.
list = {"en-US", "es-AR", "en-GB"};
EXPECT_EQ(false, language::ContainsSameBaseLanguage(list, "fr-FR"));
// Multiple elements, with match.
list = {"en-US", "fr-CA", "es-AR"};
EXPECT_EQ(true, language::ContainsSameBaseLanguage(list, "fr-FR"));
// Multiple elements matching.
list = {"en-US", "fr-CA", "es-AR", "fr-FR"};
EXPECT_EQ(true, language::ContainsSameBaseLanguage(list, "fr-FR"));
// List includes base language.
list = {"en-US", "fr", "es-AR", "fr-FR"};
EXPECT_EQ(true, language::ContainsSameBaseLanguage(list, "fr-FR"));
} }
TEST_F(LocaleUtilTest, ConvertToActualUILocale) { TEST_F(LocaleUtilTest, ConvertToActualUILocale) {
...@@ -101,17 +33,17 @@ TEST_F(LocaleUtilTest, ConvertToActualUILocale) { ...@@ -101,17 +33,17 @@ TEST_F(LocaleUtilTest, ConvertToActualUILocale) {
// Languages that are enabled as display UI. // Languages that are enabled as display UI.
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
locale = "en-US"; locale = "en-US";
bool is_ui = language::ConvertToActualUILocale(&locale); bool is_ui = ConvertToActualUILocale(&locale);
EXPECT_TRUE(is_ui); EXPECT_TRUE(is_ui);
EXPECT_EQ("en-US", locale); EXPECT_EQ("en-US", locale);
locale = "it"; locale = "it";
is_ui = language::ConvertToActualUILocale(&locale); is_ui = ConvertToActualUILocale(&locale);
EXPECT_TRUE(is_ui); EXPECT_TRUE(is_ui);
EXPECT_EQ("it", locale); EXPECT_EQ("it", locale);
locale = "fr-FR"; locale = "fr-FR";
is_ui = language::ConvertToActualUILocale(&locale); is_ui = ConvertToActualUILocale(&locale);
EXPECT_TRUE(is_ui); EXPECT_TRUE(is_ui);
EXPECT_EQ("fr-FR", locale); EXPECT_EQ("fr-FR", locale);
...@@ -120,115 +52,51 @@ TEST_F(LocaleUtilTest, ConvertToActualUILocale) { ...@@ -120,115 +52,51 @@ TEST_F(LocaleUtilTest, ConvertToActualUILocale) {
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
// All Latin American Spanish languages fall back to "es-419". // All Latin American Spanish languages fall back to "es-419".
locale = "es-AR"; for (const char* es_locale : {"es-AR", "es-CL", "es-CO", "es-CR", "es-HN",
is_ui = language::ConvertToActualUILocale(&locale); "es-MX", "es-PE", "es-US", "es-UY", "es-VE"}) {
EXPECT_TRUE(is_ui); locale = es_locale;
EXPECT_EQ("es-419", locale); is_ui = ConvertToActualUILocale(&locale);
EXPECT_TRUE(is_ui) << es_locale;
locale = "es-CL"; EXPECT_EQ("es-419", locale) << es_locale;
is_ui = language::ConvertToActualUILocale(&locale); }
EXPECT_TRUE(is_ui);
EXPECT_EQ("es-419", locale);
locale = "es-CO";
is_ui = language::ConvertToActualUILocale(&locale);
EXPECT_TRUE(is_ui);
EXPECT_EQ("es-419", locale);
locale = "es-CR";
is_ui = language::ConvertToActualUILocale(&locale);
EXPECT_TRUE(is_ui);
EXPECT_EQ("es-419", locale);
locale = "es-HN";
is_ui = language::ConvertToActualUILocale(&locale);
EXPECT_TRUE(is_ui);
EXPECT_EQ("es-419", locale);
locale = "es-MX";
is_ui = language::ConvertToActualUILocale(&locale);
EXPECT_TRUE(is_ui);
EXPECT_EQ("es-419", locale);
locale = "es-PE";
is_ui = language::ConvertToActualUILocale(&locale);
EXPECT_TRUE(is_ui);
EXPECT_EQ("es-419", locale);
locale = "es-US";
is_ui = language::ConvertToActualUILocale(&locale);
EXPECT_TRUE(is_ui);
EXPECT_EQ("es-419", locale);
locale = "es-UY";
is_ui = language::ConvertToActualUILocale(&locale);
EXPECT_TRUE(is_ui);
EXPECT_EQ("es-419", locale);
locale = "es-VE";
is_ui = language::ConvertToActualUILocale(&locale);
EXPECT_TRUE(is_ui);
EXPECT_EQ("es-419", locale);
// English falls back to US. // English falls back to US.
locale = "en"; locale = "en";
is_ui = language::ConvertToActualUILocale(&locale); is_ui = ConvertToActualUILocale(&locale);
EXPECT_TRUE(is_ui); EXPECT_TRUE(is_ui);
EXPECT_EQ("en-US", locale); EXPECT_EQ("en-US", locale);
// All other regional English languages fall back to UK. // All other regional English languages fall back to UK.
locale = "en-AU"; for (const char* en_locale :
is_ui = language::ConvertToActualUILocale(&locale); {"en-AU", "en-CA", "en-GB-oxendict", "en-IN", "en-NZ", "en-ZA"}) {
EXPECT_TRUE(is_ui); locale = en_locale;
EXPECT_EQ("en-GB", locale); is_ui = ConvertToActualUILocale(&locale);
EXPECT_TRUE(is_ui) << en_locale;
locale = "en-CA"; EXPECT_EQ("en-GB", locale) << en_locale;
is_ui = language::ConvertToActualUILocale(&locale); }
EXPECT_TRUE(is_ui);
EXPECT_EQ("en-GB", locale);
locale = "en-GB-oxendict";
is_ui = language::ConvertToActualUILocale(&locale);
EXPECT_TRUE(is_ui);
EXPECT_EQ("en-GB", locale);
locale = "en-IN";
is_ui = language::ConvertToActualUILocale(&locale);
EXPECT_TRUE(is_ui);
EXPECT_EQ("en-GB", locale);
locale = "en-NZ";
is_ui = language::ConvertToActualUILocale(&locale);
EXPECT_TRUE(is_ui);
EXPECT_EQ("en-GB", locale);
locale = "en-ZA";
is_ui = language::ConvertToActualUILocale(&locale);
EXPECT_TRUE(is_ui);
EXPECT_EQ("en-GB", locale);
locale = "pt"; locale = "pt";
is_ui = language::ConvertToActualUILocale(&locale); is_ui = ConvertToActualUILocale(&locale);
EXPECT_TRUE(is_ui); EXPECT_TRUE(is_ui);
EXPECT_EQ("pt-PT", locale); EXPECT_EQ("pt-PT", locale);
locale = "it-CH"; locale = "it-CH";
is_ui = language::ConvertToActualUILocale(&locale); is_ui = ConvertToActualUILocale(&locale);
EXPECT_TRUE(is_ui); EXPECT_TRUE(is_ui);
EXPECT_EQ("it", locale); EXPECT_EQ("it", locale);
locale = "no"; locale = "no";
is_ui = language::ConvertToActualUILocale(&locale); is_ui = ConvertToActualUILocale(&locale);
EXPECT_TRUE(is_ui); EXPECT_TRUE(is_ui);
EXPECT_EQ("nb", locale); EXPECT_EQ("nb", locale);
locale = "it-IT"; locale = "it-IT";
is_ui = language::ConvertToActualUILocale(&locale); is_ui = ConvertToActualUILocale(&locale);
EXPECT_TRUE(is_ui); EXPECT_TRUE(is_ui);
EXPECT_EQ("it-IT", locale); EXPECT_EQ("it-IT", locale);
locale = "de-DE"; locale = "de-DE";
is_ui = language::ConvertToActualUILocale(&locale); is_ui = ConvertToActualUILocale(&locale);
EXPECT_TRUE(is_ui); EXPECT_TRUE(is_ui);
EXPECT_EQ("de-DE", locale); EXPECT_EQ("de-DE", locale);
...@@ -239,23 +107,26 @@ TEST_F(LocaleUtilTest, ConvertToActualUILocale) { ...@@ -239,23 +107,26 @@ TEST_F(LocaleUtilTest, ConvertToActualUILocale) {
// where users can set the display UI. // where users can set the display UI.
#if defined(OS_CHROMEOS) || defined(OS_WIN) #if defined(OS_CHROMEOS) || defined(OS_WIN)
locale = "sd"; // Sindhi locale = "sd"; // Sindhi
is_ui = language::ConvertToActualUILocale(&locale); is_ui = ConvertToActualUILocale(&locale);
EXPECT_FALSE(is_ui); EXPECT_FALSE(is_ui);
locale = "af"; // Afrikaans locale = "af"; // Afrikaans
is_ui = language::ConvertToActualUILocale(&locale); is_ui = ConvertToActualUILocale(&locale);
EXPECT_FALSE(is_ui); EXPECT_FALSE(is_ui);
locale = "ga"; // Irish locale = "ga"; // Irish
is_ui = language::ConvertToActualUILocale(&locale); is_ui = ConvertToActualUILocale(&locale);
EXPECT_FALSE(is_ui); EXPECT_FALSE(is_ui);
locale = "ky"; // Kyrgyz locale = "ky"; // Kyrgyz
is_ui = language::ConvertToActualUILocale(&locale); is_ui = ConvertToActualUILocale(&locale);
EXPECT_FALSE(is_ui); EXPECT_FALSE(is_ui);
locale = "zu"; // Zulu locale = "zu"; // Zulu
is_ui = language::ConvertToActualUILocale(&locale); is_ui = ConvertToActualUILocale(&locale);
EXPECT_FALSE(is_ui); EXPECT_FALSE(is_ui);
#endif #endif
} }
} // namespace
} // namespace language
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
#include <map> #include <map>
#include <memory> #include <memory>
#include <tuple>
#include <utility>
#include "base/bind.h" #include "base/bind.h"
#include "base/command_line.h" #include "base/command_line.h"
...@@ -13,6 +15,7 @@ ...@@ -13,6 +15,7 @@
#include "base/metrics/histogram.h" #include "base/metrics/histogram.h"
#include "base/stl_util.h" #include "base/stl_util.h"
#include "base/strings/string_number_conversions.h" #include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_split.h" #include "base/strings/string_split.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "base/time/time.h" #include "base/time/time.h"
...@@ -613,31 +616,33 @@ bool TranslateManager::ShouldSuppressBubbleUI( ...@@ -613,31 +616,33 @@ bool TranslateManager::ShouldSuppressBubbleUI(
void TranslateManager::AddTargetLanguageToAcceptLanguages( void TranslateManager::AddTargetLanguageToAcceptLanguages(
const std::string& target_language_code) { const std::string& target_language_code) {
std::string target_language, tail; auto prefs = translate_client_->GetTranslatePrefs();
std::vector<std::string> languages;
prefs->GetLanguageList(&languages);
base::StringPiece target_language, tail;
// |target_language_code| should satisfy BCP47 and consist of a language code // |target_language_code| should satisfy BCP47 and consist of a language code
// and an optional region code joined by an hyphen. // and an optional region code joined by an hyphen.
language::SplitIntoMainAndTail(target_language_code, &target_language, &tail); std::tie(target_language, tail) =
language::SplitIntoMainAndTail(target_language_code);
std::function<bool(const std::string&)> is_redundant; // Don't add the target language if it's redundant with another already in the
// list.
if (tail.empty()) { if (tail.empty()) {
is_redundant = [&target_language](const std::string& language) { for (const auto& language : languages) {
return language::ExtractBaseLanguage(language) == target_language; if (language::ExtractBaseLanguage(language) == target_language)
}; return;
}
} else { } else {
is_redundant = [&target_language_code](const std::string& language) { for (const auto& language : languages) {
return language == target_language_code; if (language == target_language_code)
}; return;
}
} }
auto prefs = translate_client_->GetTranslatePrefs(); // Only add the target language if it's not an automatic target (such as when
std::vector<std::string> languages; // translation happens because of an hrefTranslate navigation).
prefs->GetLanguageList(&languages); if (language_state_.AutoTranslateTo() != target_language_code &&
// Only add the target language if it's not redundant with another already in
// the list, and if it's not an automatic target (such as when translation
// happens because of an hrefTranslate navigation).
if (std::none_of(languages.begin(), languages.end(), is_redundant) &&
language_state_.AutoTranslateTo() != target_language_code &&
language_state_.href_translate() != target_language_code) { language_state_.href_translate() != target_language_code) {
prefs->AddToLanguageList(target_language_code, /*force_blocked=*/false); prefs->AddToLanguageList(target_language_code, /*force_blocked=*/false);
} }
......
...@@ -38,6 +38,24 @@ ...@@ -38,6 +38,24 @@
namespace translate { namespace translate {
namespace {
// Returns whether or not the given list includes at least one language with
// the same base as the input language.
// For example: "en-US" and "en-UK" share the same base "en".
bool ContainsSameBaseLanguage(const std::vector<std::string>& list,
base::StringPiece language_code) {
base::StringPiece base_language =
language::ExtractBaseLanguage(language_code);
for (const auto& item : list) {
if (base_language == language::ExtractBaseLanguage(item))
return true;
}
return false;
}
} // namespace
const char kForceTriggerTranslateCount[] = const char kForceTriggerTranslateCount[] =
"translate_force_trigger_on_english_count_for_backoff_1"; "translate_force_trigger_on_english_count_for_backoff_1";
const char TranslatePrefs::kPrefTranslateSiteBlacklistDeprecated[] = const char TranslatePrefs::kPrefTranslateSiteBlacklistDeprecated[] =
...@@ -222,7 +240,7 @@ void TranslatePrefs::AddToLanguageList(const std::string& input_language, ...@@ -222,7 +240,7 @@ void TranslatePrefs::AddToLanguageList(const std::string& input_language,
// We should block the language if the list does not already contain another // We should block the language if the list does not already contain another
// language with the same base language. // language with the same base language.
const bool should_block = const bool should_block =
!language::ContainsSameBaseLanguage(languages, chrome_language); !ContainsSameBaseLanguage(languages, chrome_language);
if (force_blocked || should_block) { if (force_blocked || should_block) {
BlockLanguage(input_language); BlockLanguage(input_language);
...@@ -260,7 +278,7 @@ void TranslatePrefs::RemoveFromLanguageList(const std::string& input_language) { ...@@ -260,7 +278,7 @@ void TranslatePrefs::RemoveFromLanguageList(const std::string& input_language) {
// We should unblock the language if this was the last one from the same // We should unblock the language if this was the last one from the same
// language family. // language family.
if (!language::ContainsSameBaseLanguage(languages, chrome_language)) { if (!ContainsSameBaseLanguage(languages, chrome_language)) {
UnblockLanguage(input_language); UnblockLanguage(input_language);
} }
} }
...@@ -943,13 +961,13 @@ bool TranslatePrefs::IsDictionaryEmpty(const char* pref_id) const { ...@@ -943,13 +961,13 @@ bool TranslatePrefs::IsDictionaryEmpty(const char* pref_id) const {
void TranslatePrefs::PurgeUnsupportedLanguagesInLanguageFamily( void TranslatePrefs::PurgeUnsupportedLanguagesInLanguageFamily(
const std::string& language, const std::string& language,
std::vector<std::string>* list) { std::vector<std::string>* list) {
std::string base_language = language::ExtractBaseLanguage(language); base::StringPiece base_language = language::ExtractBaseLanguage(language);
std::set<std::string> languages_in_same_family; std::set<std::string> languages_in_same_family;
std::copy_if( std::copy_if(
list->begin(), list->end(), list->begin(), list->end(),
std::inserter(languages_in_same_family, languages_in_same_family.end()), std::inserter(languages_in_same_family, languages_in_same_family.end()),
[&base_language](const std::string& lang) { [base_language](const std::string& lang) {
return base_language == language::ExtractBaseLanguage(lang); return base_language == language::ExtractBaseLanguage(lang);
}); });
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment