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