diff options
author | sammc@chromium.org <sammc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-09-23 10:30:53 +0000 |
---|---|---|
committer | sammc@chromium.org <sammc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-09-23 10:30:53 +0000 |
commit | 4f1e10816d3e9016d0d16d6fb3c36d92080ef919 (patch) | |
tree | d782969f32332b7516d6e4b2866bbc69e1bf9393 /ui/base | |
parent | c23cc46f6dff65a489bca6fa45f10131ebf8dea1 (diff) | |
download | chromium_src-4f1e10816d3e9016d0d16d6fb3c36d92080ef919.zip chromium_src-4f1e10816d3e9016d0d16d6fb3c36d92080ef919.tar.gz chromium_src-4f1e10816d3e9016d0d16d6fb3c36d92080ef919.tar.bz2 |
Use ICU for string pluralization in the extension permission dialog.
This adds support for using the correct plural form of a string for any
language. In particular, this uses the aforementioned support in the
extensions permission dialog for website access and retained file
access.
BUG=290046
Review URL: https://chromiumcodereview.appspot.com/23591040
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@224700 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/base')
-rw-r--r-- | ui/base/l10n/l10n_util.cc | 22 | ||||
-rw-r--r-- | ui/base/l10n/l10n_util.h | 8 | ||||
-rw-r--r-- | ui/base/l10n/l10n_util_plurals.cc | 64 | ||||
-rw-r--r-- | ui/base/l10n/l10n_util_plurals.h | 30 | ||||
-rw-r--r-- | ui/base/l10n/time_format.cc | 44 |
5 files changed, 132 insertions, 36 deletions
diff --git a/ui/base/l10n/l10n_util.cc b/ui/base/l10n/l10n_util.cc index e0929dc..96dfa8e 100644 --- a/ui/base/l10n/l10n_util.cc +++ b/ui/base/l10n/l10n_util.cc @@ -28,6 +28,7 @@ #include "third_party/icu/source/common/unicode/rbbi.h" #include "third_party/icu/source/common/unicode/uloc.h" #include "ui/base/l10n/l10n_util_collator.h" +#include "ui/base/l10n/l10n_util_plurals.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/ui_base_paths.h" @@ -831,6 +832,27 @@ bool StringComparator<string16>::operator()(const string16& lhs, UCOL_LESS; }; +string16 GetPluralStringFUTF16(const std::vector<int>& message_ids, + int number) { + scoped_ptr<icu::PluralFormat> format = BuildPluralFormat(message_ids); + DCHECK(format); + + UErrorCode err = U_ZERO_ERROR; + icu::UnicodeString result_files_string = format->format(number, err); + int capacity = result_files_string.length() + 1; + DCHECK_GT(capacity, 1); + string16 result; + result_files_string.extract( + static_cast<UChar*>(WriteInto(&result, capacity)), capacity, err); + DCHECK(U_SUCCESS(err)); + return result; +} + +std::string GetPluralStringFUTF8(const std::vector<int>& message_ids, + int number) { + return base::UTF16ToUTF8(GetPluralStringFUTF16(message_ids, number)); +} + void SortStrings16(const std::string& locale, std::vector<string16>* strings) { SortVectorWithStringKey(locale, strings, false); diff --git a/ui/base/l10n/l10n_util.h b/ui/base/l10n/l10n_util.h index 7c26b80..d775336 100644 --- a/ui/base/l10n/l10n_util.h +++ b/ui/base/l10n/l10n_util.h @@ -139,6 +139,14 @@ UI_EXPORT string16 GetStringFUTF16(int message_id, UI_EXPORT string16 GetStringFUTF16Int(int message_id, int a); string16 GetStringFUTF16Int(int message_id, int64 a); +// Get a resource string using |number| to decide which of |message_ids| should +// be used. |message_ids| must be size 6 and in order: default, singular, zero, +// two, few, many. +UI_EXPORT string16 GetPluralStringFUTF16(const std::vector<int>& message_ids, + int number); +UI_EXPORT std::string GetPluralStringFUTF8(const std::vector<int>& message_ids, + int number); + // In place sorting of string16 strings using collation rules for |locale|. UI_EXPORT void SortStrings16(const std::string& locale, std::vector<string16>* strings); diff --git a/ui/base/l10n/l10n_util_plurals.cc b/ui/base/l10n/l10n_util_plurals.cc new file mode 100644 index 0000000..0dc008f --- /dev/null +++ b/ui/base/l10n/l10n_util_plurals.cc @@ -0,0 +1,64 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ui/base/l10n/l10n_util_plurals.h" + +#include "base/memory/scoped_ptr.h" +#include "ui/base/l10n/l10n_util.h" + +namespace l10n_util { + +scoped_ptr<icu::PluralRules> BuildPluralRules() { + UErrorCode err = U_ZERO_ERROR; + scoped_ptr<icu::PluralRules> rules( + icu::PluralRules::forLocale(icu::Locale::getDefault(), err)); + if (U_FAILURE(err)) { + err = U_ZERO_ERROR; + icu::UnicodeString fallback_rules("one: n is 1", -1, US_INV); + rules.reset(icu::PluralRules::createRules(fallback_rules, err)); + DCHECK(U_SUCCESS(err)); + } + return rules.Pass(); +} + +scoped_ptr<icu::PluralFormat> BuildPluralFormat( + const std::vector<int>& message_ids) { + const icu::UnicodeString kKeywords[] = { + UNICODE_STRING_SIMPLE("other"), + UNICODE_STRING_SIMPLE("one"), + UNICODE_STRING_SIMPLE("zero"), + UNICODE_STRING_SIMPLE("two"), + UNICODE_STRING_SIMPLE("few"), + UNICODE_STRING_SIMPLE("many"), + }; + DCHECK_EQ(message_ids.size(), arraysize(kKeywords)); + UErrorCode err = U_ZERO_ERROR; + scoped_ptr<icu::PluralRules> rules(BuildPluralRules()); + + icu::UnicodeString pattern; + for (size_t i = 0; i < arraysize(kKeywords); ++i) { + int msg_id = message_ids[i]; + std::string sub_pattern = GetStringUTF8(msg_id); + // NA means this keyword is not used in the current locale. + // Even if a translator translated for this keyword, we do not + // use it unless it's 'other' (i=0) or it's defined in the rules + // for the current locale. Special-casing of 'other' will be removed + // once ICU's isKeyword is fixed to return true for isKeyword('other'). + if (sub_pattern.compare("NA") != 0 && + (i == 0 || rules->isKeyword(kKeywords[i]))) { + pattern += kKeywords[i]; + pattern += UNICODE_STRING_SIMPLE("{"); + pattern += icu::UnicodeString(sub_pattern.c_str(), "UTF-8"); + pattern += UNICODE_STRING_SIMPLE("}"); + } + } + scoped_ptr<icu::PluralFormat> format = scoped_ptr<icu::PluralFormat>( + new icu::PluralFormat(*rules, pattern, err)); + if (!U_SUCCESS(err)) { + return scoped_ptr<icu::PluralFormat>(); + } + return format.Pass(); +} + +} // namespace l10n_util diff --git a/ui/base/l10n/l10n_util_plurals.h b/ui/base/l10n/l10n_util_plurals.h new file mode 100644 index 0000000..203797d --- /dev/null +++ b/ui/base/l10n/l10n_util_plurals.h @@ -0,0 +1,30 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This file contains utility functions for dealing with pluralization of +// localized content. + +#ifndef UI_BASE_L10N_L10N_UTIL_PLURALS_H_ +#define UI_BASE_L10N_L10N_UTIL_PLURALS_H_ + +#include <string> +#include <vector> + +#include "base/memory/scoped_ptr.h" +#include "third_party/icu/source/i18n/unicode/plurfmt.h" +#include "third_party/icu/source/i18n/unicode/plurrule.h" + +namespace l10n_util { + +// Returns a PluralRules for the current locale. +scoped_ptr<icu::PluralRules> BuildPluralRules(); + +// Returns a PluralFormat from |message_ids|. |message_ids| must be size 6 and +// in order: default, singular, zero, two, few, many. +scoped_ptr<icu::PluralFormat> BuildPluralFormat( + const std::vector<int>& message_ids); + +} // namespace l10n_util + +#endif // UI_BASE_L10N_L10N_UTIL_PLURALS_H_ diff --git a/ui/base/l10n/time_format.cc b/ui/base/l10n/time_format.cc index 5ba606c..aaa35a9 100644 --- a/ui/base/l10n/time_format.cc +++ b/ui/base/l10n/time_format.cc @@ -21,6 +21,7 @@ #include "third_party/icu/source/i18n/unicode/plurrule.h" #include "third_party/icu/source/i18n/unicode/smpdtfmt.h" #include "ui/base/l10n/l10n_util.h" +#include "ui/base/l10n/l10n_util_plurals.h" using base::Time; using base::TimeDelta; @@ -240,49 +241,20 @@ static base::LazyInstance<TimeFormatter> g_time_formatter = void TimeFormatter::BuildFormats( FormatType format_type, ScopedVector<icu::PluralFormat>* time_formats) { - const icu::UnicodeString kKeywords[] = { - UNICODE_STRING_SIMPLE("other"), UNICODE_STRING_SIMPLE("one"), - UNICODE_STRING_SIMPLE("zero"), UNICODE_STRING_SIMPLE("two"), - UNICODE_STRING_SIMPLE("few"), UNICODE_STRING_SIMPLE("many") - }; - UErrorCode err = U_ZERO_ERROR; - scoped_ptr<icu::PluralRules> rules( - icu::PluralRules::forLocale(icu::Locale::getDefault(), err)); - if (U_FAILURE(err)) { - err = U_ZERO_ERROR; - icu::UnicodeString fallback_rules("one: n is 1", -1, US_INV); - rules.reset(icu::PluralRules::createRules(fallback_rules, err)); - DCHECK(U_SUCCESS(err)); - } - const MessageIDs& message_ids = GetMessageIDs(format_type); for (int i = 0; i < 4; ++i) { icu::UnicodeString pattern; - for (size_t j = 0; j < arraysize(kKeywords); ++j) { - int msg_id = message_ids.ids[i][j]; - std::string sub_pattern = l10n_util::GetStringUTF8(msg_id); - // NA means this keyword is not used in the current locale. - // Even if a translator translated for this keyword, we do not - // use it unless it's 'other' (j=0) or it's defined in the rules - // for the current locale. Special-casing of 'other' will be removed - // once ICU's isKeyword is fixed to return true for isKeyword('other'). - if (sub_pattern.compare("NA") != 0 && - (j == 0 || rules->isKeyword(kKeywords[j]))) { - pattern += kKeywords[j]; - pattern += UNICODE_STRING_SIMPLE("{"); - pattern += icu::UnicodeString(sub_pattern.c_str(), "UTF-8"); - pattern += UNICODE_STRING_SIMPLE("}"); - } + std::vector<int> ids; + for (size_t j = 0; j < arraysize(message_ids.ids[i]); ++j) { + ids.push_back(message_ids.ids[i][j]); } - icu::PluralFormat* format = new icu::PluralFormat(*rules, pattern, err); - if (U_SUCCESS(err)) { - time_formats->push_back(format); + scoped_ptr<icu::PluralFormat> format = l10n_util::BuildPluralFormat(ids); + if (format) { + time_formats->push_back(format.release()); } else { - delete format; + scoped_ptr<icu::PluralRules> rules(l10n_util::BuildPluralRules()); time_formats->push_back(createFallbackFormat(*rules, i, format_type)); - // Reset it so that next ICU call can proceed. - err = U_ZERO_ERROR; } } } |