OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/base/l10n/formatter.h" | 5 #include "ui/base/l10n/formatter.h" |
6 | 6 |
7 #include <vector> | 7 #include <vector> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/memory/scoped_ptr.h" |
10 #include "third_party/icu/source/common/unicode/unistr.h" | 11 #include "third_party/icu/source/common/unicode/unistr.h" |
11 #include "third_party/icu/source/i18n/unicode/msgfmt.h" | 12 #include "third_party/icu/source/i18n/unicode/msgfmt.h" |
12 #include "ui/base/l10n/l10n_util.h" | 13 #include "ui/base/l10n/l10n_util.h" |
13 #include "ui/base/l10n/l10n_util_plurals.h" | |
14 #include "ui/strings/grit/ui_strings.h" | 14 #include "ui/strings/grit/ui_strings.h" |
15 | 15 |
16 namespace ui { | 16 namespace ui { |
17 | 17 |
18 UI_BASE_EXPORT bool formatter_force_fallback = false; | 18 UI_BASE_EXPORT bool formatter_force_fallback = false; |
19 | 19 |
20 struct Pluralities { | 20 struct Pluralities { |
21 int id; | 21 int id; |
22 const char* const fallback_one; | 22 const char* const fallback_one; |
23 const char* const fallback_other; | 23 const char* const fallback_other; |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
132 IDS_TIME_DAYS_1ST, | 132 IDS_TIME_DAYS_1ST, |
133 "one{# day and }", | 133 "one{# day and }", |
134 " other{# days and }" | 134 " other{# days and }" |
135 }; | 135 }; |
136 static const Pluralities IDS_DURATION_HOUR_2ND = { | 136 static const Pluralities IDS_DURATION_HOUR_2ND = { |
137 IDS_TIME_HOURS_2ND, | 137 IDS_TIME_HOURS_2ND, |
138 "one{# hour}", | 138 "one{# hour}", |
139 " other{# hours}" | 139 " other{# hours}" |
140 }; | 140 }; |
141 | 141 |
| 142 namespace { |
| 143 |
| 144 scoped_ptr<icu::PluralRules> BuildPluralRules() { |
| 145 UErrorCode err = U_ZERO_ERROR; |
| 146 scoped_ptr<icu::PluralRules> rules( |
| 147 icu::PluralRules::forLocale(icu::Locale::getDefault(), err)); |
| 148 if (U_FAILURE(err)) { |
| 149 err = U_ZERO_ERROR; |
| 150 icu::UnicodeString fallback_rules("one: n is 1", -1, US_INV); |
| 151 rules.reset(icu::PluralRules::createRules(fallback_rules, err)); |
| 152 DCHECK(U_SUCCESS(err)); |
| 153 } |
| 154 return rules.Pass(); |
| 155 } |
| 156 |
| 157 void FormatNumberInPlural(const icu::MessageFormat& format, int number, |
| 158 icu::UnicodeString* result, UErrorCode* err) { |
| 159 if (U_FAILURE(*err)) return; |
| 160 icu::Formattable formattable(number); |
| 161 icu::FieldPosition ignore(icu::FieldPosition::DONT_CARE); |
| 162 format.format(&formattable, 1, *result, ignore, *err); |
| 163 DCHECK(U_SUCCESS(*err)); |
| 164 return; |
| 165 } |
| 166 |
| 167 } // namespace |
| 168 |
142 Formatter::Formatter(const Pluralities& sec_pluralities, | 169 Formatter::Formatter(const Pluralities& sec_pluralities, |
143 const Pluralities& min_pluralities, | 170 const Pluralities& min_pluralities, |
144 const Pluralities& hour_pluralities, | 171 const Pluralities& hour_pluralities, |
145 const Pluralities& day_pluralities) { | 172 const Pluralities& day_pluralities) { |
146 simple_format_[UNIT_SEC] = InitFormat(sec_pluralities); | 173 simple_format_[UNIT_SEC] = InitFormat(sec_pluralities); |
147 simple_format_[UNIT_MIN] = InitFormat(min_pluralities); | 174 simple_format_[UNIT_MIN] = InitFormat(min_pluralities); |
148 simple_format_[UNIT_HOUR] = InitFormat(hour_pluralities); | 175 simple_format_[UNIT_HOUR] = InitFormat(hour_pluralities); |
149 simple_format_[UNIT_DAY] = InitFormat(day_pluralities); | 176 simple_format_[UNIT_DAY] = InitFormat(day_pluralities); |
150 } | 177 } |
151 | 178 |
(...skipping 18 matching lines...) Expand all Loading... |
170 detailed_format_[TWO_UNITS_DAY_HOUR][0] = InitFormat(day_hour_pluralities1); | 197 detailed_format_[TWO_UNITS_DAY_HOUR][0] = InitFormat(day_hour_pluralities1); |
171 detailed_format_[TWO_UNITS_DAY_HOUR][1] = InitFormat(day_hour_pluralities2); | 198 detailed_format_[TWO_UNITS_DAY_HOUR][1] = InitFormat(day_hour_pluralities2); |
172 } | 199 } |
173 | 200 |
174 void Formatter::Format(Unit unit, | 201 void Formatter::Format(Unit unit, |
175 int value, | 202 int value, |
176 icu::UnicodeString* formatted_string) const { | 203 icu::UnicodeString* formatted_string) const { |
177 DCHECK(simple_format_[unit]); | 204 DCHECK(simple_format_[unit]); |
178 DCHECK(formatted_string->isEmpty() == TRUE); | 205 DCHECK(formatted_string->isEmpty() == TRUE); |
179 UErrorCode error = U_ZERO_ERROR; | 206 UErrorCode error = U_ZERO_ERROR; |
180 l10n_util::FormatNumberInPlural(*simple_format_[unit], | 207 FormatNumberInPlural(*simple_format_[unit], |
181 value, formatted_string, &error); | 208 value, formatted_string, &error); |
182 DCHECK(U_SUCCESS(error)) << "Error in icu::PluralFormat::format()."; | 209 DCHECK(U_SUCCESS(error)) << "Error in icu::PluralFormat::format()."; |
183 return; | 210 return; |
184 } | 211 } |
185 | 212 |
186 void Formatter::Format(TwoUnits units, | 213 void Formatter::Format(TwoUnits units, |
187 int value_1, | 214 int value_1, |
188 int value_2, | 215 int value_2, |
189 icu::UnicodeString* formatted_string) const { | 216 icu::UnicodeString* formatted_string) const { |
190 DCHECK(detailed_format_[units][0]) | 217 DCHECK(detailed_format_[units][0]) |
191 << "Detailed() not implemented for your (format, length) combination!"; | 218 << "Detailed() not implemented for your (format, length) combination!"; |
192 DCHECK(detailed_format_[units][1]) | 219 DCHECK(detailed_format_[units][1]) |
193 << "Detailed() not implemented for your (format, length) combination!"; | 220 << "Detailed() not implemented for your (format, length) combination!"; |
194 DCHECK(formatted_string->isEmpty() == TRUE); | 221 DCHECK(formatted_string->isEmpty() == TRUE); |
195 UErrorCode error = U_ZERO_ERROR; | 222 UErrorCode error = U_ZERO_ERROR; |
196 l10n_util::FormatNumberInPlural(*detailed_format_[units][0], value_1, | 223 FormatNumberInPlural(*detailed_format_[units][0], value_1, |
197 formatted_string, &error); | 224 formatted_string, &error); |
198 DCHECK(U_SUCCESS(error)); | 225 DCHECK(U_SUCCESS(error)); |
199 l10n_util::FormatNumberInPlural(*detailed_format_[units][1], value_2, | 226 FormatNumberInPlural(*detailed_format_[units][1], value_2, |
200 formatted_string, &error); | 227 formatted_string, &error); |
201 DCHECK(U_SUCCESS(error)); | 228 DCHECK(U_SUCCESS(error)); |
202 return; | 229 return; |
203 } | 230 } |
204 | 231 |
205 scoped_ptr<icu::MessageFormat> Formatter::CreateFallbackFormat( | 232 scoped_ptr<icu::MessageFormat> Formatter::CreateFallbackFormat( |
206 const icu::PluralRules& rules, | 233 const icu::PluralRules& rules, |
207 const Pluralities& pluralities) const { | 234 const Pluralities& pluralities) const { |
208 icu::UnicodeString pattern("{NUMBER, plural, "); | 235 icu::UnicodeString pattern("{NUMBER, plural, "); |
209 if (rules.isKeyword(UNICODE_STRING_SIMPLE("one"))) | 236 if (rules.isKeyword(UNICODE_STRING_SIMPLE("one"))) |
210 pattern += icu::UnicodeString(pluralities.fallback_one); | 237 pattern += icu::UnicodeString(pluralities.fallback_one); |
(...skipping 12 matching lines...) Expand all Loading... |
223 if (!formatter_force_fallback) { | 250 if (!formatter_force_fallback) { |
224 base::string16 pattern = l10n_util::GetStringUTF16(pluralities.id); | 251 base::string16 pattern = l10n_util::GetStringUTF16(pluralities.id); |
225 UErrorCode error = U_ZERO_ERROR; | 252 UErrorCode error = U_ZERO_ERROR; |
226 scoped_ptr<icu::MessageFormat> format(new icu::MessageFormat( | 253 scoped_ptr<icu::MessageFormat> format(new icu::MessageFormat( |
227 icu::UnicodeString(FALSE, pattern.data(), pattern.length()), error)); | 254 icu::UnicodeString(FALSE, pattern.data(), pattern.length()), error)); |
228 DCHECK(U_SUCCESS(error)); | 255 DCHECK(U_SUCCESS(error)); |
229 if (format.get()) | 256 if (format.get()) |
230 return format.Pass(); | 257 return format.Pass(); |
231 } | 258 } |
232 | 259 |
233 scoped_ptr<icu::PluralRules> rules(l10n_util::BuildPluralRules()); | 260 scoped_ptr<icu::PluralRules> rules(BuildPluralRules()); |
234 return CreateFallbackFormat(*rules, pluralities); | 261 return CreateFallbackFormat(*rules, pluralities); |
235 } | 262 } |
236 | 263 |
237 const Formatter* FormatterContainer::Get(TimeFormat::Format format, | 264 const Formatter* FormatterContainer::Get(TimeFormat::Format format, |
238 TimeFormat::Length length) const { | 265 TimeFormat::Length length) const { |
239 DCHECK(formatter_[format][length]) | 266 DCHECK(formatter_[format][length]) |
240 << "Combination of FORMAT_ELAPSED and LENGTH_LONG is not implemented!"; | 267 << "Combination of FORMAT_ELAPSED and LENGTH_LONG is not implemented!"; |
241 return formatter_[format][length].get(); | 268 return formatter_[format][length].get(); |
242 } | 269 } |
243 | 270 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
285 | 312 |
286 void FormatterContainer::Shutdown() { | 313 void FormatterContainer::Shutdown() { |
287 for (int format = 0; format < TimeFormat::FORMAT_COUNT; ++format) { | 314 for (int format = 0; format < TimeFormat::FORMAT_COUNT; ++format) { |
288 for (int length = 0; length < TimeFormat::LENGTH_COUNT; ++length) { | 315 for (int length = 0; length < TimeFormat::LENGTH_COUNT; ++length) { |
289 formatter_[format][length].reset(); | 316 formatter_[format][length].reset(); |
290 } | 317 } |
291 } | 318 } |
292 } | 319 } |
293 | 320 |
294 } // namespace ui | 321 } // namespace ui |
OLD | NEW |