• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "base/i18n/rtl.h"
8 #include "base/string_split.h"
9 #include "base/stringprintf.h"
10 #include "base/utf_string_conversions.h"
11 #include "chrome/browser/browser_process.h"
12 #include "chrome/browser/metrics/user_metrics.h"
13 #include "chrome/browser/prefs/pref_service.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "grit/generated_resources.h"
16 #include "ui/base/l10n/l10n_util.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 
LanguageList()24 LanguageList::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 
LanguageList(const std::vector<std::string> & locale_codes)31 LanguageList::LanguageList(
32     const std::vector<std::string>& locale_codes) {
33   InitNativeNames(locale_codes);
34 }
35 
~LanguageList()36 LanguageList::~LanguageList() {}
37 
InitNativeNames(const std::vector<std::string> & locale_codes)38 void 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(name_in_current_ui);
54     native_names_[name_in_current_ui] =
55         LocaleData(name_native, locale_codes[i]);
56   }
57 
58   // Sort using locale specific sorter.
59   l10n_util::SortStrings16(g_browser_process->GetApplicationLocale(),
60                            &locale_names_);
61 }
62 
CopySpecifiedLanguagesUp(const std::string & locale_codes)63 void 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:
get_languages_count() const75 int LanguageList::get_languages_count() const {
76   return static_cast<int>(locale_names_.size());
77 }
78 
GetLanguageNameAt(int index) const79 string16 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   string16 locale_name = locale_names_[index];
94   base::i18n::AdjustStringForLocaleDirection(&locale_name);
95 
96   string16 native_name = it->second.native_name;
97   base::i18n::AdjustStringForLocaleDirection(&native_name);
98 
99   // We used to have a localizable template here, but none of translators
100   // changed the format. We also want to switch the order of locale_name
101   // and native_name without going back to translators.
102   std::string formatted_item;
103   base::SStringPrintf(&formatted_item, "%s - %s",
104                       UTF16ToUTF8(locale_name).c_str(),
105                       UTF16ToUTF8(native_name).c_str());
106   if (base::i18n::IsRTL())
107     // Somehow combo box (even with LAYOUTRTL flag) doesn't get this
108     // right so we add RTL BDO (U+202E) to set the direction
109     // explicitly.
110     formatted_item.insert(0, "\xE2\x80\xAE");  // U+202E = UTF-8 0xE280AE
111   return UTF8ToUTF16(formatted_item);
112 }
113 
114 // Return the locale for the given index.  E.g., may return pt-BR.
GetLocaleFromIndex(int index) const115 std::string LanguageList::GetLocaleFromIndex(int index) const {
116   DCHECK(static_cast<int>(locale_names_.size()) > index);
117   LocaleDataMap::const_iterator it =
118       native_names_.find(locale_names_[index]);
119   DCHECK(it != native_names_.end());
120 
121   return it->second.locale_code;
122 }
123 
GetIndexFromLocale(const std::string & locale) const124 int LanguageList::GetIndexFromLocale(const std::string& locale) const {
125   for (size_t i = 0; i < locale_names_.size(); ++i) {
126     LocaleDataMap::const_iterator it =
127         native_names_.find(locale_names_[i]);
128     DCHECK(it != native_names_.end());
129     if (it->second.locale_code == locale)
130       return static_cast<int>(i);
131   }
132   return -1;
133 }
134 
135 ///////////////////////////////////////////////////////////////////////////////
136 // LanguageComboboxModel used to populate a combobox with native names
137 //
138 
LanguageComboboxModel()139 LanguageComboboxModel::LanguageComboboxModel()
140     : profile_(NULL) {
141 }
142 
LanguageComboboxModel(Profile * profile,const std::vector<std::string> & locale_codes)143 LanguageComboboxModel::LanguageComboboxModel(
144     Profile* profile, const std::vector<std::string>& locale_codes)
145     : LanguageList(locale_codes),
146       profile_(profile) {
147 }
148 
~LanguageComboboxModel()149 LanguageComboboxModel::~LanguageComboboxModel() {}
150 
GetItemCount()151 int LanguageComboboxModel::GetItemCount() {
152   return get_languages_count();
153 }
154 
GetItemAt(int index)155 string16 LanguageComboboxModel::GetItemAt(int index) {
156   return GetLanguageNameAt(index);
157 }
158 
159 // Returns the index of the language currently specified in the user's
160 // preference file.  Note that it's possible for language A to be picked
161 // while chrome is currently in language B if the user specified language B
162 // via --lang.  Since --lang is not a persistent setting, it seems that it
163 // shouldn't be reflected in this combo box.  We return -1 if the value in
164 // the pref doesn't map to a know language (possible if the user edited the
165 // prefs file manually).
GetSelectedLanguageIndex(const std::string & prefs)166 int LanguageComboboxModel::GetSelectedLanguageIndex(const std::string& prefs) {
167   PrefService* local_state;
168   if (!profile_)
169     local_state = g_browser_process->local_state();
170   else
171     local_state = profile_->GetPrefs();
172 
173   DCHECK(local_state);
174   const std::string& current_locale = local_state->GetString(prefs.c_str());
175 
176   return GetIndexFromLocale(current_locale);
177 }
178