language_combobox_model.cc revision 513209b27ff55e2841eac0e4120199c23acce758
1// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/language_combobox_model.h" 6 7#include "app/l10n_util.h" 8#include "base/i18n/rtl.h" 9#include "base/string_split.h" 10#include "base/stringprintf.h" 11#include "base/utf_string_conversions.h" 12#include "chrome/browser/browser_process.h" 13#include "chrome/browser/metrics/user_metrics.h" 14#include "chrome/browser/prefs/pref_service.h" 15#include "chrome/browser/profile.h" 16#include "grit/generated_resources.h" 17#include "unicode/uloc.h" 18 19/////////////////////////////////////////////////////////////////////////////// 20// LanguageList used to enumerate native names corresponding to the 21// language code (e.g. English (United States) for en-US) 22// 23 24LanguageList::LanguageList() { 25 // Enumerate the languages we know about. 26 const std::vector<std::string>& locale_codes = 27 l10n_util::GetAvailableLocales(); 28 InitNativeNames(locale_codes); 29} 30 31LanguageList::LanguageList( 32 const std::vector<std::string>& locale_codes) { 33 InitNativeNames(locale_codes); 34} 35 36LanguageList::~LanguageList() {} 37 38void LanguageList::InitNativeNames( 39 const std::vector<std::string>& locale_codes) { 40 const std::string app_locale = g_browser_process->GetApplicationLocale(); 41 for (size_t i = 0; i < locale_codes.size(); ++i) { 42 std::string locale_code_str = locale_codes[i]; 43 const char* locale_code = locale_codes[i].c_str(); 44 45 // TODO(jungshik): Even though these strings are used for the UI, 46 // the old code does not add an RTL mark for RTL locales. Make sure 47 // that it's ok without that. 48 string16 name_in_current_ui = 49 l10n_util::GetDisplayNameForLocale(locale_code, app_locale, false); 50 string16 name_native = 51 l10n_util::GetDisplayNameForLocale(locale_code, locale_code, false); 52 53 locale_names_.push_back(UTF16ToWideHack(name_in_current_ui)); 54 native_names_[UTF16ToWideHack(name_in_current_ui)] = LocaleData( 55 UTF16ToWideHack(name_native), locale_codes[i]); 56 } 57 58 // Sort using locale specific sorter. 59 l10n_util::SortStrings(g_browser_process->GetApplicationLocale(), 60 &locale_names_); 61} 62 63void LanguageList::CopySpecifiedLanguagesUp(const std::string& locale_codes) { 64 DCHECK(!locale_names_.empty()); 65 std::vector<std::string> locale_codes_vector; 66 base::SplitString(locale_codes, ',', &locale_codes_vector); 67 for (size_t i = 0; i != locale_codes_vector.size(); i++) { 68 const int locale_index = GetIndexFromLocale(locale_codes_vector[i]); 69 CHECK_NE(locale_index, -1); 70 locale_names_.insert(locale_names_.begin(), locale_names_[locale_index]); 71 } 72} 73 74// Overridden from ComboboxModel: 75int LanguageList::get_languages_count() const { 76 return static_cast<int>(locale_names_.size()); 77} 78 79std::wstring LanguageList::GetLanguageNameAt(int index) const { 80 DCHECK(static_cast<int>(locale_names_.size()) > index); 81 LocaleDataMap::const_iterator it = 82 native_names_.find(locale_names_[index]); 83 DCHECK(it != native_names_.end()); 84 85 // If the name is the same in the native language and local language, 86 // don't show it twice. 87 if (it->second.native_name == locale_names_[index]) 88 return it->second.native_name; 89 90 // We must add directionality formatting to both the native name and the 91 // locale name in order to avoid text rendering problems such as misplaced 92 // parentheses or languages appearing in the wrong order. 93 std::wstring locale_name_localized; 94 std::wstring locale_name; 95 if (base::i18n::AdjustStringForLocaleDirection(locale_names_[index], 96 &locale_name_localized)) 97 locale_name.assign(locale_name_localized); 98 else 99 locale_name.assign(locale_names_[index]); 100 101 std::wstring native_name_localized; 102 std::wstring native_name; 103 if (base::i18n::AdjustStringForLocaleDirection(it->second.native_name, 104 &native_name_localized)) 105 native_name.assign(native_name_localized); 106 else 107 native_name.assign(it->second.native_name); 108 109 // We used to have a localizable template here, but none of translators 110 // changed the format. We also want to switch the order of locale_name 111 // and native_name without going back to translators. 112 std::wstring formatted_item; 113 base::SStringPrintf(&formatted_item, L"%ls - %ls", locale_name.c_str(), 114 native_name.c_str()); 115 if (base::i18n::IsRTL()) 116 // Somehow combo box (even with LAYOUTRTL flag) doesn't get this 117 // right so we add RTL BDO (U+202E) to set the direction 118 // explicitly. 119 formatted_item.insert(0, L"\x202E"); 120 return formatted_item; 121} 122 123// Return the locale for the given index. E.g., may return pt-BR. 124std::string LanguageList::GetLocaleFromIndex(int index) const { 125 DCHECK(static_cast<int>(locale_names_.size()) > index); 126 LocaleDataMap::const_iterator it = 127 native_names_.find(locale_names_[index]); 128 DCHECK(it != native_names_.end()); 129 130 return it->second.locale_code; 131} 132 133int LanguageList::GetIndexFromLocale(const std::string& locale) const { 134 for (size_t i = 0; i < locale_names_.size(); ++i) { 135 LocaleDataMap::const_iterator it = 136 native_names_.find(locale_names_[i]); 137 DCHECK(it != native_names_.end()); 138 if (it->second.locale_code == locale) 139 return static_cast<int>(i); 140 } 141 return -1; 142} 143 144/////////////////////////////////////////////////////////////////////////////// 145// LanguageComboboxModel used to populate a combobox with native names 146// 147 148LanguageComboboxModel::LanguageComboboxModel() 149 : profile_(NULL) { 150} 151 152LanguageComboboxModel::LanguageComboboxModel( 153 Profile* profile, const std::vector<std::string>& locale_codes) 154 : LanguageList(locale_codes), 155 profile_(profile) { 156} 157 158LanguageComboboxModel::~LanguageComboboxModel() {} 159 160int LanguageComboboxModel::GetItemCount() { 161 return get_languages_count(); 162} 163 164string16 LanguageComboboxModel::GetItemAt(int index) { 165 return WideToUTF16Hack(GetLanguageNameAt(index)); 166} 167 168// Returns the index of the language currently specified in the user's 169// preference file. Note that it's possible for language A to be picked 170// while chrome is currently in language B if the user specified language B 171// via --lang. Since --lang is not a persistent setting, it seems that it 172// shouldn't be reflected in this combo box. We return -1 if the value in 173// the pref doesn't map to a know language (possible if the user edited the 174// prefs file manually). 175int LanguageComboboxModel::GetSelectedLanguageIndex(const std::string& prefs) { 176 PrefService* local_state; 177 if (!profile_) 178 local_state = g_browser_process->local_state(); 179 else 180 local_state = profile_->GetPrefs(); 181 182 DCHECK(local_state); 183 const std::string& current_locale = local_state->GetString(prefs.c_str()); 184 185 return GetIndexFromLocale(current_locale); 186} 187