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