1// Copyright (c) 2011 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/chromeos/login/language_list.h"
6
7#include "base/i18n/rtl.h"
8#include "base/strings/string_split.h"
9#include "base/strings/stringprintf.h"
10#include "base/strings/utf_string_conversions.h"
11#include "chrome/browser/browser_process.h"
12#include "ui/base/l10n/l10n_util.h"
13
14namespace chromeos {
15
16LanguageList::LanguageList() {
17  // Enumerate the languages we know about.
18  const std::vector<std::string>& locale_codes =
19      l10n_util::GetAvailableLocales();
20  InitNativeNames(locale_codes);
21}
22
23LanguageList::~LanguageList() {}
24
25base::string16 LanguageList::GetLanguageNameAt(int index) const {
26  DCHECK_LT(index, languages_count());
27  LocaleDataMap::const_iterator locale_data =
28      native_names_.find(locale_names_[index]);
29  DCHECK(locale_data != native_names_.end());
30
31  // If the name is the same in the native language and local language,
32  // don't show it twice.
33  if (locale_data->second.native_name == locale_names_[index])
34    return locale_data->second.native_name;
35
36  // We must add directionality formatting to both the native name and the
37  // locale name in order to avoid text rendering problems such as misplaced
38  // parentheses or languages appearing in the wrong order.
39  base::string16 locale_name = locale_names_[index];
40  base::i18n::AdjustStringForLocaleDirection(&locale_name);
41
42  base::string16 native_name = locale_data->second.native_name;
43  base::i18n::AdjustStringForLocaleDirection(&native_name);
44
45  // We used to have a localizable template here, but none of translators
46  // changed the format. We also want to switch the order of locale_name
47  // and native_name without going back to translators.
48  std::string formatted_item;
49  base::SStringPrintf(&formatted_item, "%s - %s",
50                      base::UTF16ToUTF8(locale_name).c_str(),
51                      base::UTF16ToUTF8(native_name).c_str());
52  if (base::i18n::IsRTL())
53    // Somehow combo box (even with LAYOUTRTL flag) doesn't get this
54    // right so we add RTL BDO (U+202E) to set the direction
55    // explicitly.
56    formatted_item.insert(0, "\xE2\x80\xAE");  // U+202E = UTF-8 0xE280AE
57  return base::UTF8ToUTF16(formatted_item);
58}
59
60std::string LanguageList::GetLocaleFromIndex(int index) const {
61  DCHECK(static_cast<int>(locale_names_.size()) > index);
62  LocaleDataMap::const_iterator locale_data =
63      native_names_.find(locale_names_[index]);
64  DCHECK(locale_data != native_names_.end());
65  return locale_data->second.locale_code;
66}
67
68int LanguageList::GetIndexFromLocale(const std::string& locale) const {
69  for (size_t i = 0; i < locale_names_.size(); ++i) {
70    LocaleDataMap::const_iterator locale_data =
71        native_names_.find(locale_names_[i]);
72    DCHECK(locale_data != native_names_.end());
73    if (locale_data->second.locale_code == locale)
74      return static_cast<int>(i);
75  }
76  return -1;
77}
78
79void LanguageList::CopySpecifiedLanguagesUp(const std::string& locale_codes) {
80  DCHECK(!locale_names_.empty());
81  std::vector<std::string> locale_codes_vector;
82  base::SplitString(locale_codes, ',', &locale_codes_vector);
83  for (size_t i = 0; i != locale_codes_vector.size(); ++i) {
84    const int locale_index = GetIndexFromLocale(locale_codes_vector[i]);
85    CHECK_NE(locale_index, -1);
86    locale_names_.insert(locale_names_.begin(), locale_names_[locale_index]);
87  }
88}
89
90void LanguageList::InitNativeNames(
91    const std::vector<std::string>& locale_codes) {
92  const std::string app_locale = g_browser_process->GetApplicationLocale();
93  for (size_t i = 0; i < locale_codes.size(); ++i) {
94    const char* locale_code = locale_codes[i].c_str();
95
96    // TODO(jungshik): Even though these strings are used for the UI,
97    // the old code does not add an RTL mark for RTL locales. Make sure
98    // that it's ok without that.
99    base::string16 name_in_current_ui =
100        l10n_util::GetDisplayNameForLocale(locale_code, app_locale, false);
101    base::string16 name_native =
102        l10n_util::GetDisplayNameForLocale(locale_code, locale_code, false);
103
104    locale_names_.push_back(name_in_current_ui);
105    native_names_[name_in_current_ui] =
106        LocaleData(name_native, locale_codes[i]);
107  }
108
109  // Sort using locale specific sorter.
110  l10n_util::SortStrings16(g_browser_process->GetApplicationLocale(),
111                           &locale_names_);
112}
113
114}  // namespace chromeos
115