Home | History | Annotate | Download | only in browser
      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 
     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 
     31 LanguageList::LanguageList(
     32     const std::vector<std::string>& locale_codes) {
     33   InitNativeNames(locale_codes);
     34 }
     35 
     36 LanguageList::~LanguageList() {}
     37 
     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 
     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:
     75 int LanguageList::get_languages_count() const {
     76   return static_cast<int>(locale_names_.size());
     77 }
     78 
     79 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.
    115 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 
    124 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 
    139 LanguageComboboxModel::LanguageComboboxModel()
    140     : profile_(NULL) {
    141 }
    142 
    143 LanguageComboboxModel::LanguageComboboxModel(
    144     Profile* profile, const std::vector<std::string>& locale_codes)
    145     : LanguageList(locale_codes),
    146       profile_(profile) {
    147 }
    148 
    149 LanguageComboboxModel::~LanguageComboboxModel() {}
    150 
    151 int LanguageComboboxModel::GetItemCount() {
    152   return get_languages_count();
    153 }
    154 
    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).
    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