diff options
author | yusukes@google.com <yusukes@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-06-18 10:12:21 +0000 |
---|---|---|
committer | yusukes@google.com <yusukes@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-06-18 10:12:21 +0000 |
commit | 1e8e765e76578341934e7285afa6b4e12b4f8c6e (patch) | |
tree | 9d6f8f21cf5a5b75938b40a6431343ae74672330 /chrome/browser/chromeos | |
parent | e713a43daff36ba4317c7585a1a6ea056f49cb8c (diff) | |
download | chromium_src-1e8e765e76578341934e7285afa6b4e12b4f8c6e.zip chromium_src-1e8e765e76578341934e7285afa6b4e12b4f8c6e.tar.gz chromium_src-1e8e765e76578341934e7285afa6b4e12b4f8c6e.tar.bz2 |
Added input_method_util.h.
- Moved all functions in language_menu_l10n_util.h to the new file.
- Moved static methods in language_library.h and language_config_model.h to the file.
BUG=none
TEST=try bot passed
Review URL: http://codereview.chromium.org/2810008
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@50223 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/chromeos')
14 files changed, 862 insertions, 800 deletions
diff --git a/chrome/browser/chromeos/cros/language_library.cc b/chrome/browser/chromeos/cros/language_library.cc index 0ddb1f2..0d377a5 100644 --- a/chrome/browser/chromeos/cros/language_library.cc +++ b/chrome/browser/chromeos/cros/language_library.cc @@ -37,111 +37,13 @@ bool FindAndUpdateProperty(const chromeos::ImeProperty& new_prop, return false; } -// There are some differences between ISO 639-2 (T) and ISO 639-2 B, and -// some language codes are not recognized by ICU (i.e. ICU cannot convert -// these codes to two-letter language codes and display names). Hence we -// convert these codes to ones that ICU recognize. -// -// See http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes for details. -const char* kIso639VariantMapping[][2] = { - {"cze", "ces"}, - {"ger", "deu"}, - {"gre", "ell"}, - // "scr" is not a ISO 639 code. For some reason, evdev.xml uses "scr" as - // the language code for Croatian. - {"scr", "hrv"}, - {"rum", "ron"}, - {"slo", "slk"}, -}; - // The default keyboard layout. const char kDefaultKeyboardLayout[] = "us"; + } // namespace namespace chromeos { -std::string InputMethodLibrary::NormalizeLanguageCode( - const std::string& language_code) { - // Some ibus engines return locale codes like "zh_CN" as language codes. - // Normalize these to like "zh-CN". - if (language_code.size() >= 5 && language_code[2] == '_') { - std::string copied_language_code = language_code; - copied_language_code[2] = '-'; - // Downcase the language code part. - for (size_t i = 0; i < 2; ++i) { - copied_language_code[i] = ToLowerASCII(copied_language_code[i]); - } - // Upcase the country code part. - for (size_t i = 3; i < copied_language_code.size(); ++i) { - copied_language_code[i] = ToUpperASCII(copied_language_code[i]); - } - return copied_language_code; - } - // We only handle three-letter codes from here. - if (language_code.size() != 3) { - return language_code; - } - - // Convert special language codes. See comments at kIso639VariantMapping. - std::string copied_language_code = language_code; - for (size_t i = 0; i < arraysize(kIso639VariantMapping); ++i) { - if (language_code == kIso639VariantMapping[i][0]) { - copied_language_code = kIso639VariantMapping[i][1]; - } - } - // Convert the three-letter code to two letter-code. - UErrorCode error = U_ZERO_ERROR; - char two_letter_code[ULOC_LANG_CAPACITY]; - uloc_getLanguage(copied_language_code.c_str(), - two_letter_code, sizeof(two_letter_code), &error); - if (U_FAILURE(error)) { - return language_code; - } - return two_letter_code; -} - -bool InputMethodLibrary::IsKeyboardLayout(const std::string& input_method_id) { - const bool kCaseInsensitive = false; - return StartsWithASCII(input_method_id, "xkb:", kCaseInsensitive); -} - -std::string InputMethodLibrary::GetLanguageCodeFromDescriptor( - const InputMethodDescriptor& descriptor) { - // Handle some Chinese input methods as zh-CN/zh-TW, rather than zh. - // TODO: we should fix this issue in engines rather than here. - if (descriptor.language_code == "zh") { - if (descriptor.id == "pinyin") { - return "zh-CN"; - } else if (descriptor.id == "bopomofo" || - descriptor.id == "chewing" || - descriptor.id == "m17n:zh:cangjie" || - descriptor.id == "m17n:zh:quick") { - return "zh-TW"; - } - } - - std::string language_code = - InputMethodLibrary::NormalizeLanguageCode(descriptor.language_code); - - // Add country codes to language codes of some XKB input methods to make - // these compatible with Chrome's application locale codes like "en-US". - // TODO(satorux): Maybe we need to handle "es" for "es-419". - // TODO: We should not rely on the format of the engine name. Should we add - // |country_code| in InputMethodDescriptor? - if (IsKeyboardLayout(descriptor.id) && - (language_code == "en" || - language_code == "zh" || - language_code == "pt")) { - std::vector<std::string> portions; - SplitString(descriptor.id, ':', &portions); - if (portions.size() >= 2 && !portions[1].empty()) { - language_code.append("-"); - language_code.append(StringToUpperASCII(portions[1])); - } - } - return language_code; -} - InputMethodLibraryImpl::InputMethodLibraryImpl() : input_method_status_connection_(NULL), previous_input_method_("", "", "", ""), diff --git a/chrome/browser/chromeos/cros/language_library.h b/chrome/browser/chromeos/cros/language_library.h index 47b6006..f961880 100644 --- a/chrome/browser/chromeos/cros/language_library.h +++ b/chrome/browser/chromeos/cros/language_library.h @@ -84,36 +84,6 @@ class InputMethodLibrary { virtual const InputMethodDescriptor& current_input_method() const = 0; virtual const ImePropertyList& current_ime_properties() const = 0; - - // Normalizes the language code and returns the normalized version. The - // function normalizes the given language code to be compatible with the - // one used in Chrome's application locales. Otherwise, returns the - // given language code as-is. - // - // Examples: - // - // - "zh_CN" => "zh-CN" (Use - instead of _) - // - "jpn" => "ja" (Use two-letter code) - // - "t" => "t" (Return as-is if unknown) - static std::string NormalizeLanguageCode(const std::string& language_code); - - // Returns true if the given input method id is for a keyboard layout. - static bool IsKeyboardLayout(const std::string& input_method_id); - - // Gets the language code from the given input method descriptor. This - // encapsulates differences between the language codes used in - // InputMethodDescriptor and Chrome's application locale codes. - static std::string GetLanguageCodeFromDescriptor( - const InputMethodDescriptor& descriptor); - - // Gets the keyboard layout name from the given input method ID. - // If the ID is invalid, the default layout name will be returned. - // - // Examples: - // - // "xkb:us::eng" => "us" - // "xkb:us:dvorak:eng" => "us(dvorak)" - static std::string GetKeyboardLayoutName(const std::string& input_method_id); }; // This class handles the interaction with the ChromeOS language library APIs. diff --git a/chrome/browser/chromeos/cros/language_library_test.cc b/chrome/browser/chromeos/cros/language_library_test.cc deleted file mode 100644 index ab62901..0000000 --- a/chrome/browser/chromeos/cros/language_library_test.cc +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) 2010 The Chromium 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 "chrome/browser/chromeos/cros/language_library.h" -#include <string> -#include "testing/gtest/include/gtest/gtest.h" - -namespace chromeos { - -TEST(InputMethodLibraryTest, NormalizeLanguageCode) { - // TODO(yusukes): test all language codes that IBus provides. - EXPECT_EQ("ja", InputMethodLibrary::NormalizeLanguageCode("ja")); - EXPECT_EQ("ja", InputMethodLibrary::NormalizeLanguageCode("jpn")); - EXPECT_EQ("t", InputMethodLibrary::NormalizeLanguageCode("t")); - EXPECT_EQ("zh-CN", InputMethodLibrary::NormalizeLanguageCode("zh-CN")); - EXPECT_EQ("zh-CN", InputMethodLibrary::NormalizeLanguageCode("zh_CN")); - EXPECT_EQ("en-US", InputMethodLibrary::NormalizeLanguageCode("EN_us")); - // See app/l10n_util.cc for es-419. - EXPECT_EQ("es-419", InputMethodLibrary::NormalizeLanguageCode("es_419")); - - // Special three-letter language codes. - EXPECT_EQ("cs", InputMethodLibrary::NormalizeLanguageCode("cze")); - EXPECT_EQ("de", InputMethodLibrary::NormalizeLanguageCode("ger")); - EXPECT_EQ("el", InputMethodLibrary::NormalizeLanguageCode("gre")); - EXPECT_EQ("hr", InputMethodLibrary::NormalizeLanguageCode("scr")); - EXPECT_EQ("ro", InputMethodLibrary::NormalizeLanguageCode("rum")); - EXPECT_EQ("sk", InputMethodLibrary::NormalizeLanguageCode("slo")); -} - -TEST(InputMethodLibraryTest, IsKeyboardLayout) { - EXPECT_TRUE(InputMethodLibrary::IsKeyboardLayout("xkb:us::eng")); - EXPECT_FALSE(InputMethodLibrary::IsKeyboardLayout("anthy")); -} - -TEST(InputMethodLibraryTest, GetLanguageCodeFromDescriptor) { - EXPECT_EQ("ja", InputMethodLibrary::GetLanguageCodeFromDescriptor( - InputMethodDescriptor("anthy", "Anthy", "us", "ja"))); - EXPECT_EQ("zh-TW", InputMethodLibrary::GetLanguageCodeFromDescriptor( - InputMethodDescriptor("chewing", "Chewing", "us", "zh"))); - EXPECT_EQ("zh-TW", InputMethodLibrary::GetLanguageCodeFromDescriptor( - InputMethodDescriptor("bopomofo", "Bopomofo(Zhuyin)", "us", "zh"))); - EXPECT_EQ("zh-TW", InputMethodLibrary::GetLanguageCodeFromDescriptor( - InputMethodDescriptor("m17n:zh:cangjie", "Cangjie", "us", "zh"))); - EXPECT_EQ("zh-TW", InputMethodLibrary::GetLanguageCodeFromDescriptor( - InputMethodDescriptor("m17n:zh:quick", "Quick", "us", "zh"))); - EXPECT_EQ("zh-CN", InputMethodLibrary::GetLanguageCodeFromDescriptor( - InputMethodDescriptor("pinyin", "Pinyin", "us", "zh"))); - EXPECT_EQ("en-US", InputMethodLibrary::GetLanguageCodeFromDescriptor( - InputMethodDescriptor("xkb:us::eng", "USA", "us", "eng"))); - EXPECT_EQ("en-UK", InputMethodLibrary::GetLanguageCodeFromDescriptor( - InputMethodDescriptor("xkb:uk::eng", "United Kingdom", "us", "eng"))); -} - -} // namespace chromeos diff --git a/chrome/browser/chromeos/input_method/input_method_util.cc b/chrome/browser/chromeos/input_method/input_method_util.cc new file mode 100644 index 0000000..9d7cf1e --- /dev/null +++ b/chrome/browser/chromeos/input_method/input_method_util.cc @@ -0,0 +1,503 @@ +// Copyright (c) 2010 The Chromium 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 "chrome/browser/chromeos/input_method/input_method_util.h" + +#include <map> +#include <utility> + +#include "app/l10n_util.h" +#include "app/l10n_util_collator.h" +#include "base/basictypes.h" +#include "base/hash_tables.h" +#include "base/scoped_ptr.h" +#include "base/utf_string_conversions.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/chrome_thread.h" +#include "chrome/browser/chromeos/cros/cros_library.h" +#include "chrome/browser/chromeos/cros/keyboard_library.h" +#include "grit/generated_resources.h" +#include "third_party/icu/public/common/unicode/uloc.h" + +namespace { + +// Map from language code to associated input method IDs. +typedef std::multimap<std::string, std::string> LanguageCodeToIdsMap; +LanguageCodeToIdsMap* g_language_code_to_ids_map = NULL; + +const struct EnglishToResouceId { + const char* english_string_from_ibus; + int resource_id; +} kEnglishToResourceIdArray[] = { + // For ibus-mozc: third_party/ibus-mozc/files/src/unix/ibus/. + { "Direct input", IDS_STATUSBAR_IME_JAPANESE_IME_STATUS_DIRECT_INPUT }, + { "Hiragana", IDS_STATUSBAR_IME_JAPANESE_IME_STATUS_HIRAGANA }, + { "Katakana", IDS_STATUSBAR_IME_JAPANESE_IME_STATUS_KATAKANA }, + { "Half width katakana", // small k is not a typo. + IDS_STATUSBAR_IME_JAPANESE_IME_STATUS_HALF_WIDTH_KATAKANA }, + { "Latin", IDS_STATUSBAR_IME_JAPANESE_IME_STATUS_LATIN }, + { "Wide Latin", IDS_STATUSBAR_IME_JAPANESE_IME_STATUS_WIDE_LATIN }, + + // For ibus-hangul: third_party/ibus-hangul/files/po/. + { "Enable/Disable Hanja mode", IDS_STATUSBAR_IME_KOREAN_HANJA_MODE }, + + // For ibus-pinyin: third_party/ibus-pinyin/files/po/. + { "Chinese", IDS_STATUSBAR_IME_CHINESE_PINYIN_TOGGLE_CHINESE_ENGLISH }, + { "Full/Half width", + IDS_STATUSBAR_IME_CHINESE_PINYIN_TOGGLE_FULL_HALF }, + { "Full/Half width punctuation", + IDS_STATUSBAR_IME_CHINESE_PINYIN_TOGGLE_FULL_HALF_PUNCTUATION }, + { "Simplfied/Traditional Chinese", + IDS_STATUSBAR_IME_CHINESE_PINYIN_TOGGLE_S_T_CHINESE }, + + // TODO(yusukes): Support ibus-chewing and ibus-table-* if needed. + + // For the "Languages and Input" dialog. + { "kbd (m17n)", IDS_OPTIONS_SETTINGS_LANGUAGES_M17N_STANDARD_INPUT_METHOD }, + { "itrans (m17n)", // also uses the "STANDARD_INPUT_METHOD" id. + IDS_OPTIONS_SETTINGS_LANGUAGES_M17N_STANDARD_INPUT_METHOD }, + { "cangjie (m17n)", + IDS_OPTIONS_SETTINGS_LANGUAGES_M17N_CHINESE_CANGJIE_INPUT_METHOD }, + { "quick (m17n)", + IDS_OPTIONS_SETTINGS_LANGUAGES_M17N_CHINESE_QUICK_INPUT_METHOD }, + { "isiri (m17n)", + IDS_OPTIONS_SETTINGS_LANGUAGES_M17N_PERSIAN_ISIRI_2901_INPUT_METHOD }, + { "kesmanee (m17n)", + IDS_OPTIONS_SETTINGS_LANGUAGES_M17N_THAI_KESMANEE_INPUT_METHOD }, + { "tis820 (m17n)", + IDS_OPTIONS_SETTINGS_LANGUAGES_M17N_THAI_TIS820_INPUT_METHOD }, + { "pattachote (m17n)", + IDS_OPTIONS_SETTINGS_LANGUAGES_M17N_THAI_PATTACHOTE_INPUT_METHOD }, + { "tcvn (m17n)", + IDS_OPTIONS_SETTINGS_LANGUAGES_M17N_VIETNAMESE_TCVN_INPUT_METHOD }, + { "telex (m17n)", + IDS_OPTIONS_SETTINGS_LANGUAGES_M17N_VIETNAMESE_TELEX_INPUT_METHOD }, + { "viqr (m17n)", + IDS_OPTIONS_SETTINGS_LANGUAGES_M17N_VIETNAMESE_VIQR_INPUT_METHOD }, + { "vni (m17n)", + IDS_OPTIONS_SETTINGS_LANGUAGES_M17N_VIETNAMESE_VNI_INPUT_METHOD }, + { "latn-post (m17n)", + IDS_OPTIONS_SETTINGS_LANGUAGES_M17N_LATIN_POST_INPUT_METHOD }, + { "latn-pre (m17n)", + IDS_OPTIONS_SETTINGS_LANGUAGES_M17N_LATIN_PRE_INPUT_METHOD }, + { "Bopomofo", IDS_OPTIONS_SETTINGS_LANGUAGES_BOPOMOFO_INPUT_METHOD }, + { "Chewing", IDS_OPTIONS_SETTINGS_LANGUAGES_CHEWING_INPUT_METHOD }, + { "Pinyin", IDS_OPTIONS_SETTINGS_LANGUAGES_PINYIN_INPUT_METHOD }, + { "Mozc (US keyboard layout)", + IDS_OPTIONS_SETTINGS_LANGUAGES_JAPANESE_MOZC_US_INPUT_METHOD }, + { "Mozc (Japanese keyboard layout)", + IDS_OPTIONS_SETTINGS_LANGUAGES_JAPANESE_MOZC_JP_INPUT_METHOD }, + { "Google Japanese Input (US keyboard layout)", + IDS_OPTIONS_SETTINGS_LANGUAGES_JAPANESE_GOOGLE_US_INPUT_METHOD }, + { "Google Japanese Input (Japanese keyboard layout)", + IDS_OPTIONS_SETTINGS_LANGUAGES_JAPANESE_GOOGLE_JP_INPUT_METHOD }, + { "Korean", IDS_OPTIONS_SETTINGS_LANGUAGES_KOREAN_INPUT_METHOD }, + + // For ibus-xkb-layouts engine: third_party/ibus-xkb-layouts/files + { "Japan", IDS_STATUSBAR_LAYOUT_JAPAN }, + { "Slovenia", IDS_STATUSBAR_LAYOUT_SLOVENIA }, + { "Germany", IDS_STATUSBAR_LAYOUT_GERMANY }, + { "Italy", IDS_STATUSBAR_LAYOUT_ITALY }, + { "Estonia", IDS_STATUSBAR_LAYOUT_ESTONIA }, + { "Hungary", IDS_STATUSBAR_LAYOUT_HUNGARY }, + { "Poland", IDS_STATUSBAR_LAYOUT_POLAND }, + { "Denmark", IDS_STATUSBAR_LAYOUT_DENMARK }, + { "Croatia", IDS_STATUSBAR_LAYOUT_CROATIA }, + { "Brazil", IDS_STATUSBAR_LAYOUT_BRAZIL }, + { "Serbia", IDS_STATUSBAR_LAYOUT_SERBIA }, + { "Czechia", IDS_STATUSBAR_LAYOUT_CZECHIA }, + { "USA - Dvorak", IDS_STATUSBAR_LAYOUT_USA_DVORAK }, + { "Romania", IDS_STATUSBAR_LAYOUT_ROMANIA }, + { "USA", IDS_STATUSBAR_LAYOUT_USA }, + { "Lithuania", IDS_STATUSBAR_LAYOUT_LITHUANIA }, + { "United Kingdom", IDS_STATUSBAR_LAYOUT_UNITED_KINGDOM }, + { "Slovakia", IDS_STATUSBAR_LAYOUT_SLOVAKIA }, + { "Russia", IDS_STATUSBAR_LAYOUT_RUSSIA }, + { "Greece", IDS_STATUSBAR_LAYOUT_GREECE }, + { "Belgium", IDS_STATUSBAR_LAYOUT_BELGIUM }, + { "Bulgaria", IDS_STATUSBAR_LAYOUT_BULGARIA }, + { "Switzerland", IDS_STATUSBAR_LAYOUT_SWITZERLAND }, + { "Turkey", IDS_STATUSBAR_LAYOUT_TURKEY }, + { "Portugal", IDS_STATUSBAR_LAYOUT_PORTUGAL }, + { "Spain", IDS_STATUSBAR_LAYOUT_SPAIN }, + { "Finland", IDS_STATUSBAR_LAYOUT_FINLAND }, + { "Ukraine", IDS_STATUSBAR_LAYOUT_UKRAINE }, + { "Spain - Catalan variant with middle-dot L", + IDS_STATUSBAR_LAYOUT_SPAIN_CATALAN }, + { "France", IDS_STATUSBAR_LAYOUT_FRANCE }, + { "Norway", IDS_STATUSBAR_LAYOUT_NORWAY }, + { "Sweden", IDS_STATUSBAR_LAYOUT_SWEDEN }, + { "Netherlands", IDS_STATUSBAR_LAYOUT_NETHERLANDS }, + { "Latvia", IDS_STATUSBAR_LAYOUT_LATVIA }, +}; +const size_t kNumEntries = arraysize(kEnglishToResourceIdArray); + +// There are some differences between ISO 639-2 (T) and ISO 639-2 B, and +// some language codes are not recognized by ICU (i.e. ICU cannot convert +// these codes to two-letter language codes and display names). Hence we +// convert these codes to ones that ICU recognize. +// +// See http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes for details. +const char* kIso639VariantMapping[][2] = { + {"cze", "ces"}, + {"ger", "deu"}, + {"gre", "ell"}, + // "scr" is not a ISO 639 code. For some reason, evdev.xml uses "scr" as + // the language code for Croatian. + {"scr", "hrv"}, + {"rum", "ron"}, + {"slo", "slk"}, +}; + +// The list defines pairs of language code and the default input method +// id. The list is used for reordering input method ids. +// +// TODO(satorux): We may need to handle secondary, and ternary input +// methods, rather than handling the default input method only. +const struct LanguageDefaultInputMethodId { + const char* language_code; + const char* input_method_id; +} kLanguageDefaultInputMethodIds[] = { + { "en-US", "xkb:us::eng", }, // US - English + { "fr", "xkb:fr::fra", }, // France - French + { "de", "xkb:de::ger", }, // Germany - German +}; + +// The comparator is used for sorting language codes by their +// corresponding language names, using the ICU collator. +struct CompareLanguageCodesByLanguageName + : std::binary_function<const std::string&, const std::string&, bool> { + explicit CompareLanguageCodesByLanguageName(icu::Collator* collator) + : collator_(collator) { + } + + // Calling GetLanguageDisplayNameFromCode() in the comparator is not + // efficient, but acceptable as the function is cheap, and the language + // list is short (about 40 at most). + bool operator()(const std::string& s1, const std::string& s2) const { + const std::wstring key1 = + chromeos::input_method::GetLanguageDisplayNameFromCode(s1); + const std::wstring key2 = + chromeos::input_method::GetLanguageDisplayNameFromCode(s2); + return l10n_util::StringComparator<std::wstring>(collator_)(key1, key2); + } + + icu::Collator* collator_; +}; + +// The comparator is used for sorting input method ids by their +// corresponding language names, using the ICU collator. +struct CompareInputMethodIdsByLanguageName + : std::binary_function<const std::string&, const std::string&, bool> { + CompareInputMethodIdsByLanguageName( + icu::Collator* collator, + const std::map<std::string, std::string>& id_to_language_code_map) + : comparator_(collator), + id_to_language_code_map_(id_to_language_code_map) { + } + + bool operator()(const std::string& s1, const std::string& s2) const { + std::string language_code_1; + std::map<std::string, std::string>::const_iterator iter = + id_to_language_code_map_.find(s1); + if (iter != id_to_language_code_map_.end()) { + language_code_1 = iter->second; + } + std::string language_code_2; + iter = id_to_language_code_map_.find(s2); + if (iter != id_to_language_code_map_.end()) { + language_code_2 = iter->second; + } + return comparator_(language_code_1, language_code_2); + } + + const CompareLanguageCodesByLanguageName comparator_; + const std::map<std::string, std::string>& id_to_language_code_map_; +}; + +bool GetLocalizedString( + const std::string& english_string, string16 *out_string) { + DCHECK(out_string); + typedef base::hash_map<std::string, int> HashType; + static HashType* english_to_resource_id = NULL; + + // Initialize the map if needed. + if (!english_to_resource_id) { + // We don't free this map. + english_to_resource_id = new HashType(kNumEntries); + for (size_t i = 0; i < kNumEntries; ++i) { + const bool result = english_to_resource_id->insert( + std::make_pair(kEnglishToResourceIdArray[i].english_string_from_ibus, + kEnglishToResourceIdArray[i].resource_id)).second; + DCHECK(result) << "Duplicated string is found: " + << kEnglishToResourceIdArray[i].english_string_from_ibus; + } + } + + HashType::const_iterator iter = english_to_resource_id->find(english_string); + if (iter == english_to_resource_id->end()) { + LOG(ERROR) << "Resouce ID is not found for: " << english_string; + return false; + } + + *out_string = l10n_util::GetStringUTF16(iter->second); + return true; +}; + +// Initializes |g_language_code_to_ids_map| if necessary. +// Returns true on success. If this function returns true, it is guaranteed +// |g_language_code_to_ids_map| is non-NULL. The function might return false +// when ibus-daemon is not ready. +bool InitializeLanguageCodeToIdsMap() { + if (g_language_code_to_ids_map) { + return true; + } + + chromeos::InputMethodLibrary* library = + chromeos::CrosLibrary::Get()->GetInputMethodLibrary(); + scoped_ptr<chromeos::InputMethodDescriptors> supported_input_methods( + library->GetSupportedInputMethods()); + if (supported_input_methods->size() <= 1) { + // TODO(yusukes): Handle this error in nicer way. + LOG(ERROR) << "GetSupportedInputMethods returned a fallback ID"; + return false; + } + + g_language_code_to_ids_map = new LanguageCodeToIdsMap; + for (size_t i = 0; i < supported_input_methods->size(); ++i) { + const std::string language_code = + chromeos::input_method::GetLanguageCodeFromDescriptor( + supported_input_methods->at(i)); + const std::string& input_method_id = supported_input_methods->at(i).id; + g_language_code_to_ids_map->insert( + std::make_pair(language_code, input_method_id)); + } + // Go through the languages listed in kExtraLanguages. + using chromeos::input_method::kExtraLanguages; + for (size_t i = 0; i < arraysize(kExtraLanguages); ++i) { + const char* language_code = kExtraLanguages[i].language_code; + const char* input_method_id = kExtraLanguages[i].input_method_id; + g_language_code_to_ids_map->insert( + std::make_pair(language_code, input_method_id)); + } + return true; +} + +} // namespace + +namespace chromeos { +namespace input_method { + +std::wstring GetString(const std::string& english_string) { + string16 localized_string; + if (GetLocalizedString(english_string, &localized_string)) { + return UTF16ToWide(localized_string); + } + return UTF8ToWide(english_string); +} + +std::string GetStringUTF8(const std::string& english_string) { + string16 localized_string; + if (GetLocalizedString(english_string, &localized_string)) { + return UTF16ToUTF8(localized_string); + } + return english_string; +} + +string16 GetStringUTF16(const std::string& english_string) { + string16 localized_string; + if (GetLocalizedString(english_string, &localized_string)) { + return localized_string; + } + return UTF8ToUTF16(english_string); +} + +bool StringIsSupported(const std::string& english_string) { + string16 localized_string; + return GetLocalizedString(english_string, &localized_string); +} + +std::string NormalizeLanguageCode( + const std::string& language_code) { + // Some ibus engines return locale codes like "zh_CN" as language codes. + // Normalize these to like "zh-CN". + if (language_code.size() >= 5 && language_code[2] == '_') { + std::string copied_language_code = language_code; + copied_language_code[2] = '-'; + // Downcase the language code part. + for (size_t i = 0; i < 2; ++i) { + copied_language_code[i] = ToLowerASCII(copied_language_code[i]); + } + // Upcase the country code part. + for (size_t i = 3; i < copied_language_code.size(); ++i) { + copied_language_code[i] = ToUpperASCII(copied_language_code[i]); + } + return copied_language_code; + } + // We only handle three-letter codes from here. + if (language_code.size() != 3) { + return language_code; + } + + // Convert special language codes. See comments at kIso639VariantMapping. + std::string copied_language_code = language_code; + for (size_t i = 0; i < arraysize(kIso639VariantMapping); ++i) { + if (language_code == kIso639VariantMapping[i][0]) { + copied_language_code = kIso639VariantMapping[i][1]; + } + } + // Convert the three-letter code to two letter-code. + UErrorCode error = U_ZERO_ERROR; + char two_letter_code[ULOC_LANG_CAPACITY]; + uloc_getLanguage(copied_language_code.c_str(), + two_letter_code, sizeof(two_letter_code), &error); + if (U_FAILURE(error)) { + return language_code; + } + return two_letter_code; +} + +bool IsKeyboardLayout(const std::string& input_method_id) { + const bool kCaseInsensitive = false; + return StartsWithASCII(input_method_id, "xkb:", kCaseInsensitive); +} + +std::string GetLanguageCodeFromDescriptor( + const InputMethodDescriptor& descriptor) { + // Handle some Chinese input methods as zh-CN/zh-TW, rather than zh. + // TODO: we should fix this issue in engines rather than here. + if (descriptor.language_code == "zh") { + if (descriptor.id == "pinyin") { + return "zh-CN"; + } else if (descriptor.id == "bopomofo" || + descriptor.id == "chewing" || + descriptor.id == "m17n:zh:cangjie" || + descriptor.id == "m17n:zh:quick") { + return "zh-TW"; + } + } + + std::string language_code = NormalizeLanguageCode(descriptor.language_code); + + // Add country codes to language codes of some XKB input methods to make + // these compatible with Chrome's application locale codes like "en-US". + // TODO(satorux): Maybe we need to handle "es" for "es-419". + // TODO: We should not rely on the format of the engine name. Should we add + // |country_code| in InputMethodDescriptor? + if (IsKeyboardLayout(descriptor.id) && + (language_code == "en" || + language_code == "zh" || + language_code == "pt")) { + std::vector<std::string> portions; + SplitString(descriptor.id, ':', &portions); + if (portions.size() >= 2 && !portions[1].empty()) { + language_code.append("-"); + language_code.append(StringToUpperASCII(portions[1])); + } + } + return language_code; +} + +std::wstring MaybeRewriteLanguageName(const std::wstring& language_name) { + // "t" is used as the language code for input methods that don't fall + // under any other languages. + if (language_name == L"t") { + return l10n_util::GetString( + IDS_OPTIONS_SETTINGS_LANGUAGES_OTHERS); + } + return language_name; +} + +std::wstring GetLanguageDisplayNameFromCode(const std::string& language_code) { + if (!g_browser_process) { + return L""; + } + return MaybeRewriteLanguageName(UTF16ToWide( + l10n_util::GetDisplayNameForLocale( + language_code, g_browser_process->GetApplicationLocale(), + true))); +} + +void SortLanguageCodesByNames(std::vector<std::string>* language_codes) { + if (!g_browser_process) { + return; + } + // We should build collator outside of the comparator. We cannot have + // scoped_ptr<> in the comparator for a subtle STL reason. + UErrorCode error = U_ZERO_ERROR; + icu::Locale locale(g_browser_process->GetApplicationLocale().c_str()); + scoped_ptr<icu::Collator> collator( + icu::Collator::createInstance(locale, error)); + if (U_FAILURE(error)) { + collator.reset(); + } + std::sort(language_codes->begin(), language_codes->end(), + CompareLanguageCodesByLanguageName(collator.get())); +} + +void SortInputMethodIdsByNames( + const std::map<std::string, std::string>& id_to_language_code_map, + std::vector<std::string>* input_method_ids) { + if (!g_browser_process) { + return; + } + UErrorCode error = U_ZERO_ERROR; + icu::Locale locale(g_browser_process->GetApplicationLocale().c_str()); + scoped_ptr<icu::Collator> collator( + icu::Collator::createInstance(locale, error)); + if (U_FAILURE(error)) { + collator.reset(); + } + std::stable_sort(input_method_ids->begin(), input_method_ids->end(), + CompareInputMethodIdsByLanguageName( + collator.get(), id_to_language_code_map)); +} + +void ReorderInputMethodIdsForLanguageCode( + const std::string& language_code, + std::vector<std::string>* input_method_ids) { + for (size_t i = 0; i < arraysize(kLanguageDefaultInputMethodIds); ++i) { + if (language_code == kLanguageDefaultInputMethodIds[i].language_code) { + std::vector<std::string>::iterator iter = + std::find(input_method_ids->begin(), input_method_ids->end(), + kLanguageDefaultInputMethodIds[i].input_method_id); + // If it's not on the top of |input_method_id|, swap it with the top one. + if (iter != input_method_ids->end() && + iter != input_method_ids->begin()) { + std::swap(*input_method_ids->begin(), *iter); + } + break; // Don't have to check other language codes. + } + } +} + +bool GetInputMethodIdsByLanguageCode( + const std::string& normalized_language_code, + bool keyboard_layout_only, + std::vector<std::string>* out_input_method_ids) { + DCHECK(out_input_method_ids); + out_input_method_ids->clear(); + + bool result = false; + if (InitializeLanguageCodeToIdsMap()) { + std::pair<LanguageCodeToIdsMap::const_iterator, + LanguageCodeToIdsMap::const_iterator> range = + g_language_code_to_ids_map->equal_range(normalized_language_code); + for (LanguageCodeToIdsMap::const_iterator iter = range.first; + iter != range.second; ++iter) { + const std::string& input_method_id = iter->second; + if ((!keyboard_layout_only) || IsKeyboardLayout(input_method_id)) { + out_input_method_ids->push_back(input_method_id); + result = true; + } + } + if (!result) { + LOG(ERROR) << "Unknown language code: " << normalized_language_code; + } + } + return result; +} + +} // namespace input_method +} // namespace chromeos diff --git a/chrome/browser/chromeos/input_method/input_method_util.h b/chrome/browser/chromeos/input_method/input_method_util.h new file mode 100644 index 0000000..77ebbd3 --- /dev/null +++ b/chrome/browser/chromeos/input_method/input_method_util.h @@ -0,0 +1,119 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROMEOS_INPUT_METHOD_INPUT_METHOD_UTIL_H_ +#define CHROME_BROWSER_CHROMEOS_INPUT_METHOD_INPUT_METHOD_UTIL_H_ + +#include <string> +#include <vector> + +#include "base/string16.h" +#include "chrome/browser/chromeos/cros/language_library.h" + +namespace chromeos { +namespace input_method { + +// The list of language that do not have associated input methods. For +// these languages, we associate input methods here. +const struct ExtraLanguage { + const char* language_code; + const char* input_method_id; +} kExtraLanguages[] = { + { "id", "xkb:us::eng" }, // For Indonesian, use US keyboard layout. + // The code "fil" comes from app/l10_util.cc. + { "fil", "xkb:us::eng" }, // For Filipino, use US keyboard layout. + // The code "es-419" comes from app/l10_util.cc. + // For Spanish in Latin America, use Spanish keyboard layout. + { "es-419", "xkb:es::spa" }, +}; +// TODO(yusukes): Move |kExtraLanguages| to input_method_util.cc. + +// Converts a string sent from IBus IME engines, which is written in English, +// into Chrome's string ID, then pulls internationalized resource string from +// the resource bundle and returns it. These functions are not thread-safe. +// Non-UI threads are not allowed to call them. +std::wstring GetString(const std::string& english_string); +std::string GetStringUTF8(const std::string& english_string); +string16 GetStringUTF16(const std::string& english_string); + +// This method is ONLY for unit testing. Returns true if the given string is +// supported (i.e. the string is associated with a resource ID). +bool StringIsSupported(const std::string& english_string); + +// Normalizes the language code and returns the normalized version. The +// function normalizes the given language code to be compatible with the +// one used in Chrome's application locales. Otherwise, returns the +// given language code as-is. +// +// Examples: +// +// - "zh_CN" => "zh-CN" (Use - instead of _) +// - "jpn" => "ja" (Use two-letter code) +// - "t" => "t" (Return as-is if unknown) +std::string NormalizeLanguageCode(const std::string& language_code); + +// Returns true if the given input method id is for a keyboard layout. +bool IsKeyboardLayout(const std::string& input_method_id); + +// Gets the language code from the given input method descriptor. This +// encapsulates differences between the language codes used in +// InputMethodDescriptor and Chrome's application locale codes. +std::string GetLanguageCodeFromDescriptor( + const InputMethodDescriptor& descriptor); + +// Gets the keyboard layout name from the given input method ID. +// If the ID is invalid, the default layout name will be returned. +// +// Examples: +// +// "xkb:us::eng" => "us" +// "xkb:us:dvorak:eng" => "us(dvorak)" +std::string GetKeyboardLayoutName(const std::string& input_method_id); + +// Rewrites the language name and returns the modified version if +// necessary. Otherwise, returns the given language name as is. +// In particular, this rewrites the special language name used for input +// methods that don't fall under any other languages. +std::wstring MaybeRewriteLanguageName(const std::wstring& language_name); + +// Converts a language code to a language display name, using the +// current application locale. MaybeRewriteLanguageName() is called +// internally. +// Examples: "fr" => "French" +// "en-US" => "English (United States)" +std::wstring GetLanguageDisplayNameFromCode(const std::string& language_code); + +// Sorts the given language codes by their corresponding language names, +// using the unicode string comparator. Uses unstable sorting. +void SortLanguageCodesByNames(std::vector<std::string>* language_codes); + +// Sorts the given input method ids by their corresponding language names, +// using the unicode string comparator. Uses stable sorting. +void SortInputMethodIdsByNames( + const std::map<std::string, std::string>& id_to_language_code_map, + std::vector<std::string>* input_method_ids); + +// Reorders the given input method ids for the language code. For +// example, if |language_codes| is "fr" and |input_method_ids| contains +// ["xkb:be::fra", and "xkb:fr::fra"], the list is reordered to +// ["xkb:fr::fra", and "xkb:be::fra"], so that French keyboard layout +// comes before Belgian keyboard layout. +void ReorderInputMethodIdsForLanguageCode( + const std::string& language_code, + std::vector<std::string>* input_method_ids); + +// Gets input method ids that belong to |language_code|. +// If |keyboard_layout_only| is true, the function does not return input methods +// that are not for keybord layout switching. Returns true on success. Note that +// the function might return false if ibus-daemon is not running, or +// |language_code| is unknown. +bool GetInputMethodIdsByLanguageCode( + const std::string& language_code, + bool keyboard_layout_only, + std::vector<std::string>* out_input_method_ids); + +} // namespace input_method +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_INPUT_METHOD_INPUT_METHOD_UTIL_H_ diff --git a/chrome/browser/chromeos/input_method/input_method_util_unittest.cc b/chrome/browser/chromeos/input_method/input_method_util_unittest.cc new file mode 100644 index 0000000..3c59b6a --- /dev/null +++ b/chrome/browser/chromeos/input_method/input_method_util_unittest.cc @@ -0,0 +1,204 @@ +// Copyright (c) 2010 The Chromium 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 "chrome/browser/chromeos/input_method/input_method_util.h" + +#include <string> + +#include "app/l10n_util.h" +#include "base/utf_string_conversions.h" +#include "grit/generated_resources.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace chromeos { +namespace input_method { + +TEST(InputMethodUtilTest, FindLocalizedStringTest) { + EXPECT_TRUE(StringIsSupported("Hiragana")); + EXPECT_TRUE(StringIsSupported("Latin")); + EXPECT_TRUE(StringIsSupported("Direct input")); + EXPECT_FALSE(StringIsSupported("####THIS_STRING_IS_NOT_SUPPORTED####")); +} + +TEST(InputMethodUtilTest, NormalizeLanguageCode) { + // TODO(yusukes): test all language codes that IBus provides. + EXPECT_EQ("ja", NormalizeLanguageCode("ja")); + EXPECT_EQ("ja", NormalizeLanguageCode("jpn")); + EXPECT_EQ("t", NormalizeLanguageCode("t")); + EXPECT_EQ("zh-CN", NormalizeLanguageCode("zh-CN")); + EXPECT_EQ("zh-CN", NormalizeLanguageCode("zh_CN")); + EXPECT_EQ("en-US", NormalizeLanguageCode("EN_us")); + // See app/l10n_util.cc for es-419. + EXPECT_EQ("es-419", NormalizeLanguageCode("es_419")); + + // Special three-letter language codes. + EXPECT_EQ("cs", NormalizeLanguageCode("cze")); + EXPECT_EQ("de", NormalizeLanguageCode("ger")); + EXPECT_EQ("el", NormalizeLanguageCode("gre")); + EXPECT_EQ("hr", NormalizeLanguageCode("scr")); + EXPECT_EQ("ro", NormalizeLanguageCode("rum")); + EXPECT_EQ("sk", NormalizeLanguageCode("slo")); +} + +TEST(InputMethodUtilTest, IsKeyboardLayout) { + EXPECT_TRUE(IsKeyboardLayout("xkb:us::eng")); + EXPECT_FALSE(IsKeyboardLayout("anthy")); +} + +TEST(InputMethodUtilTest, GetLanguageCodeFromDescriptor) { + EXPECT_EQ("ja", GetLanguageCodeFromDescriptor( + InputMethodDescriptor("anthy", "Anthy", "us", "ja"))); + EXPECT_EQ("zh-TW", GetLanguageCodeFromDescriptor( + InputMethodDescriptor("chewing", "Chewing", "us", "zh"))); + EXPECT_EQ("zh-TW", GetLanguageCodeFromDescriptor( + InputMethodDescriptor("bopomofo", "Bopomofo(Zhuyin)", "us", "zh"))); + EXPECT_EQ("zh-TW", GetLanguageCodeFromDescriptor( + InputMethodDescriptor("m17n:zh:cangjie", "Cangjie", "us", "zh"))); + EXPECT_EQ("zh-TW", GetLanguageCodeFromDescriptor( + InputMethodDescriptor("m17n:zh:quick", "Quick", "us", "zh"))); + EXPECT_EQ("zh-CN", GetLanguageCodeFromDescriptor( + InputMethodDescriptor("pinyin", "Pinyin", "us", "zh"))); + EXPECT_EQ("en-US", GetLanguageCodeFromDescriptor( + InputMethodDescriptor("xkb:us::eng", "USA", "us", "eng"))); + EXPECT_EQ("en-UK", GetLanguageCodeFromDescriptor( + InputMethodDescriptor("xkb:uk::eng", "United Kingdom", "us", "eng"))); +} + +TEST(LanguageConfigModelTest, MaybeRewriteLanguageName) { + EXPECT_EQ(L"English", MaybeRewriteLanguageName(L"English")); + EXPECT_EQ(l10n_util::GetString(IDS_OPTIONS_SETTINGS_LANGUAGES_OTHERS), + MaybeRewriteLanguageName(L"t")); +} + +TEST(LanguageConfigModelTest, GetLanguageDisplayNameFromCode) { + EXPECT_EQ(L"French", GetLanguageDisplayNameFromCode("fr")); + // MaybeRewriteLanguageName() should be applied. + EXPECT_EQ(l10n_util::GetString(IDS_OPTIONS_SETTINGS_LANGUAGES_OTHERS), + GetLanguageDisplayNameFromCode("t")); +} + +TEST(LanguageConfigModelTest, SortLanguageCodesByNames) { + std::vector<std::string> language_codes; + // Check if this function can handle an empty list. + SortLanguageCodesByNames(&language_codes); + + language_codes.push_back("ja"); + language_codes.push_back("fr"); + language_codes.push_back("t"); + SortLanguageCodesByNames(&language_codes); + ASSERT_EQ(3U, language_codes.size()); + ASSERT_EQ("fr", language_codes[0]); // French + ASSERT_EQ("ja", language_codes[1]); // Japanese + ASSERT_EQ("t", language_codes[2]); // Others + + // Add a duplicate entry and see if it works. + language_codes.push_back("ja"); + SortLanguageCodesByNames(&language_codes); + ASSERT_EQ(4U, language_codes.size()); + ASSERT_EQ("fr", language_codes[0]); // French + ASSERT_EQ("ja", language_codes[1]); // Japanese + ASSERT_EQ("ja", language_codes[2]); // Japanese + ASSERT_EQ("t", language_codes[3]); // Others +} + +TEST(LanguageConfigModelTest, SortInputMethodIdsByNames) { + std::map<std::string, std::string> id_to_language_code_map; + id_to_language_code_map.insert(std::make_pair("mozc", "ja")); + id_to_language_code_map.insert(std::make_pair("mozc-jp", "ja")); + id_to_language_code_map.insert(std::make_pair("xkb:jp::jpn", "ja")); + id_to_language_code_map.insert(std::make_pair("xkb:fr::fra", "fr")); + id_to_language_code_map.insert(std::make_pair("m17n:latn-pre", "t")); + + std::vector<std::string> input_method_ids; + // Check if this function can handle an empty list. + SortInputMethodIdsByNames(id_to_language_code_map, + &input_method_ids); + + input_method_ids.push_back("mozc"); // Japanese + input_method_ids.push_back("xkb:fr::fra"); // French + input_method_ids.push_back("m17n:latn-pre"); // Others + SortInputMethodIdsByNames(id_to_language_code_map, + &input_method_ids); + ASSERT_EQ(3U, input_method_ids.size()); + ASSERT_EQ("xkb:fr::fra", input_method_ids[0]); // French + ASSERT_EQ("mozc", input_method_ids[1]); // Japanese + ASSERT_EQ("m17n:latn-pre", input_method_ids[2]); // Others + + // Add a duplicate entry and see if it works. + // Note that SortInputMethodIdsByNames uses std::stable_sort. + input_method_ids.push_back("xkb:jp::jpn"); // also Japanese + SortInputMethodIdsByNames(id_to_language_code_map, + &input_method_ids); + ASSERT_EQ(4U, input_method_ids.size()); + ASSERT_EQ("xkb:fr::fra", input_method_ids[0]); // French + ASSERT_EQ("mozc", input_method_ids[1]); // Japanese + ASSERT_EQ("xkb:jp::jpn", input_method_ids[2]); // Japanese + ASSERT_EQ("m17n:latn-pre", input_method_ids[3]); // Others + + input_method_ids.push_back("mozc-jp"); // also Japanese + SortInputMethodIdsByNames(id_to_language_code_map, + &input_method_ids); + ASSERT_EQ(5U, input_method_ids.size()); + ASSERT_EQ("xkb:fr::fra", input_method_ids[0]); // French + ASSERT_EQ("mozc", input_method_ids[1]); // Japanese + ASSERT_EQ("xkb:jp::jpn", input_method_ids[2]); // Japanese + ASSERT_EQ("mozc-jp", input_method_ids[3]); // Japanese + ASSERT_EQ("m17n:latn-pre", input_method_ids[4]); // Others +} + +TEST(LanguageConfigModelTest, ReorderInputMethodIdsForLanguageCode_DE) { + std::vector<std::string> input_method_ids; + input_method_ids.push_back("xkb:ch::ger"); // Switzerland - German + input_method_ids.push_back("xkb:de::ger"); // Germany - German + ReorderInputMethodIdsForLanguageCode("de", &input_method_ids); + // The list should be reordered. + ASSERT_EQ(2U, input_method_ids.size()); + EXPECT_EQ("xkb:de::ger", input_method_ids[0]); + EXPECT_EQ("xkb:ch::ger", input_method_ids[1]); +} + +TEST(LanguageConfigModelTest, ReorderInputMethodIdsForLanguageCode_FR) { + std::vector<std::string> input_method_ids; + input_method_ids.push_back("xkb:be::fra"); // Belgium - French + input_method_ids.push_back("xkb:fr::fra"); // France - French + ReorderInputMethodIdsForLanguageCode("fr", &input_method_ids); + // The list should be reordered. + ASSERT_EQ(2U, input_method_ids.size()); + EXPECT_EQ("xkb:fr::fra", input_method_ids[0]); + EXPECT_EQ("xkb:be::fra", input_method_ids[1]); +} + +TEST(LanguageConfigModelTest, ReorderInputMethodIdsForLanguageCode_EN_US) { + std::vector<std::string> input_method_ids; + input_method_ids.push_back("xkb:us:dvorak:eng"); // US - Dvorak - English + input_method_ids.push_back("xkb:us::eng"); // US - English + ReorderInputMethodIdsForLanguageCode("en-US", &input_method_ids); + // The list should be reordered. + ASSERT_EQ(2U, input_method_ids.size()); + EXPECT_EQ("xkb:us::eng", input_method_ids[0]); + EXPECT_EQ("xkb:us:dvorak:eng", input_method_ids[1]); +} + +TEST(LanguageConfigModelTest, ReorderInputMethodIdsForLanguageCode_FI) { + std::vector<std::string> input_method_ids; + input_method_ids.push_back("xkb:fi::fin"); // Finland - Finnish + ReorderInputMethodIdsForLanguageCode("fi", &input_method_ids); + // There is no rule for reordering for Finnish. + ASSERT_EQ(1U, input_method_ids.size()); + EXPECT_EQ("xkb:fi::fin", input_method_ids[0]); +} + +TEST(LanguageConfigModelTest, ReorderInputMethodIdsForLanguageCode_Noop) { + std::vector<std::string> input_method_ids; + input_method_ids.push_back("xkb:fr::fra"); // France - French + input_method_ids.push_back("xkb:be::fra"); // Belgium - French + // If the list is already sorted, nothing should happen. + ReorderInputMethodIdsForLanguageCode("fr", &input_method_ids); + ASSERT_EQ(2U, input_method_ids.size()); + EXPECT_EQ("xkb:fr::fra", input_method_ids[0]); + EXPECT_EQ("xkb:be::fra", input_method_ids[1]); +} + +} // namespace input_method +} // namespace chromeos diff --git a/chrome/browser/chromeos/options/language_config_model.cc b/chrome/browser/chromeos/options/language_config_model.cc index 6d9076f..b10ca2b 100644 --- a/chrome/browser/chromeos/options/language_config_model.cc +++ b/chrome/browser/chromeos/options/language_config_model.cc @@ -8,13 +8,12 @@ #include <functional> #include <utility> -#include "app/l10n_util_collator.h" +#include "app/l10n_util.h" #include "base/utf_string_conversions.h" -#include "chrome/browser/browser_process.h" #include "chrome/browser/chromeos/cros/cros_library.h" #include "chrome/browser/chromeos/cros/language_library.h" +#include "chrome/browser/chromeos/input_method/input_method_util.h" #include "chrome/browser/chromeos/preferences.h" -#include "chrome/browser/chromeos/status/language_menu_l10n_util.h" #include "chrome/common/notification_type.h" #include "chrome/common/pref_names.h" @@ -26,34 +25,6 @@ namespace { // defined in app/l10_util.cc. const char kDefaultLanguageCode[] = "en-US"; -// The list of language that do not have associated input methods. For -// these languages, we associate input methods here. -const struct ExtraLanguage { - const char* language_code; - const char* input_method_id; -} kExtraLanguages[] = { - { "id", "xkb:us::eng" }, // For Indonesian, use US keyboard layout. - // The code "fil" comes from app/l10_util.cc. - { "fil", "xkb:us::eng" }, // For Filipino, use US keyboard layout. - // The code "es-419" comes from app/l10_util.cc. - // For Spanish in Latin America, use Spanish keyboard layout. - { "es-419", "xkb:es::spa" }, -}; - -// The list defines pairs of language code and the default input method -// id. The list is used for reordering input method ids. -// -// TODO(satorux): We may need to handle secondary, and ternary input -// methods, rather than handling the default input method only. -const struct LanguageDefaultInputMethodId { - const char* language_code; - const char* input_method_id; -} kLanguageDefaultInputMethodIds[] = { - { "en-US", "xkb:us::eng", }, // US - English - { "fr", "xkb:fr::fra", }, // France - French - { "de", "xkb:de::ger", }, // Germany - German -}; - } // namespace AddLanguageComboboxModel::AddLanguageComboboxModel( @@ -73,7 +44,7 @@ std::wstring AddLanguageComboboxModel::GetItemAt(int index) { return l10n_util::GetString( IDS_OPTIONS_SETTINGS_LANGUAGES_ADD_LANGUAGE_COMBOBOX); } - return LanguageConfigModel::MaybeRewriteLanguageName( + return input_method::MaybeRewriteLanguageName( GetLanguageNameAt(GetLanguageIndex(index))); } @@ -127,12 +98,11 @@ void LanguageConfigModel::Init() { size_t LanguageConfigModel::CountNumActiveInputMethods( const std::string& language_code) { int num_selected_active_input_methods = 0; - std::pair<LanguageCodeToIdsMap::const_iterator, - LanguageCodeToIdsMap::const_iterator> range = - language_code_to_ids_map_.equal_range(language_code); - for (LanguageCodeToIdsMap::const_iterator iter = range.first; - iter != range.second; ++iter) { - if (InputMethodIsActivated(iter->second)) { + std::vector<std::string> input_method_ids; + input_method::GetInputMethodIdsByLanguageCode( + language_code, false /* keyboard_layout_only */, &input_method_ids); + for (size_t i = 0; i < input_method_ids.size(); ++i) { + if (InputMethodIsActivated(input_method_ids[i])) { ++num_selected_active_input_methods; } } @@ -153,7 +123,7 @@ size_t LanguageConfigModel::AddLanguageCode( // acceptable as the language list is about 40 item long at most. In // theory, we could find the position to insert rather than sorting, but // it would be complex as we need to use unicode string comparator. - SortLanguageCodesByNames(&preferred_language_codes_); + input_method::SortLanguageCodesByNames(&preferred_language_codes_); // Find the language code just added in the sorted language codes. const int added_at = std::distance(preferred_language_codes_.begin(), @@ -173,7 +143,8 @@ void LanguageConfigModel::UpdateInputMethodPreferences( // Note: Since |new_input_method_ids| is alphabetically sorted and the sort // function below uses stable sort, the relateve order of input methods that // belong to the same language (e.g. "mozc" and "xkb:jp::jpn") is maintained. - SortInputMethodIdsByNames(id_to_language_code_map_, &new_input_method_ids); + input_method::SortInputMethodIdsByNames( + id_to_language_code_map_, &new_input_method_ids); preload_engines_.SetValue(UTF8ToWide(JoinString(new_input_method_ids, ','))); } @@ -256,16 +227,12 @@ void LanguageConfigModel::GetInputMethodIdsFromLanguageCode( std::vector<std::string>* input_method_ids) const { DCHECK(input_method_ids); input_method_ids->clear(); + input_method::GetInputMethodIdsByLanguageCode( + language_code, false /* keyboard_layout_only */, input_method_ids); - std::pair<LanguageCodeToIdsMap::const_iterator, - LanguageCodeToIdsMap::const_iterator> range = - language_code_to_ids_map_.equal_range(language_code); - for (LanguageCodeToIdsMap::const_iterator iter = range.first; - iter != range.second; ++iter) { - input_method_ids->push_back(iter->second); - } // Reorder the input methods. - ReorderInputMethodIdsForLanguageCode(language_code, input_method_ids); + input_method::ReorderInputMethodIdsForLanguageCode( + language_code, input_method_ids); } void LanguageConfigModel::NotifyPrefChanged() { @@ -282,7 +249,7 @@ void LanguageConfigModel::NotifyPrefChanged() { preferred_language_codes_.clear(); preferred_language_codes_.assign( language_code_set.begin(), language_code_set.end()); - LanguageConfigModel::SortLanguageCodesByNames(&preferred_language_codes_); + input_method::SortLanguageCodesByNames(&preferred_language_codes_); } void LanguageConfigModel::Observe(NotificationType type, @@ -293,129 +260,6 @@ void LanguageConfigModel::Observe(NotificationType type, } } -std::wstring LanguageConfigModel::MaybeRewriteLanguageName( - const std::wstring& language_name) { - // "t" is used as the language code for input methods that don't fall - // under any other languages. - if (language_name == L"t") { - return l10n_util::GetString( - IDS_OPTIONS_SETTINGS_LANGUAGES_OTHERS); - } - return language_name; -} - -std::wstring LanguageConfigModel::GetLanguageDisplayNameFromCode( - const std::string& language_code) { - return MaybeRewriteLanguageName(UTF16ToWide( - l10n_util::GetDisplayNameForLocale( - language_code, g_browser_process->GetApplicationLocale(), - true))); -} - -namespace { - -// The comparator is used for sorting language codes by their -// corresponding language names, using the ICU collator. -struct CompareLanguageCodesByLanguageName - : std::binary_function<const std::string&, const std::string&, bool> { - explicit CompareLanguageCodesByLanguageName(icu::Collator* collator) - : collator_(collator) { - } - - // Calling GetLanguageDisplayNameFromCode() in the comparator is not - // efficient, but acceptable as the function is cheap, and the language - // list is short (about 40 at most). - bool operator()(const std::string& s1, const std::string& s2) const { - const std::wstring key1 = - LanguageConfigModel::GetLanguageDisplayNameFromCode(s1); - const std::wstring key2 = - LanguageConfigModel::GetLanguageDisplayNameFromCode(s2); - return l10n_util::StringComparator<std::wstring>(collator_)(key1, key2); - } - - icu::Collator* collator_; -}; - -// The comparator is used for sorting input method ids by their -// corresponding language names, using the ICU collator. -struct CompareInputMethodIdsByLanguageName - : std::binary_function<const std::string&, const std::string&, bool> { - CompareInputMethodIdsByLanguageName( - icu::Collator* collator, - const std::map<std::string, std::string>& id_to_language_code_map) - : comparator_(collator), - id_to_language_code_map_(id_to_language_code_map) { - } - - bool operator()(const std::string& s1, const std::string& s2) const { - std::string language_code_1; - std::map<std::string, std::string>::const_iterator iter = - id_to_language_code_map_.find(s1); - if (iter != id_to_language_code_map_.end()) { - language_code_1 = iter->second; - } - std::string language_code_2; - iter = id_to_language_code_map_.find(s2); - if (iter != id_to_language_code_map_.end()) { - language_code_2 = iter->second; - } - return comparator_(language_code_1, language_code_2); - } - - const CompareLanguageCodesByLanguageName comparator_; - const std::map<std::string, std::string>& id_to_language_code_map_; -}; - -} // namespace - -void LanguageConfigModel::SortLanguageCodesByNames( - std::vector<std::string>* language_codes) { - // We should build collator outside of the comparator. We cannot have - // scoped_ptr<> in the comparator for a subtle STL reason. - UErrorCode error = U_ZERO_ERROR; - icu::Locale locale(g_browser_process->GetApplicationLocale().c_str()); - scoped_ptr<icu::Collator> collator( - icu::Collator::createInstance(locale, error)); - if (U_FAILURE(error)) { - collator.reset(); - } - std::sort(language_codes->begin(), language_codes->end(), - CompareLanguageCodesByLanguageName(collator.get())); -} - -void LanguageConfigModel::SortInputMethodIdsByNames( - const std::map<std::string, std::string>& id_to_language_code_map, - std::vector<std::string>* input_method_ids) { - UErrorCode error = U_ZERO_ERROR; - icu::Locale locale(g_browser_process->GetApplicationLocale().c_str()); - scoped_ptr<icu::Collator> collator( - icu::Collator::createInstance(locale, error)); - if (U_FAILURE(error)) { - collator.reset(); - } - std::stable_sort(input_method_ids->begin(), input_method_ids->end(), - CompareInputMethodIdsByLanguageName( - collator.get(), id_to_language_code_map)); -} - -void LanguageConfigModel::ReorderInputMethodIdsForLanguageCode( - const std::string& language_code, - std::vector<std::string>* input_method_ids) { - for (size_t i = 0; i < arraysize(kLanguageDefaultInputMethodIds); ++i) { - if (language_code == kLanguageDefaultInputMethodIds[i].language_code) { - std::vector<std::string>::iterator iter = - std::find(input_method_ids->begin(), input_method_ids->end(), - kLanguageDefaultInputMethodIds[i].input_method_id); - // If it's not on the top of |input_method_id|, swap it with the top one. - if (iter != input_method_ids->end() && - iter != input_method_ids->begin()) { - std::swap(*input_method_ids->begin(), *iter); - } - break; // Don't have to check other language codes. - } - } -} - void LanguageConfigModel::InitInputMethodIdMapsAndVectors() { // The two sets are used to build lists without duplication. std::set<std::string> supported_language_code_set; @@ -429,7 +273,7 @@ void LanguageConfigModel::InitInputMethodIdMapsAndVectors() { for (size_t i = 0; i < supported_input_methods->size(); ++i) { const InputMethodDescriptor& input_method = supported_input_methods->at(i); const std::string language_code = - InputMethodLibrary::GetLanguageCodeFromDescriptor(input_method); + input_method::GetLanguageCodeFromDescriptor(input_method); AddInputMethodToMaps(language_code, input_method); // Add the language code and the input method id to the sets. supported_language_code_set.insert(language_code); @@ -440,9 +284,10 @@ void LanguageConfigModel::InitInputMethodIdMapsAndVectors() { } // Go through the languages listed in kExtraLanguages. - for (size_t i = 0; i < arraysize(kExtraLanguages); ++i) { - const char* language_code = kExtraLanguages[i].language_code; - const char* input_method_id = kExtraLanguages[i].input_method_id; + for (size_t i = 0; i < arraysize(input_method::kExtraLanguages); ++i) { + const char* language_code = input_method::kExtraLanguages[i].language_code; + const char* input_method_id = + input_method::kExtraLanguages[i].input_method_id; std::map<std::string, const InputMethodDescriptor*>::const_iterator iter = id_to_descriptor_map.find(input_method_id); // If the associated input method descriptor is found, add the @@ -469,10 +314,8 @@ void LanguageConfigModel::AddInputMethodToMaps( id_to_language_code_map_.insert( std::make_pair(input_method.id, language_code)); id_to_display_name_map_.insert( - std::make_pair(input_method.id, LanguageMenuL10nUtil::GetStringUTF8( - input_method.display_name))); - language_code_to_ids_map_.insert( - std::make_pair(language_code, input_method.id)); + std::make_pair(input_method.id, + input_method::GetStringUTF8(input_method.display_name))); } } // namespace chromeos diff --git a/chrome/browser/chromeos/options/language_config_model.h b/chrome/browser/chromeos/options/language_config_model.h index a0440d4..cb01b65 100644 --- a/chrome/browser/chromeos/options/language_config_model.h +++ b/chrome/browser/chromeos/options/language_config_model.h @@ -132,41 +132,6 @@ class LanguageConfigModel : public NotificationObserver { return supported_language_codes_; } - // Rewrites the language name and returns the modified version if - // necessary. Otherwise, returns the given language name as is. - // In particular, this rewrites the special language name used for input - // methods that don't fall under any other languages. - static std::wstring MaybeRewriteLanguageName( - const std::wstring& language_name); - - // Converts a language code to a language display name, using the - // current application locale. MaybeRewriteLanguageName() is called - // internally. - // Examples: "fr" => "French" - // "en-US" => "English (United States)" - static std::wstring GetLanguageDisplayNameFromCode( - const std::string& language_code); - - // Sorts the given language codes by their corresponding language names, - // using the unicode string comparator. Uses unstable sorting. - static void SortLanguageCodesByNames( - std::vector<std::string>* language_codes); - - // Sorts the given input method ids by their corresponding language names, - // using the unicode string comparator. Uses stable sorting. - static void SortInputMethodIdsByNames( - const std::map<std::string, std::string>& id_to_language_code_map, - std::vector<std::string>* input_method_ids); - - // Reorders the given input method ids for the language code. For - // example, if |language_codes| is "fr" and |input_method_ids| contains - // ["xkb:be::fra", and "xkb:fr::fra"], the list is reordered to - // ["xkb:fr::fra", and "xkb:be::fra"], so that French keyboard layout - // comes before Belgian keyboard layout. - static void ReorderInputMethodIdsForLanguageCode( - const std::string& language_code, - std::vector<std::string>* input_method_ids); - private: // Initializes id_to_{code,display_name}_map_ maps, // as well as supported_{language_codes,input_method_ids}_ vectors. @@ -186,9 +151,6 @@ class LanguageConfigModel : public NotificationObserver { std::vector<std::string> supported_language_codes_; // List of supported IME IDs like "pinyin" and "m17n:ar:kbd". std::vector<std::string> supported_input_method_ids_; - // Map from language code to associated input method IDs. - typedef std::multimap<std::string, std::string> LanguageCodeToIdsMap; - LanguageCodeToIdsMap language_code_to_ids_map_; DISALLOW_COPY_AND_ASSIGN(LanguageConfigModel); }; diff --git a/chrome/browser/chromeos/options/language_config_model_unittest.cc b/chrome/browser/chromeos/options/language_config_model_unittest.cc index 758488d..e9b593d 100644 --- a/chrome/browser/chromeos/options/language_config_model_unittest.cc +++ b/chrome/browser/chromeos/options/language_config_model_unittest.cc @@ -15,148 +15,6 @@ namespace chromeos { -TEST(LanguageConfigModelTest, MaybeRewriteLanguageName) { - EXPECT_EQ(L"English", - LanguageConfigModel::MaybeRewriteLanguageName(L"English")); - EXPECT_EQ(l10n_util::GetString(IDS_OPTIONS_SETTINGS_LANGUAGES_OTHERS), - LanguageConfigModel::MaybeRewriteLanguageName(L"t")); -} - -TEST(LanguageConfigModelTest, GetLanguageDisplayNameFromCode) { - EXPECT_EQ(L"French", - LanguageConfigModel::GetLanguageDisplayNameFromCode("fr")); - // MaybeRewriteLanguageName() should be applied. - EXPECT_EQ(l10n_util::GetString(IDS_OPTIONS_SETTINGS_LANGUAGES_OTHERS), - LanguageConfigModel::GetLanguageDisplayNameFromCode("t")); -} - -TEST(LanguageConfigModelTest, SortLanguageCodesByNames) { - std::vector<std::string> language_codes; - // Check if this function can handle an empty list. - LanguageConfigModel::SortLanguageCodesByNames(&language_codes); - - language_codes.push_back("ja"); - language_codes.push_back("fr"); - language_codes.push_back("t"); - LanguageConfigModel::SortLanguageCodesByNames(&language_codes); - ASSERT_EQ(3, static_cast<int>(language_codes.size())); - ASSERT_EQ("fr", language_codes[0]); // French - ASSERT_EQ("ja", language_codes[1]); // Japanese - ASSERT_EQ("t", language_codes[2]); // Others - - // Add a duplicate entry and see if it works. - language_codes.push_back("ja"); - LanguageConfigModel::SortLanguageCodesByNames(&language_codes); - ASSERT_EQ(4, static_cast<int>(language_codes.size())); - ASSERT_EQ("fr", language_codes[0]); // French - ASSERT_EQ("ja", language_codes[1]); // Japanese - ASSERT_EQ("ja", language_codes[2]); // Japanese - ASSERT_EQ("t", language_codes[3]); // Others -} - -TEST(LanguageConfigModelTest, SortInputMethodIdsByNames) { - std::map<std::string, std::string> id_to_language_code_map; - id_to_language_code_map.insert(std::make_pair("mozc", "ja")); - id_to_language_code_map.insert(std::make_pair("mozc-jp", "ja")); - id_to_language_code_map.insert(std::make_pair("xkb:jp::jpn", "ja")); - id_to_language_code_map.insert(std::make_pair("xkb:fr::fra", "fr")); - id_to_language_code_map.insert(std::make_pair("m17n:latn-pre", "t")); - - std::vector<std::string> input_method_ids; - // Check if this function can handle an empty list. - LanguageConfigModel::SortInputMethodIdsByNames(id_to_language_code_map, - &input_method_ids); - - input_method_ids.push_back("mozc"); // Japanese - input_method_ids.push_back("xkb:fr::fra"); // French - input_method_ids.push_back("m17n:latn-pre"); // Others - LanguageConfigModel::SortInputMethodIdsByNames(id_to_language_code_map, - &input_method_ids); - ASSERT_EQ(3, static_cast<int>(input_method_ids.size())); - ASSERT_EQ("xkb:fr::fra", input_method_ids[0]); // French - ASSERT_EQ("mozc", input_method_ids[1]); // Japanese - ASSERT_EQ("m17n:latn-pre", input_method_ids[2]); // Others - - // Add a duplicate entry and see if it works. - // Note that SortInputMethodIdsByNames uses std::stable_sort. - input_method_ids.push_back("xkb:jp::jpn"); // also Japanese - LanguageConfigModel::SortInputMethodIdsByNames(id_to_language_code_map, - &input_method_ids); - ASSERT_EQ(4, static_cast<int>(input_method_ids.size())); - ASSERT_EQ("xkb:fr::fra", input_method_ids[0]); // French - ASSERT_EQ("mozc", input_method_ids[1]); // Japanese - ASSERT_EQ("xkb:jp::jpn", input_method_ids[2]); // Japanese - ASSERT_EQ("m17n:latn-pre", input_method_ids[3]); // Others - - input_method_ids.push_back("mozc-jp"); // also Japanese - LanguageConfigModel::SortInputMethodIdsByNames(id_to_language_code_map, - &input_method_ids); - ASSERT_EQ(5, static_cast<int>(input_method_ids.size())); - ASSERT_EQ("xkb:fr::fra", input_method_ids[0]); // French - ASSERT_EQ("mozc", input_method_ids[1]); // Japanese - ASSERT_EQ("xkb:jp::jpn", input_method_ids[2]); // Japanese - ASSERT_EQ("mozc-jp", input_method_ids[3]); // Japanese - ASSERT_EQ("m17n:latn-pre", input_method_ids[4]); // Others -} - -TEST(LanguageConfigModelTest, ReorderInputMethodIdsForLanguageCode_DE) { - std::vector<std::string> input_method_ids; - input_method_ids.push_back("xkb:ch::ger"); // Switzerland - German - input_method_ids.push_back("xkb:de::ger"); // Germany - German - LanguageConfigModel::ReorderInputMethodIdsForLanguageCode( - "de", &input_method_ids); - // The list should be reordered. - ASSERT_EQ(2, static_cast<int>(input_method_ids.size())); - EXPECT_EQ("xkb:de::ger", input_method_ids[0]); - EXPECT_EQ("xkb:ch::ger", input_method_ids[1]); -} - -TEST(LanguageConfigModelTest, ReorderInputMethodIdsForLanguageCode_FR) { - std::vector<std::string> input_method_ids; - input_method_ids.push_back("xkb:be::fra"); // Belgium - French - input_method_ids.push_back("xkb:fr::fra"); // France - French - LanguageConfigModel::ReorderInputMethodIdsForLanguageCode( - "fr", &input_method_ids); - // The list should be reordered. - ASSERT_EQ(2, static_cast<int>(input_method_ids.size())); - EXPECT_EQ("xkb:fr::fra", input_method_ids[0]); - EXPECT_EQ("xkb:be::fra", input_method_ids[1]); -} - -TEST(LanguageConfigModelTest, ReorderInputMethodIdsForLanguageCode_EN_US) { - std::vector<std::string> input_method_ids; - input_method_ids.push_back("xkb:us:dvorak:eng"); // US - Dvorak - English - input_method_ids.push_back("xkb:us::eng"); // US - English - LanguageConfigModel::ReorderInputMethodIdsForLanguageCode( - "en-US", &input_method_ids); - // The list should be reordered. - ASSERT_EQ(2, static_cast<int>(input_method_ids.size())); - EXPECT_EQ("xkb:us::eng", input_method_ids[0]); - EXPECT_EQ("xkb:us:dvorak:eng", input_method_ids[1]); -} - -TEST(LanguageConfigModelTest, ReorderInputMethodIdsForLanguageCode_FI) { - std::vector<std::string> input_method_ids; - input_method_ids.push_back("xkb:fi::fin"); // Finland - Finnish - LanguageConfigModel::ReorderInputMethodIdsForLanguageCode( - "fi", &input_method_ids); - // There is no rule for reordering for Finnish. - ASSERT_EQ(1, static_cast<int>(input_method_ids.size())); - EXPECT_EQ("xkb:fi::fin", input_method_ids[0]); -} - -TEST(LanguageConfigModelTest, ReorderInputMethodIdsForLanguageCode_Noop) { - std::vector<std::string> input_method_ids; - input_method_ids.push_back("xkb:fr::fra"); // France - French - input_method_ids.push_back("xkb:be::fra"); // Belgium - French - // If the list is already sorted, nothing should happen. - LanguageConfigModel::ReorderInputMethodIdsForLanguageCode( - "fr", &input_method_ids); - ASSERT_EQ(2, static_cast<int>(input_method_ids.size())); - EXPECT_EQ("xkb:fr::fra", input_method_ids[0]); - EXPECT_EQ("xkb:be::fra", input_method_ids[1]); -} - TEST(AddLanguageComboboxModelTest, AddLanguageComboboxModel) { std::vector<std::string> language_codes; language_codes.push_back("de"); diff --git a/chrome/browser/chromeos/options/language_config_view.cc b/chrome/browser/chromeos/options/language_config_view.cc index fddf73a..e4cb32c 100644 --- a/chrome/browser/chromeos/options/language_config_view.cc +++ b/chrome/browser/chromeos/options/language_config_view.cc @@ -9,6 +9,7 @@ #include "app/l10n_util.h" #include "base/utf_string_conversions.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/chromeos/input_method/input_method_util.h" #include "chrome/browser/chromeos/options/language_chewing_config_view.h" #include "chrome/browser/chromeos/options/language_hangul_config_view.h" #include "chrome/browser/chromeos/options/language_mozc_config_view.h" @@ -238,8 +239,8 @@ void LanguageConfigView::OnSelectionChanged() { std::wstring LanguageConfigView::GetText(int row, int column_id) { if (row >= 0 && row < static_cast<int>( model.num_preferred_language_codes())) { - return LanguageConfigModel:: - GetLanguageDisplayNameFromCode(model.preferred_language_code_at(row)); + return input_method::GetLanguageDisplayNameFromCode( + model.preferred_language_code_at(row)); } NOTREACHED(); return L""; @@ -523,8 +524,7 @@ void LanguageConfigView::AddUiLanguageSection(const std::string& language_code, const string16 language_name16 = l10n_util::GetDisplayNameForLocale( language_code, application_locale, true); const std::wstring language_name - = LanguageConfigModel::MaybeRewriteLanguageName( - UTF16ToWide(language_name16)); + = input_method::MaybeRewriteLanguageName(UTF16ToWide(language_name16)); views::Label* language_name_label = new views::Label(language_name); language_name_label->SetFont( language_name_label->font().DeriveFont(0, gfx::Font::BOLD)); diff --git a/chrome/browser/chromeos/status/language_menu_button.cc b/chrome/browser/chromeos/status/language_menu_button.cc index 8a22ccc..7265c70 100644 --- a/chrome/browser/chromeos/status/language_menu_button.cc +++ b/chrome/browser/chromeos/status/language_menu_button.cc @@ -13,7 +13,7 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/chromeos/cros/cros_library.h" #include "chrome/browser/chromeos/cros/keyboard_library.h" -#include "chrome/browser/chromeos/status/language_menu_l10n_util.h" +#include "chrome/browser/chromeos/input_method/input_method_util.h" #include "chrome/browser/chromeos/status/status_area_host.h" #include "chrome/browser/metrics/user_metrics.h" #include "chrome/browser/profile.h" @@ -303,7 +303,7 @@ string16 LanguageMenuButton::GetLabelAt(int index) const { std::wstring name; if (IndexIsInInputMethodList(index)) { const std::string language_code = - InputMethodLibrary::GetLanguageCodeFromDescriptor( + input_method::GetLanguageCodeFromDescriptor( input_method_descriptors_->at(index)); bool need_method_name = (need_method_name_.count(language_code) > 0); name = GetTextForMenu(input_method_descriptors_->at(index), @@ -311,8 +311,7 @@ string16 LanguageMenuButton::GetLabelAt(int index) const { } else if (GetPropertyIndex(index, &index)) { const ImePropertyList& property_list = CrosLibrary::Get()->GetInputMethodLibrary()->current_ime_properties(); - return LanguageMenuL10nUtil::GetStringUTF16( - property_list.at(index).label); + return input_method::GetStringUTF16(property_list.at(index).label); } return WideToUTF16(name); @@ -432,7 +431,7 @@ void LanguageMenuButton::UpdateIndicator( scoped_ptr<InputMethodDescriptors> active_input_methods( CrosLibrary::Get()->GetInputMethodLibrary()->GetActiveInputMethods()); if (active_input_methods->size() == 1 && - InputMethodLibrary::IsKeyboardLayout(active_input_methods->at(0).id)) { + input_method::IsKeyboardLayout(active_input_methods->at(0).id)) { // As the disabled color is set to invisible, disabling makes the // button disappear. SetEnabled(false); @@ -468,7 +467,7 @@ void LanguageMenuButton::RebuildModel() { model_->AddRadioItem(COMMAND_ID_INPUT_METHODS, dummy_label, i); const std::string language_code - = InputMethodLibrary::GetLanguageCodeFromDescriptor( + = input_method::GetLanguageCodeFromDescriptor( input_method_descriptors_->at(i)); // If there is more than one input method for this language, then we need // to display the method name. @@ -570,7 +569,7 @@ std::wstring LanguageMenuButton::GetTextForIndicator( if (text.empty()) { const size_t kMaxLanguageNameLen = 2; const std::wstring language_code = UTF8ToWide( - InputMethodLibrary::GetLanguageCodeFromDescriptor(input_method)); + input_method::GetLanguageCodeFromDescriptor(input_method)); text = StringToUpperASCII(language_code).substr(0, kMaxLanguageNameLen); } DCHECK(!text.empty()); @@ -580,7 +579,7 @@ std::wstring LanguageMenuButton::GetTextForIndicator( std::wstring LanguageMenuButton::GetTextForMenu( const InputMethodDescriptor& input_method, bool add_method_name) { const std::string language_code - = InputMethodLibrary::GetLanguageCodeFromDescriptor(input_method); + = input_method::GetLanguageCodeFromDescriptor(input_method); std::wstring text; if (language_code == "t") { @@ -594,7 +593,7 @@ std::wstring LanguageMenuButton::GetTextForMenu( text = GetLanguageName(language_code); if (add_method_name) { text += L" - "; - text += LanguageMenuL10nUtil::GetString(input_method.display_name); + text += input_method::GetString(input_method.display_name); } } DCHECK(!text.empty()); diff --git a/chrome/browser/chromeos/status/language_menu_l10n_util.cc b/chrome/browser/chromeos/status/language_menu_l10n_util.cc deleted file mode 100644 index 711e461..0000000 --- a/chrome/browser/chromeos/status/language_menu_l10n_util.cc +++ /dev/null @@ -1,188 +0,0 @@ -// Copyright (c) 2010 The Chromium 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 "chrome/browser/chromeos/status/language_menu_l10n_util.h" - -#include "base/hash_tables.h" -#include "base/utf_string_conversions.h" -#include "chrome/browser/chrome_thread.h" -#include "grit/generated_resources.h" - -namespace { - -const struct EnglishToResouceId { - const char* english_string_from_ibus; - int resource_id; -} kEnglishToResourceIdArray[] = { - // For ibus-mozc: third_party/ibus-mozc/files/src/unix/ibus/. - { "Direct input", IDS_STATUSBAR_IME_JAPANESE_IME_STATUS_DIRECT_INPUT }, - { "Hiragana", IDS_STATUSBAR_IME_JAPANESE_IME_STATUS_HIRAGANA }, - { "Katakana", IDS_STATUSBAR_IME_JAPANESE_IME_STATUS_KATAKANA }, - { "Half width katakana", // small k is not a typo. - IDS_STATUSBAR_IME_JAPANESE_IME_STATUS_HALF_WIDTH_KATAKANA }, - { "Latin", IDS_STATUSBAR_IME_JAPANESE_IME_STATUS_LATIN }, - { "Wide Latin", IDS_STATUSBAR_IME_JAPANESE_IME_STATUS_WIDE_LATIN }, - - // For ibus-hangul: third_party/ibus-hangul/files/po/. - { "Enable/Disable Hanja mode", IDS_STATUSBAR_IME_KOREAN_HANJA_MODE }, - - // For ibus-pinyin: third_party/ibus-pinyin/files/po/. - { "Chinese", IDS_STATUSBAR_IME_CHINESE_PINYIN_TOGGLE_CHINESE_ENGLISH }, - { "Full/Half width", - IDS_STATUSBAR_IME_CHINESE_PINYIN_TOGGLE_FULL_HALF }, - { "Full/Half width punctuation", - IDS_STATUSBAR_IME_CHINESE_PINYIN_TOGGLE_FULL_HALF_PUNCTUATION }, - { "Simplfied/Traditional Chinese", - IDS_STATUSBAR_IME_CHINESE_PINYIN_TOGGLE_S_T_CHINESE }, - - // TODO(yusukes): Support ibus-chewing and ibus-table-* if needed. - - // For the "Languages and Input" dialog. - { "kbd (m17n)", IDS_OPTIONS_SETTINGS_LANGUAGES_M17N_STANDARD_INPUT_METHOD }, - { "itrans (m17n)", // also uses the "STANDARD_INPUT_METHOD" id. - IDS_OPTIONS_SETTINGS_LANGUAGES_M17N_STANDARD_INPUT_METHOD }, - { "cangjie (m17n)", - IDS_OPTIONS_SETTINGS_LANGUAGES_M17N_CHINESE_CANGJIE_INPUT_METHOD }, - { "quick (m17n)", - IDS_OPTIONS_SETTINGS_LANGUAGES_M17N_CHINESE_QUICK_INPUT_METHOD }, - { "isiri (m17n)", - IDS_OPTIONS_SETTINGS_LANGUAGES_M17N_PERSIAN_ISIRI_2901_INPUT_METHOD }, - { "kesmanee (m17n)", - IDS_OPTIONS_SETTINGS_LANGUAGES_M17N_THAI_KESMANEE_INPUT_METHOD }, - { "tis820 (m17n)", - IDS_OPTIONS_SETTINGS_LANGUAGES_M17N_THAI_TIS820_INPUT_METHOD }, - { "pattachote (m17n)", - IDS_OPTIONS_SETTINGS_LANGUAGES_M17N_THAI_PATTACHOTE_INPUT_METHOD }, - { "tcvn (m17n)", - IDS_OPTIONS_SETTINGS_LANGUAGES_M17N_VIETNAMESE_TCVN_INPUT_METHOD }, - { "telex (m17n)", - IDS_OPTIONS_SETTINGS_LANGUAGES_M17N_VIETNAMESE_TELEX_INPUT_METHOD }, - { "viqr (m17n)", - IDS_OPTIONS_SETTINGS_LANGUAGES_M17N_VIETNAMESE_VIQR_INPUT_METHOD }, - { "vni (m17n)", - IDS_OPTIONS_SETTINGS_LANGUAGES_M17N_VIETNAMESE_VNI_INPUT_METHOD }, - { "latn-post (m17n)", - IDS_OPTIONS_SETTINGS_LANGUAGES_M17N_LATIN_POST_INPUT_METHOD }, - { "latn-pre (m17n)", - IDS_OPTIONS_SETTINGS_LANGUAGES_M17N_LATIN_PRE_INPUT_METHOD }, - { "Bopomofo", IDS_OPTIONS_SETTINGS_LANGUAGES_BOPOMOFO_INPUT_METHOD }, - { "Chewing", IDS_OPTIONS_SETTINGS_LANGUAGES_CHEWING_INPUT_METHOD }, - { "Pinyin", IDS_OPTIONS_SETTINGS_LANGUAGES_PINYIN_INPUT_METHOD }, - { "Mozc (US keyboard layout)", - IDS_OPTIONS_SETTINGS_LANGUAGES_JAPANESE_MOZC_US_INPUT_METHOD }, - { "Mozc (Japanese keyboard layout)", - IDS_OPTIONS_SETTINGS_LANGUAGES_JAPANESE_MOZC_JP_INPUT_METHOD }, - { "Google Japanese Input (US keyboard layout)", - IDS_OPTIONS_SETTINGS_LANGUAGES_JAPANESE_GOOGLE_US_INPUT_METHOD }, - { "Google Japanese Input (Japanese keyboard layout)", - IDS_OPTIONS_SETTINGS_LANGUAGES_JAPANESE_GOOGLE_JP_INPUT_METHOD }, - { "Korean", IDS_OPTIONS_SETTINGS_LANGUAGES_KOREAN_INPUT_METHOD }, - - // For ibus-xkb-layouts engine: third_party/ibus-xkb-layouts/files - { "Japan", IDS_STATUSBAR_LAYOUT_JAPAN }, - { "Slovenia", IDS_STATUSBAR_LAYOUT_SLOVENIA }, - { "Germany", IDS_STATUSBAR_LAYOUT_GERMANY }, - { "Italy", IDS_STATUSBAR_LAYOUT_ITALY }, - { "Estonia", IDS_STATUSBAR_LAYOUT_ESTONIA }, - { "Hungary", IDS_STATUSBAR_LAYOUT_HUNGARY }, - { "Poland", IDS_STATUSBAR_LAYOUT_POLAND }, - { "Denmark", IDS_STATUSBAR_LAYOUT_DENMARK }, - { "Croatia", IDS_STATUSBAR_LAYOUT_CROATIA }, - { "Brazil", IDS_STATUSBAR_LAYOUT_BRAZIL }, - { "Serbia", IDS_STATUSBAR_LAYOUT_SERBIA }, - { "Czechia", IDS_STATUSBAR_LAYOUT_CZECHIA }, - { "USA - Dvorak", IDS_STATUSBAR_LAYOUT_USA_DVORAK }, - { "Romania", IDS_STATUSBAR_LAYOUT_ROMANIA }, - { "USA", IDS_STATUSBAR_LAYOUT_USA }, - { "Lithuania", IDS_STATUSBAR_LAYOUT_LITHUANIA }, - { "United Kingdom", IDS_STATUSBAR_LAYOUT_UNITED_KINGDOM }, - { "Slovakia", IDS_STATUSBAR_LAYOUT_SLOVAKIA }, - { "Russia", IDS_STATUSBAR_LAYOUT_RUSSIA }, - { "Greece", IDS_STATUSBAR_LAYOUT_GREECE }, - { "Belgium", IDS_STATUSBAR_LAYOUT_BELGIUM }, - { "Bulgaria", IDS_STATUSBAR_LAYOUT_BULGARIA }, - { "Switzerland", IDS_STATUSBAR_LAYOUT_SWITZERLAND }, - { "Turkey", IDS_STATUSBAR_LAYOUT_TURKEY }, - { "Portugal", IDS_STATUSBAR_LAYOUT_PORTUGAL }, - { "Spain", IDS_STATUSBAR_LAYOUT_SPAIN }, - { "Finland", IDS_STATUSBAR_LAYOUT_FINLAND }, - { "Ukraine", IDS_STATUSBAR_LAYOUT_UKRAINE }, - { "Spain - Catalan variant with middle-dot L", - IDS_STATUSBAR_LAYOUT_SPAIN_CATALAN }, - { "France", IDS_STATUSBAR_LAYOUT_FRANCE }, - { "Norway", IDS_STATUSBAR_LAYOUT_NORWAY }, - { "Sweden", IDS_STATUSBAR_LAYOUT_SWEDEN }, - { "Netherlands", IDS_STATUSBAR_LAYOUT_NETHERLANDS }, - { "Latvia", IDS_STATUSBAR_LAYOUT_LATVIA }, -}; -const size_t kNumEntries = arraysize(kEnglishToResourceIdArray); - -bool GetLocalizedString( - const std::string& english_string, string16 *out_string) { - DCHECK(out_string); - typedef base::hash_map<std::string, int> HashType; - static HashType* english_to_resource_id = NULL; - - // Initialize the map if needed. - if (!english_to_resource_id) { - // We don't free this map. - english_to_resource_id = new HashType(kNumEntries); - for (size_t i = 0; i < kNumEntries; ++i) { - const bool result = english_to_resource_id->insert( - std::make_pair(kEnglishToResourceIdArray[i].english_string_from_ibus, - kEnglishToResourceIdArray[i].resource_id)).second; - DCHECK(result) << "Duplicated string is found: " - << kEnglishToResourceIdArray[i].english_string_from_ibus; - } - } - - HashType::const_iterator iter = english_to_resource_id->find(english_string); - if (iter == english_to_resource_id->end()) { - LOG(ERROR) << "Resouce ID is not found for: " << english_string; - return false; - } - - *out_string = l10n_util::GetStringUTF16(iter->second); - return true; -}; - - -} // namespace - -namespace chromeos { - -std::wstring LanguageMenuL10nUtil::GetString( - const std::string& english_string) { - string16 localized_string; - if (GetLocalizedString(english_string, &localized_string)) { - return UTF16ToWide(localized_string); - } - return UTF8ToWide(english_string); -} - -std::string LanguageMenuL10nUtil::GetStringUTF8( - const std::string& english_string) { - string16 localized_string; - if (GetLocalizedString(english_string, &localized_string)) { - return UTF16ToUTF8(localized_string); - } - return english_string; -} - -string16 LanguageMenuL10nUtil::GetStringUTF16( - const std::string& english_string) { - string16 localized_string; - if (GetLocalizedString(english_string, &localized_string)) { - return localized_string; - } - return UTF8ToUTF16(english_string); -} - -bool LanguageMenuL10nUtil::StringIsSupported( - const std::string& english_string) { - string16 localized_string; - return GetLocalizedString(english_string, &localized_string); -} - -} // namespace chromeos diff --git a/chrome/browser/chromeos/status/language_menu_l10n_util.h b/chrome/browser/chromeos/status/language_menu_l10n_util.h deleted file mode 100644 index be48515..0000000 --- a/chrome/browser/chromeos/status/language_menu_l10n_util.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_CHROMEOS_STATUS_LANGUAGE_MENU_L10N_UTIL_H_ -#define CHROME_BROWSER_CHROMEOS_STATUS_LANGUAGE_MENU_L10N_UTIL_H_ - -#include <string> - -#include "app/l10n_util.h" -#include "base/string16.h" - -namespace chromeos { - -class LanguageMenuL10nUtil { - public: - // Converts a string sent from IBus IME engines, which is written in English, - // into Chrome's string ID, then pulls internationalized resource string from - // the resource bundle and returns it. These functions are not thread-safe. - // Non-UI threads are not allowed to call them. - static std::wstring GetString(const std::string& english_string); - static std::string GetStringUTF8(const std::string& english_string); - static string16 GetStringUTF16(const std::string& english_string); - - // This method is ONLY for unit testing. Returns true if the given string is - // supported (i.e. the string is associated with a resource ID). - static bool StringIsSupported(const std::string& english_string); - - private: - LanguageMenuL10nUtil(); - ~LanguageMenuL10nUtil(); -}; - -} // namespace chromeos - -#endif // CHROME_BROWSER_CHROMEOS_STATUS_LANGUAGE_MENU_L10N_UTIL_H_ diff --git a/chrome/browser/chromeos/status/language_menu_l10n_util_unittest.cc b/chrome/browser/chromeos/status/language_menu_l10n_util_unittest.cc deleted file mode 100644 index 8865cfc..0000000 --- a/chrome/browser/chromeos/status/language_menu_l10n_util_unittest.cc +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2010 The Chromium 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 "chrome/browser/chromeos/status/language_menu_l10n_util.h" - -#include "testing/gtest/include/gtest/gtest.h" - -namespace chromeos { - -TEST(LanguageMenuL10nUtilTest, FindLocalizedStringTest) { - EXPECT_TRUE(LanguageMenuL10nUtil::StringIsSupported("Hiragana")); - EXPECT_TRUE(LanguageMenuL10nUtil::StringIsSupported("Latin")); - EXPECT_TRUE(LanguageMenuL10nUtil::StringIsSupported("Direct input")); - EXPECT_FALSE(LanguageMenuL10nUtil::StringIsSupported( - "####THIS_STRING_IS_NOT_SUPPORTED####")); -} - -} // namespace chromeos |