OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2015 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 "base/i18n/message_formatter.h" | |
6 | |
7 #include "base/i18n/rtl.h" | |
8 #include "base/memory/scoped_ptr.h" | |
9 #include "base/strings/string_piece.h" | |
10 #include "base/strings/string_util.h" | |
11 #include "base/strings/utf_string_conversions.h" | |
12 #include "testing/gtest/include/gtest/gtest.h" | |
13 #include "third_party/icu/source/common/unicode/unistr.h" | |
14 #include "third_party/icu/source/i18n/unicode/datefmt.h" | |
15 | |
16 typedef testing::Test MessageFormatterTest; | |
17 | |
18 namespace base { | |
19 namespace i18n { | |
20 | |
21 class MessageFormatterTest : public testing::Test { | |
22 protected: | |
23 void SetUp() override { | |
24 original_locale_ = GetConfiguredLocale(); | |
25 SetICUDefaultLocale("en-US"); | |
26 } | |
27 void TearDown() override { | |
28 SetICUDefaultLocale(original_locale_); | |
29 } | |
Ryan Sleevi
2015/07/31 22:19:36
pedantic nit: Rather than using SetUp/TearDown, it
jungshik at Google
2015/08/01 14:00:58
Thanks for the suggestion. DOne
| |
30 | |
31 private: | |
32 std::string original_locale_; | |
33 }; | |
34 | |
35 namespace { | |
36 | |
37 void AppendFormattedDateTime(const scoped_ptr<icu::DateFormat>& df, | |
38 const Time& now, std::string* result) { | |
39 icu::UnicodeString formatted; | |
40 df->format(static_cast<UDate>(now.ToJsTime()), formatted). | |
41 toUTF8String(*result); | |
42 } | |
43 | |
44 } // namespace | |
45 | |
46 TEST_F(MessageFormatterTest, PluralNamedArgs) { | |
47 const string16 pattern = ASCIIToUTF16( | |
48 "{num_people, plural, " | |
49 "=0 {I met nobody in {place}.}" | |
50 "=1 {I met a person in {place}.}" | |
51 "other {I met # people in {place}.}}"); | |
52 | |
53 std::string result = UTF16ToASCII(MessageFormatter::FormatWithNamedArgs( | |
54 pattern, "num_people", 0, "place", "Paris")); | |
55 EXPECT_EQ("I met nobody in Paris.", result); | |
56 result = UTF16ToASCII(MessageFormatter::FormatWithNamedArgs( | |
57 pattern, "num_people", 1, "place", "Paris")); | |
58 EXPECT_EQ("I met a person in Paris.", result); | |
59 result = UTF16ToASCII(MessageFormatter::FormatWithNamedArgs( | |
60 pattern, "num_people", 5, "place", "Paris")); | |
61 EXPECT_EQ("I met 5 people in Paris.", result); | |
62 } | |
63 | |
64 TEST_F(MessageFormatterTest, PluralNamedArgsWithOffset) { | |
65 const string16 pattern = ASCIIToUTF16( | |
66 "{num_people, plural, offset:1 " | |
67 "=0 {I met nobody in {place}.}" | |
68 "=1 {I met {person} in {place}.}" | |
69 "=2 {I met {person} and one other person in {place}.}" | |
70 "=13 {I met {person} and a dozen other people in {place}.}" | |
71 "other {I met {person} and # other people in {place}.}}"); | |
72 | |
73 std::string result = UTF16ToASCII(MessageFormatter::FormatWithNamedArgs( | |
74 pattern, "num_people", 0, "place", "Paris")); | |
75 EXPECT_EQ("I met nobody in Paris.", result); | |
76 // {person} is ignored if {num_people} is 0. | |
77 result = UTF16ToASCII(MessageFormatter::FormatWithNamedArgs( | |
78 pattern, "num_people", 0, "place", "Paris", "person", "Peter")); | |
79 EXPECT_EQ("I met nobody in Paris.", result); | |
80 result = UTF16ToASCII(MessageFormatter::FormatWithNamedArgs( | |
81 pattern, "num_people", 1, "place", "Paris", "person", "Peter")); | |
82 EXPECT_EQ("I met Peter in Paris.", result); | |
83 result = UTF16ToASCII(MessageFormatter::FormatWithNamedArgs( | |
84 pattern, "num_people", 2, "place", "Paris", "person", "Peter")); | |
85 EXPECT_EQ("I met Peter and one other person in Paris.", result); | |
86 result = UTF16ToASCII(MessageFormatter::FormatWithNamedArgs( | |
87 pattern, "num_people", 13, "place", "Paris", "person", "Peter")); | |
88 EXPECT_EQ("I met Peter and a dozen other people in Paris.", result); | |
89 result = UTF16ToASCII(MessageFormatter::FormatWithNamedArgs( | |
90 pattern, "num_people", 50, "place", "Paris", "person", "Peter")); | |
91 EXPECT_EQ("I met Peter and 49 other people in Paris.", result); | |
92 } | |
93 | |
94 TEST_F(MessageFormatterTest, PluralNumberedArgs) { | |
95 const string16 pattern = ASCIIToUTF16( | |
96 "{1, plural, " | |
97 "=1 {The cert for {0} expired yesterday.}" | |
98 "=7 {The cert for {0} expired a week ago.}" | |
99 "other {The cert for {0} expired # days ago.}}"); | |
100 | |
101 std::string result = UTF16ToASCII(MessageFormatter::FormatWithNumberedArgs( | |
102 pattern, "example.com", 1)); | |
103 EXPECT_EQ("The cert for example.com expired yesterday.", result); | |
104 result = UTF16ToASCII(MessageFormatter::FormatWithNumberedArgs( | |
105 pattern, "example.com", 7)); | |
106 EXPECT_EQ("The cert for example.com expired a week ago.", result); | |
107 result = UTF16ToASCII(MessageFormatter::FormatWithNumberedArgs( | |
108 pattern, "example.com", 15)); | |
109 EXPECT_EQ("The cert for example.com expired 15 days ago.", result); | |
110 } | |
111 | |
112 TEST_F(MessageFormatterTest, PluralNumberedArgsWithDate) { | |
113 const string16 pattern = ASCIIToUTF16( | |
114 "{1, plural, " | |
115 "=1 {The cert for {0} expired yesterday. Today is {2,date,full}}" | |
116 "other {The cert for {0} expired # days ago. Today is {2,date,full}}}"); | |
117 | |
118 base::Time now = base::Time::Now(); | |
119 using icu::DateFormat; | |
120 scoped_ptr<DateFormat> df(DateFormat::createDateInstance(DateFormat::FULL)); | |
121 std::string second_sentence = " Today is "; | |
122 AppendFormattedDateTime(df, now, &second_sentence); | |
123 | |
124 std::string result = UTF16ToASCII(MessageFormatter::FormatWithNumberedArgs( | |
125 pattern, "example.com", 1, now)); | |
126 EXPECT_EQ("The cert for example.com expired yesterday." + second_sentence, | |
127 result); | |
128 result = UTF16ToASCII(MessageFormatter::FormatWithNumberedArgs( | |
129 pattern, "example.com", 15, now)); | |
130 EXPECT_EQ("The cert for example.com expired 15 days ago." + second_sentence, | |
131 result); | |
132 } | |
133 | |
134 TEST_F(MessageFormatterTest, DateTimeAndNumber) { | |
135 // Note that using 'mph' for all locales is not a good i18n practice. | |
136 const string16 pattern = ASCIIToUTF16( | |
137 "At {0,time, short} on {0,date, medium}, " | |
138 "there was {1} at building {2,number,integer}. " | |
139 "The speed of the wind was {3,number,###.#} mph."); | |
140 | |
141 using icu::DateFormat; | |
142 scoped_ptr<DateFormat> tf(DateFormat::createTimeInstance(DateFormat::SHORT)); | |
143 scoped_ptr<DateFormat> df(DateFormat::createDateInstance(DateFormat::MEDIUM)); | |
144 | |
145 base::Time now = base::Time::Now(); | |
146 std::string expected = "At "; | |
147 AppendFormattedDateTime(tf, now, &expected); | |
148 expected.append(" on "); | |
149 AppendFormattedDateTime(df, now, &expected); | |
150 expected.append(", there was an explosion at building 3. " | |
151 "The speed of the wind was 37.4 mph."); | |
152 | |
153 EXPECT_EQ(expected, UTF16ToASCII(MessageFormatter::FormatWithNumberedArgs( | |
154 pattern, now, "an explosion", 3, 37.413))); | |
155 } | |
156 | |
157 TEST_F(MessageFormatterTest, SelectorSingleOrMultiple) { | |
158 const string16 pattern = ASCIIToUTF16( | |
159 "{0, select," | |
160 "single {Select a file to upload.}" | |
161 "multiple {Select files to upload.}" | |
162 "other {UNUSED}}"); | |
163 | |
164 std::string result = UTF16ToASCII(MessageFormatter::FormatWithNumberedArgs( | |
165 pattern, "single")); | |
166 EXPECT_EQ("Select a file to upload.", result); | |
167 result = UTF16ToASCII(MessageFormatter::FormatWithNumberedArgs( | |
168 pattern, "multiple")); | |
169 EXPECT_EQ("Select files to upload.", result); | |
170 | |
171 // fallback if a parameter is not selectors specified in the message pattern. | |
172 result = UTF16ToASCII(MessageFormatter::FormatWithNumberedArgs( | |
173 pattern, "foobar")); | |
174 EXPECT_EQ("UNUSED", result); | |
175 } | |
176 | |
177 } // namespace i18n | |
178 } // namespace base | |
OLD | NEW |