OLD | NEW |
---|---|
(Empty) | |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "ui/base/l10n/formatter.h" | |
6 | |
7 #include <vector> | |
8 | |
9 #include "grit/ui_strings.h" | |
10 #include "third_party/icu/source/common/unicode/unistr.h" | |
11 #include "ui/base/l10n/l10n_util_plurals.h" | |
12 | |
13 namespace ui { | |
14 | |
15 // static | |
16 bool FormatterContainer::ForceFallback_ = false; | |
17 | |
18 static const size_t kNPluralities = 6; | |
19 struct Pluralities { | |
20 int Ids[kNPluralities]; | |
bartfab (slow)
2014/02/18 12:04:04
Nit: User hacker_style, not CamelCaps for member n
Thiemo Nagel
2014/02/19 17:08:44
Done.
| |
21 const char *FallbackOne; | |
bartfab (slow)
2014/02/18 12:04:04
Nit: Put * on the type, not the member.
Thiemo Nagel
2014/02/19 17:08:44
Done.
| |
22 const char *FallbackOther; | |
23 }; | |
24 | |
25 static const Pluralities IDS_ELAPSED_SHORT_SEC = { | |
26 { IDS_TIME_ELAPSED_SECS_DEFAULT, IDS_TIME_ELAPSED_SEC_SINGULAR, | |
27 IDS_TIME_ELAPSED_SECS_ZERO, IDS_TIME_ELAPSED_SECS_TWO, | |
28 IDS_TIME_ELAPSED_SECS_FEW, IDS_TIME_ELAPSED_SECS_MANY }, | |
29 "one{# sec ago}", | |
30 " other{# secs ago}" | |
31 }; | |
32 static const Pluralities IDS_ELAPSED_SHORT_MIN = { | |
33 { IDS_TIME_ELAPSED_MINS_DEFAULT, IDS_TIME_ELAPSED_MIN_SINGULAR, | |
34 IDS_TIME_ELAPSED_MINS_ZERO, IDS_TIME_ELAPSED_MINS_TWO, | |
35 IDS_TIME_ELAPSED_MINS_FEW, IDS_TIME_ELAPSED_MINS_MANY }, | |
36 "one{# min ago}", | |
37 " other{# mins ago}" | |
38 }; | |
39 static const Pluralities IDS_ELAPSED_HOUR = { | |
40 { IDS_TIME_ELAPSED_HOURS_DEFAULT, IDS_TIME_ELAPSED_HOUR_SINGULAR, | |
41 IDS_TIME_ELAPSED_HOURS_ZERO, IDS_TIME_ELAPSED_HOURS_TWO, | |
42 IDS_TIME_ELAPSED_HOURS_FEW, IDS_TIME_ELAPSED_HOURS_MANY }, | |
43 "one{# hour ago}", | |
44 " other{# hours ago}" | |
45 }; | |
46 static const Pluralities IDS_ELAPSED_DAY = { | |
47 { IDS_TIME_ELAPSED_DAYS_DEFAULT, IDS_TIME_ELAPSED_DAY_SINGULAR, | |
48 IDS_TIME_ELAPSED_DAYS_ZERO, IDS_TIME_ELAPSED_DAYS_TWO, | |
49 IDS_TIME_ELAPSED_DAYS_FEW, IDS_TIME_ELAPSED_DAYS_MANY }, | |
50 "one{# day ago}", | |
51 " other{# days ago}" | |
52 }; | |
53 | |
54 static const Pluralities IDS_REMAINING_SHORT_SEC = { | |
55 { IDS_TIME_REMAINING_SECS_DEFAULT, IDS_TIME_REMAINING_SEC_SINGULAR, | |
56 IDS_TIME_REMAINING_SECS_ZERO, IDS_TIME_REMAINING_SECS_TWO, | |
57 IDS_TIME_REMAINING_SECS_FEW, IDS_TIME_REMAINING_SECS_MANY }, | |
58 "one{# sec left}", | |
59 " other{# secs left}" | |
60 }; | |
61 static const Pluralities IDS_REMAINING_SHORT_MIN = { | |
62 { IDS_TIME_REMAINING_MINS_DEFAULT, IDS_TIME_REMAINING_MIN_SINGULAR, | |
63 IDS_TIME_REMAINING_MINS_ZERO, IDS_TIME_REMAINING_MINS_TWO, | |
64 IDS_TIME_REMAINING_MINS_FEW, IDS_TIME_REMAINING_MINS_MANY }, | |
65 "one{# min left}", | |
66 " other{# mins left}" | |
67 }; | |
68 | |
69 static const Pluralities IDS_REMAINING_LONG_SEC = { | |
70 { IDS_TIME_REMAINING_LONG_SECS_DEFAULT, IDS_TIME_REMAINING_LONG_SEC_SINGULAR, | |
71 IDS_TIME_REMAINING_LONG_SECS_ZERO, IDS_TIME_REMAINING_LONG_SECS_TWO, | |
72 IDS_TIME_REMAINING_LONG_SECS_FEW, IDS_TIME_REMAINING_LONG_SECS_MANY }, | |
73 "one{# second left}", | |
74 " other{# seconds left}" | |
75 }; | |
76 static const Pluralities IDS_REMAINING_LONG_MIN = { | |
77 { IDS_TIME_REMAINING_LONG_MINS_DEFAULT, IDS_TIME_REMAINING_LONG_MIN_SINGULAR, | |
78 IDS_TIME_REMAINING_LONG_MINS_ZERO, IDS_TIME_REMAINING_LONG_MINS_TWO, | |
79 IDS_TIME_REMAINING_LONG_MINS_FEW, IDS_TIME_REMAINING_LONG_MINS_MANY }, | |
80 "one{# minute left}", | |
81 " other{# minutes left}" | |
82 }; | |
83 static const Pluralities IDS_REMAINING_HOUR = { | |
84 { IDS_TIME_REMAINING_HOURS_DEFAULT, IDS_TIME_REMAINING_HOUR_SINGULAR, | |
85 IDS_TIME_REMAINING_HOURS_ZERO, IDS_TIME_REMAINING_HOURS_TWO, | |
86 IDS_TIME_REMAINING_HOURS_FEW, IDS_TIME_REMAINING_HOURS_MANY }, | |
87 "one{# hour left}", | |
88 " other{# hours left}" | |
89 }; | |
90 static const Pluralities IDS_REMAINING_DAY = { | |
91 { IDS_TIME_REMAINING_DAYS_DEFAULT, IDS_TIME_REMAINING_DAY_SINGULAR, | |
92 IDS_TIME_REMAINING_DAYS_ZERO, IDS_TIME_REMAINING_DAYS_TWO, | |
93 IDS_TIME_REMAINING_DAYS_FEW, IDS_TIME_REMAINING_DAYS_MANY }, | |
94 "one{# day left}", | |
95 " other{# days left}" | |
96 }; | |
97 | |
98 static const Pluralities IDS_DURATION_SHORT_SEC = { | |
99 { IDS_TIME_SECS_DEFAULT, IDS_TIME_SEC_SINGULAR, IDS_TIME_SECS_ZERO, | |
100 IDS_TIME_SECS_TWO, IDS_TIME_SECS_FEW, IDS_TIME_SECS_MANY }, | |
101 "one{# sec}", | |
102 " other{# secs}" | |
103 }; | |
104 static const Pluralities IDS_DURATION_SHORT_MIN = { | |
105 { IDS_TIME_MINS_DEFAULT, IDS_TIME_MIN_SINGULAR, IDS_TIME_MINS_ZERO, | |
106 IDS_TIME_MINS_TWO, IDS_TIME_MINS_FEW, IDS_TIME_MINS_MANY }, | |
107 "one{# min}", | |
108 " other{# mins}" | |
109 }; | |
110 | |
111 static const Pluralities IDS_LONG_SEC = { | |
112 { IDS_TIME_LONG_SECS_DEFAULT, IDS_TIME_LONG_SEC_SINGULAR, | |
113 IDS_TIME_LONG_SECS_ZERO, IDS_TIME_LONG_SECS_TWO, | |
114 IDS_TIME_LONG_SECS_FEW, IDS_TIME_LONG_SECS_MANY }, | |
115 "one{# second}", | |
116 " other{# seconds}" | |
117 }; | |
118 static const Pluralities IDS_LONG_MIN = { | |
119 { IDS_TIME_LONG_MINS_DEFAULT, IDS_TIME_LONG_MIN_SINGULAR, | |
120 IDS_TIME_LONG_MINS_ZERO, IDS_TIME_LONG_MINS_TWO, | |
121 IDS_TIME_LONG_MINS_FEW, IDS_TIME_LONG_MINS_MANY }, | |
122 "one{# minute}", | |
123 " other{# minutes}" | |
124 }; | |
125 static const Pluralities IDS_DURATION_HOUR = { | |
126 { IDS_TIME_HOURS_DEFAULT, IDS_TIME_HOUR_SINGULAR, IDS_TIME_HOURS_ZERO, | |
127 IDS_TIME_HOURS_TWO, IDS_TIME_HOURS_FEW, IDS_TIME_HOURS_MANY }, | |
128 "one{# hour}", | |
129 " other{# hours}" | |
130 }; | |
131 static const Pluralities IDS_DURATION_DAY = { | |
132 { IDS_TIME_DAYS_DEFAULT, IDS_TIME_DAY_SINGULAR, IDS_TIME_DAYS_ZERO, | |
133 IDS_TIME_DAYS_TWO, IDS_TIME_DAYS_FEW, IDS_TIME_DAYS_MANY }, | |
134 "one{# day}", | |
135 " other{# days}" | |
136 }; | |
137 | |
138 static const Pluralities IDS_LONG_MIN_1ST = { | |
139 { IDS_TIME_LONG_MINS_1ST_DEFAULT, IDS_TIME_LONG_MIN_1ST_SINGULAR, | |
140 IDS_TIME_LONG_MINS_1ST_ZERO, IDS_TIME_LONG_MINS_1ST_TWO, | |
141 IDS_TIME_LONG_MINS_1ST_FEW, IDS_TIME_LONG_MINS_1ST_MANY }, | |
142 "one{# minute }", | |
143 " other{# minutes }" | |
144 }; | |
145 static const Pluralities IDS_LONG_SEC_2ND = { | |
146 { IDS_TIME_LONG_SECS_2ND_DEFAULT, IDS_TIME_LONG_SEC_2ND_SINGULAR, | |
147 IDS_TIME_LONG_SECS_2ND_ZERO, IDS_TIME_LONG_SECS_2ND_TWO, | |
148 IDS_TIME_LONG_SECS_2ND_FEW, IDS_TIME_LONG_SECS_2ND_MANY }, | |
149 "one{# second}", | |
150 " other{# seconds}" | |
151 }; | |
152 static const Pluralities IDS_DURATION_HOUR_1ST = { | |
153 { IDS_TIME_HOURS_1ST_DEFAULT, IDS_TIME_HOUR_1ST_SINGULAR, | |
154 IDS_TIME_HOURS_1ST_ZERO, IDS_TIME_HOURS_1ST_TWO, | |
155 IDS_TIME_HOURS_1ST_FEW, IDS_TIME_HOURS_1ST_MANY }, | |
156 "one{# hour }", | |
157 " other{# hours }" | |
158 }; | |
159 static const Pluralities IDS_LONG_MIN_2ND = { | |
160 { IDS_TIME_LONG_MINS_2ND_DEFAULT, IDS_TIME_LONG_MIN_2ND_SINGULAR, | |
161 IDS_TIME_LONG_MINS_2ND_ZERO, IDS_TIME_LONG_MINS_2ND_TWO, | |
162 IDS_TIME_LONG_MINS_2ND_FEW, IDS_TIME_LONG_MINS_2ND_MANY }, | |
163 "one{# minute}", | |
164 " other{# minutes}" | |
165 }; | |
166 static const Pluralities IDS_DURATION_DAY_1ST = { | |
167 { IDS_TIME_DAYS_1ST_DEFAULT, IDS_TIME_DAY_1ST_SINGULAR, | |
168 IDS_TIME_DAYS_1ST_ZERO, IDS_TIME_DAYS_1ST_TWO, | |
169 IDS_TIME_DAYS_1ST_FEW, IDS_TIME_DAYS_1ST_MANY }, | |
170 "one{# day }", | |
171 " other{# days }" | |
172 }; | |
173 static const Pluralities IDS_DURATION_HOUR_2ND = { | |
174 { IDS_TIME_HOURS_2ND_DEFAULT, IDS_TIME_HOUR_2ND_SINGULAR, | |
175 IDS_TIME_HOURS_2ND_ZERO, IDS_TIME_HOURS_2ND_TWO, | |
176 IDS_TIME_HOURS_2ND_FEW, IDS_TIME_HOURS_2ND_MANY }, | |
177 "one{# hour}", | |
178 " other{# hours}" | |
179 }; | |
180 | |
181 Formatter::Formatter(const Pluralities& sec_pluralities, | |
182 const Pluralities& min_pluralities, | |
183 const Pluralities& hour_pluralities, | |
184 const Pluralities& day_pluralities) { | |
185 format_[SEC].reset(InitFormat(sec_pluralities)); | |
186 format_[MIN].reset(InitFormat(min_pluralities)); | |
187 format_[HOUR].reset(InitFormat(hour_pluralities)); | |
188 format_[DAY].reset(InitFormat(day_pluralities)); | |
189 } | |
190 | |
191 Formatter::Formatter(const Pluralities& sec_pluralities, | |
192 const Pluralities& min_pluralities, | |
193 const Pluralities& hour_pluralities, | |
194 const Pluralities& day_pluralities, | |
195 const Pluralities& min_sec_pluralities1, | |
196 const Pluralities& min_sec_pluralities2, | |
197 const Pluralities& hour_min_pluralities1, | |
198 const Pluralities& hour_min_pluralities2, | |
199 const Pluralities& day_hour_pluralities1, | |
200 const Pluralities& day_hour_pluralities2) { | |
201 format_[SEC].reset(InitFormat(sec_pluralities)); | |
202 format_[MIN].reset(InitFormat(min_pluralities)); | |
203 format_[HOUR].reset(InitFormat(hour_pluralities)); | |
204 format_[DAY].reset(InitFormat(day_pluralities)); | |
205 detailed_format_[MIN_SEC][0].reset(InitFormat(min_sec_pluralities1)); | |
206 detailed_format_[MIN_SEC][1].reset(InitFormat(min_sec_pluralities2)); | |
207 detailed_format_[HOUR_MIN][0].reset(InitFormat(hour_min_pluralities1)); | |
208 detailed_format_[HOUR_MIN][1].reset(InitFormat(hour_min_pluralities2)); | |
209 detailed_format_[DAY_HOUR][0].reset(InitFormat(day_hour_pluralities1)); | |
210 detailed_format_[DAY_HOUR][1].reset(InitFormat(day_hour_pluralities2)); | |
211 } | |
212 | |
213 void Formatter::Format(Unit unit, int value, | |
bartfab (slow)
2014/02/18 12:04:04
Nit: Per the style guide, a declaration/definition
Thiemo Nagel
2014/02/19 17:08:44
Done.
| |
214 icu::UnicodeString& formatted_string) const { | |
215 UErrorCode error = U_ZERO_ERROR; | |
bartfab (slow)
2014/02/18 12:04:04
Nit: Why not move down the definition of |error| d
Thiemo Nagel
2014/02/19 17:08:44
Done.
| |
216 DCHECK(format_[unit].get()) << "This can never happen."; | |
bartfab (slow)
2014/02/18 12:04:04
Nit 1: #include "base/logging.h"
Nit 2: format_[un
Thiemo Nagel
2014/02/19 17:08:44
Done.
| |
217 formatted_string = format_[unit].get()->format(value, error); | |
bartfab (slow)
2014/02/18 12:04:04
Nit: No need for get() before ->
Thiemo Nagel
2014/02/19 17:08:44
Done.
| |
218 DCHECK(U_SUCCESS(error)) << "Formatter error."; | |
219 return; | |
220 } | |
221 | |
222 void Formatter::Format(TwoUnits units, int value1, int value2, | |
bartfab (slow)
2014/02/18 12:04:04
Nit: Per the style guide, a declaration/definition
Thiemo Nagel
2014/02/19 17:08:44
Done.
| |
223 icu::UnicodeString& formatted_string) const { | |
224 UErrorCode error = U_ZERO_ERROR; | |
bartfab (slow)
2014/02/18 12:04:04
Nit: Why not move down the definition of |error| d
Thiemo Nagel
2014/02/19 17:08:44
Done.
| |
225 DCHECK(detailed_format_[units][0].get()) | |
bartfab (slow)
2014/02/18 12:04:04
Nit: detailed_format_[unit][0] can be truth-checke
Thiemo Nagel
2014/02/19 17:08:44
Done.
| |
226 << "Detailed() not implemented for your (type,length) combination!"; | |
227 DCHECK(detailed_format_[units][1].get()) | |
bartfab (slow)
2014/02/18 12:04:04
Nit: detailed_format_[unit][1] can be truth-checke
Thiemo Nagel
2014/02/19 17:08:44
Done.
| |
228 << "Detailed() not implemented for your (type,length) combination!"; | |
229 formatted_string = detailed_format_[units][0].get()->format(value1, error); | |
bartfab (slow)
2014/02/18 12:04:04
Nit: No need for get() before ->
Thiemo Nagel
2014/02/19 17:08:44
Done.
| |
230 DCHECK(U_SUCCESS(error)); | |
231 formatted_string += detailed_format_[units][1].get()->format(value2, error); | |
bartfab (slow)
2014/02/18 12:04:04
Nit: No need for get() before ->
Thiemo Nagel
2014/02/19 17:08:44
Done.
| |
232 DCHECK(U_SUCCESS(error)); | |
233 return; | |
234 } | |
235 | |
236 icu::PluralFormat* Formatter::CreateFallbackFormat( | |
bartfab (slow)
2014/02/18 12:04:04
Nit: Per the style guide, a declaration/definition
Thiemo Nagel
2014/02/19 17:08:44
Done.
| |
237 const icu::PluralRules& rules, const Pluralities& pluralities) const { | |
238 icu::UnicodeString pattern; | |
239 if (rules.isKeyword(UNICODE_STRING_SIMPLE("one"))) { | |
bartfab (slow)
2014/02/18 12:04:04
Nit: No curly braces necessary for single-line if.
Thiemo Nagel
2014/02/19 17:08:44
Not necessary but optional, if I read the style gu
bartfab (slow)
2014/02/20 16:31:22
Yes, it is a matter of choice. But if you look at
Thiemo Nagel
2014/02/22 21:44:09
Done, though I'm not certain the code is more read
| |
240 pattern += icu::UnicodeString(pluralities.FallbackOne); | |
241 } | |
242 pattern += icu::UnicodeString(pluralities.FallbackOther); | |
243 | |
244 UErrorCode err = U_ZERO_ERROR; | |
245 icu::PluralFormat* format = new icu::PluralFormat(rules, pattern, err); | |
246 DCHECK(U_SUCCESS(err)); | |
247 return format; | |
248 } | |
249 | |
250 icu::PluralFormat* Formatter::InitFormat(const Pluralities& pluralities) { | |
251 icu::UnicodeString pattern; | |
252 std::vector<int> ids; | |
253 for (size_t j = 0; j < kNPluralities; ++j) { | |
bartfab (slow)
2014/02/18 12:04:04
Nit: No need for curly braces when the body of a l
Thiemo Nagel
2014/02/19 17:08:44
I can't find a rule for that.
bartfab (slow)
2014/02/20 16:31:22
It's hiding in the rule for conditionals:
"In gen
Thiemo Nagel
2014/02/22 21:44:09
Done.
Thiemo Nagel
2014/02/22 21:44:09
Oh well...
| |
254 ids.push_back(pluralities.Ids[j]); | |
255 } | |
256 scoped_ptr<icu::PluralFormat> format = l10n_util::BuildPluralFormat(ids); | |
257 if (format.get() && !FormatterContainer::GetFallbackForTesting()) | |
bartfab (slow)
2014/02/18 12:04:04
Nit 1: scoped_ptr supports truth testing out of th
Thiemo Nagel
2014/02/19 17:08:44
Done.
| |
258 return format.release(); | |
259 | |
260 scoped_ptr<icu::PluralRules> rules(l10n_util::BuildPluralRules()); | |
261 return CreateFallbackFormat(*rules, pluralities); | |
262 } | |
263 | |
264 const Formatter* FormatterContainer::Get(TimeFormat::Type type, | |
265 TimeFormat::Length length) const { | |
266 DCHECK(formatter_[type][length]) | |
267 << "Combination of kElapsed and kLong is not implemented!"; | |
268 return formatter_[type][length]; | |
269 } | |
270 | |
271 FormatterContainer::FormatterContainer() { | |
bartfab (slow)
2014/02/18 12:04:04
Nit: Can you not initialize formatter_ in the init
Thiemo Nagel
2014/02/19 17:08:44
I'd love to, but that's C++11.
bartfab (slow)
2014/02/20 16:31:22
That's too bad...
| |
272 formatter_[TimeFormat::kElapsed][TimeFormat::kShort] = | |
273 new Formatter(IDS_ELAPSED_SHORT_SEC, | |
274 IDS_ELAPSED_SHORT_MIN, | |
275 IDS_ELAPSED_HOUR, | |
276 IDS_ELAPSED_DAY); | |
277 formatter_[TimeFormat::kElapsed][TimeFormat::kLong] = NULL; | |
278 formatter_[TimeFormat::kRemaining][TimeFormat::kShort] = | |
279 new Formatter(IDS_REMAINING_SHORT_SEC, | |
280 IDS_REMAINING_SHORT_MIN, | |
281 IDS_REMAINING_HOUR, | |
282 IDS_REMAINING_DAY); | |
283 formatter_[TimeFormat::kRemaining][TimeFormat::kLong] = | |
284 new Formatter(IDS_REMAINING_LONG_SEC, | |
285 IDS_REMAINING_LONG_MIN, | |
286 IDS_REMAINING_HOUR, | |
287 IDS_REMAINING_DAY); | |
288 formatter_[TimeFormat::kDuration][TimeFormat::kShort] = | |
289 new Formatter(IDS_DURATION_SHORT_SEC, | |
290 IDS_DURATION_SHORT_MIN, | |
291 IDS_DURATION_HOUR, | |
292 IDS_DURATION_DAY); | |
293 formatter_[TimeFormat::kDuration][TimeFormat::kLong] = | |
294 new Formatter(IDS_LONG_SEC, | |
295 IDS_LONG_MIN, | |
296 IDS_DURATION_HOUR, | |
297 IDS_DURATION_DAY, | |
298 IDS_LONG_MIN_1ST, | |
299 IDS_LONG_SEC_2ND, | |
300 IDS_DURATION_HOUR_1ST, | |
301 IDS_LONG_MIN_2ND, | |
302 IDS_DURATION_DAY_1ST, | |
303 IDS_DURATION_HOUR_2ND); | |
304 } | |
305 | |
306 FormatterContainer::~FormatterContainer() { | |
307 for (int type = 0; type < TimeFormat::kNType; ++type) | |
bartfab (slow)
2014/02/18 12:04:04
Nit: This for loop needs curly braces because its
Thiemo Nagel
2014/02/19 17:08:44
Done.
| |
308 for (int length = 0; length < TimeFormat::kNLength; ++length) | |
309 delete formatter_[type][length]; | |
bartfab (slow)
2014/02/18 12:04:04
Can you make formatter_ be an array of scoped_ptrs
Thiemo Nagel
2014/02/19 17:08:44
Done.
| |
310 } | |
311 | |
312 } // namespace ui | |
OLD | NEW |