diff options
Diffstat (limited to 'chrome/browser/views/options/language_combobox_model.cc')
-rw-r--r-- | chrome/browser/views/options/language_combobox_model.cc | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/chrome/browser/views/options/language_combobox_model.cc b/chrome/browser/views/options/language_combobox_model.cc new file mode 100644 index 0000000..7743a8c --- /dev/null +++ b/chrome/browser/views/options/language_combobox_model.cc @@ -0,0 +1,190 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "chrome/browser/views/options/language_combobox_model.h" + +#include "base/string_util.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/user_metrics.h" +#include "chrome/common/pref_service.h" +#include "unicode/uloc.h" + +#include "generated_resources.h" + +/////////////////////////////////////////////////////////////////////////////// +// LanguageComboboxModel used to populate a combobox with native names +// corresponding to the language code (e.g. English (United States) for en-US) +// +LanguageComboboxModel::LanguageComboboxModel() + : profile_(NULL) { + // Enumerate the languages we know about. + const std::vector<std::wstring>& locale_codes = + l10n_util::GetAvailableLocales(); + InitNativeNames(locale_codes); +} + +// Overload using a profile and customized local_codes vector. +LanguageComboboxModel::LanguageComboboxModel( + Profile* profile, const std::vector<std::wstring>& locale_codes) + : profile_(profile) { + InitNativeNames(locale_codes); +} + +void LanguageComboboxModel::InitNativeNames(const std::vector<std::wstring>& + locale_codes) { + const std::string app_locale = WideToASCII( + g_browser_process->GetApplicationLocale()); + for (size_t i = 0; i < locale_codes.size(); ++i) { + std::string locale_code_str = WideToASCII(locale_codes[i]); + const char* locale_code = locale_code_str.c_str(); + + // Internally, we use the language code of zh-CN and zh-TW, but we want the + // display names to be Chinese (Simplified) and Chinese (Traditional). To + // do that, we use zh-hans and zh-hant when using ICU's + // uloc_getDisplayName. + if (locale_code_str == "zh-CN") { + locale_code = "zh-hans"; + } else if (locale_code_str == "zh-TW") { + locale_code = "zh-hant"; + } + + UErrorCode error = U_ZERO_ERROR; + const int buffer_size = 1024; + std::wstring name_local; + int actual_size = uloc_getDisplayName(locale_code, app_locale.c_str(), + WriteInto(&name_local, buffer_size + 1), buffer_size, &error); + DCHECK(U_SUCCESS(error)); + name_local.resize(actual_size); + + std::wstring name_native; + actual_size = uloc_getDisplayName(locale_code, locale_code, + WriteInto(&name_native, buffer_size + 1), buffer_size, &error); + DCHECK(U_SUCCESS(error)); + name_native.resize(actual_size); + + locale_names_.push_back(name_local); + native_names_[name_local] = LocaleData(name_native, locale_codes[i]); + } + + // Sort using locale specific sorter. + l10n_util::SortStrings(g_browser_process->GetApplicationLocale(), + &locale_names_); +} + +// Overridden from ChromeViews::Combobox::Model: +int LanguageComboboxModel::GetItemCount(ChromeViews::ComboBox* source) { + return static_cast<int>(locale_names_.size()); +} + +std::wstring LanguageComboboxModel::GetItemAt(ChromeViews::ComboBox* source, + int index) { + DCHECK(static_cast<int>(locale_names_.size()) > index); + LocaleDataMap::const_iterator it = + native_names_.find(locale_names_[index]); + DCHECK(it != native_names_.end()); + + // If the name is the same in the native language and local language, + // don't show it twice. + if (it->second.native_name == locale_names_[index]) + return it->second.native_name; + + // We must add directionality formatting to both the native name and the + // locale name in order to avoid text rendering problems such as misplaced + // parentheses or languages appearing in the wrong order. + std::wstring locale_name_localized; + std::wstring locale_name; + if (l10n_util::AdjustStringForLocaleDirection(locale_names_[index], + &locale_name_localized)) + locale_name.assign(locale_name_localized); + else + locale_name.assign(locale_names_[index]); + + std::wstring native_name_localized; + std::wstring native_name; + if (l10n_util::AdjustStringForLocaleDirection(it->second.native_name, + &native_name_localized)) + native_name.assign(native_name_localized); + else + native_name.assign(it->second.native_name); + + // We used to have a localizable template here, but none of translators + // changed the format. We also want to switch the order of locale_name + // and native_name without going back to translators. + std::wstring formatted_item; + SStringPrintf(&formatted_item, L"%s - %s", locale_name.c_str(), + native_name.c_str()); + if (l10n_util::GetTextDirection() == l10n_util::RIGHT_TO_LEFT) + // Somehow combo box (even with LAYOUTRTL flag) doesn't get this + // right so we add RTL BDO (U+202E) to set the direction + // explicitly. + formatted_item.insert(0, L"\x202E"); + return formatted_item; +} + +// Return the locale for the given index. E.g., may return pt-BR. +std::wstring LanguageComboboxModel::GetLocaleFromIndex(int index) { + DCHECK(static_cast<int>(locale_names_.size()) > index); + LocaleDataMap::const_iterator it = + native_names_.find(locale_names_[index]); + DCHECK(it != native_names_.end()); + + return it->second.locale_code; +} + +int LanguageComboboxModel::GetIndexFromLocale(const std::wstring& locale) { + for (size_t i = 0; i < locale_names_.size(); ++i) { + LocaleDataMap::const_iterator it = + native_names_.find(locale_names_[i]); + DCHECK(it != native_names_.end()); + if (it->second.locale_code == locale) + return static_cast<int>(i); + } + return -1; +} + +// Returns the index of the language currently specified in the user's +// preference file. Note that it's possible for language A to be picked +// while chrome is currently in language B if the user specified language B +// via --lang. Since --lang is not a persistent setting, it seems that it +// shouldn't be reflected in this combo box. We return -1 if the value in +// the pref doesn't map to a know language (possible if the user edited the +// prefs file manually). +int LanguageComboboxModel::GetSelectedLanguageIndex(const std::wstring& + prefs) { + PrefService* local_state; + if (!profile_) + local_state = g_browser_process->local_state(); + else + local_state = profile_->GetPrefs(); + + DCHECK(local_state); + const std::wstring& current_lang = local_state->GetString(prefs.c_str()); + + return GetIndexFromLocale(current_lang); +} |