OLD | NEW |
| (Empty) |
1 // Copyright (c) 2006-2008 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 "build/build_config.h" | |
6 | |
7 #include "base/basictypes.h" | |
8 #include "base/file_util.h" | |
9 #include "base/path_service.h" | |
10 #include "base/stl_util-inl.h" | |
11 #include "base/string_util.h" | |
12 #if defined(OS_WIN) | |
13 #include "base/win_util.h" | |
14 #endif | |
15 #include "chrome/common/chrome_paths.h" | |
16 #include "chrome/common/l10n_util.h" | |
17 #if !defined(OS_MACOSX) | |
18 #include "chrome/test/data/resource.h" | |
19 #endif | |
20 #include "testing/gtest/include/gtest/gtest.h" | |
21 #include "testing/platform_test.h" | |
22 #include "unicode/locid.h" | |
23 | |
24 namespace { | |
25 | |
26 class StringWrapper { | |
27 public: | |
28 explicit StringWrapper(const std::wstring& string) : string_(string) {} | |
29 const std::wstring& string() const { return string_; } | |
30 | |
31 private: | |
32 std::wstring string_; | |
33 | |
34 DISALLOW_COPY_AND_ASSIGN(StringWrapper); | |
35 }; | |
36 | |
37 l10n_util::TextDirection GetTextDirection(const char* locale_name) { | |
38 return l10n_util::GetTextDirectionForLocale(locale_name); | |
39 } | |
40 | |
41 } // namespace | |
42 | |
43 class L10nUtilTest : public PlatformTest { | |
44 }; | |
45 | |
46 #if defined(OS_WIN) | |
47 TEST_F(L10nUtilTest, GetString) { | |
48 std::wstring s = l10n_util::GetString(IDS_SIMPLE); | |
49 EXPECT_EQ(std::wstring(L"Hello World!"), s); | |
50 | |
51 s = l10n_util::GetStringF(IDS_PLACEHOLDERS, L"chrome", L"10"); | |
52 EXPECT_EQ(std::wstring(L"Hello, chrome. Your number is 10."), s); | |
53 | |
54 s = l10n_util::GetStringF(IDS_PLACEHOLDERS_2, 20); | |
55 EXPECT_EQ(std::wstring(L"You owe me $20."), s); | |
56 } | |
57 #endif // defined(OS_WIN) | |
58 | |
59 TEST_F(L10nUtilTest, TruncateString) { | |
60 std::wstring string(L"foooooey bxxxar baz"); | |
61 | |
62 // Make sure it doesn't modify the string if length > string length. | |
63 EXPECT_EQ(string, l10n_util::TruncateString(string, 100)); | |
64 | |
65 // Test no characters. | |
66 EXPECT_EQ(L"", l10n_util::TruncateString(string, 0)); | |
67 | |
68 // Test 1 character. | |
69 EXPECT_EQ(L"\x2026", l10n_util::TruncateString(string, 1)); | |
70 | |
71 // Test adds ... at right spot when there is enough room to break at a | |
72 // word boundary. | |
73 EXPECT_EQ(L"foooooey\x2026", l10n_util::TruncateString(string, 14)); | |
74 | |
75 // Test adds ... at right spot when there is not enough space in first word. | |
76 EXPECT_EQ(L"f\x2026", l10n_util::TruncateString(string, 2)); | |
77 | |
78 // Test adds ... at right spot when there is not enough room to break at a | |
79 // word boundary. | |
80 EXPECT_EQ(L"foooooey\x2026", l10n_util::TruncateString(string, 11)); | |
81 | |
82 // Test completely truncates string if break is on initial whitespace. | |
83 EXPECT_EQ(L"\x2026", l10n_util::TruncateString(L" ", 2)); | |
84 } | |
85 | |
86 void SetICUDefaultLocale(const std::wstring& locale_string) { | |
87 Locale locale(WideToASCII(locale_string).c_str()); | |
88 UErrorCode error_code = U_ZERO_ERROR; | |
89 Locale::setDefault(locale, error_code); | |
90 EXPECT_TRUE(U_SUCCESS(error_code)); | |
91 } | |
92 | |
93 #if defined(OS_WIN) || defined(OS_LINUX) | |
94 // We are disabling this test on MacOS because GetApplicationLocale() as an | |
95 // API isn't something that we'll easily be able to unit test in this manner. | |
96 // The meaning of that API, on the Mac, is "the locale used by Cocoa's main | |
97 // nib file", which clearly can't be stubbed by a test app that doesn't use | |
98 // Cocoa. | |
99 TEST_F(L10nUtilTest, GetAppLocale) { | |
100 // Use a temporary locale dir so we don't have to actually build the locale | |
101 // dlls for this test. | |
102 FilePath orig_locale_dir; | |
103 PathService::Get(chrome::DIR_LOCALES, &orig_locale_dir); | |
104 FilePath new_locale_dir; | |
105 EXPECT_TRUE(file_util::CreateNewTempDirectory( | |
106 FILE_PATH_LITERAL("l10n_util_test"), | |
107 &new_locale_dir)); | |
108 PathService::Override(chrome::DIR_LOCALES, new_locale_dir.ToWStringHack()); | |
109 // Make fake locale files. | |
110 std::string filenames[] = { | |
111 "en-US", | |
112 "en-GB", | |
113 "fr", | |
114 "es-419", | |
115 "es", | |
116 "zh-TW", | |
117 "zh-CN", | |
118 "he", | |
119 "fil", | |
120 "nb", | |
121 "or", | |
122 }; | |
123 | |
124 #if defined(OS_WIN) | |
125 static const char kLocaleFileExtension[] = ".dll"; | |
126 #elif defined(OS_POSIX) | |
127 static const char kLocaleFileExtension[] = ".pak"; | |
128 #endif | |
129 for (size_t i = 0; i < arraysize(filenames); ++i) { | |
130 FilePath filename = new_locale_dir.AppendASCII( | |
131 filenames[i] + kLocaleFileExtension); | |
132 file_util::WriteFile(filename, "", 0); | |
133 } | |
134 | |
135 // Keep a copy of ICU's default locale before we overwrite it. | |
136 Locale locale = Locale::getDefault(); | |
137 | |
138 SetICUDefaultLocale(L"en-US"); | |
139 EXPECT_EQ(L"en-US", l10n_util::GetApplicationLocale(L"")); | |
140 | |
141 SetICUDefaultLocale(L"en-GB"); | |
142 EXPECT_EQ(L"en-GB", l10n_util::GetApplicationLocale(L"")); | |
143 | |
144 SetICUDefaultLocale(L"fr-CA"); | |
145 EXPECT_EQ(L"fr", l10n_util::GetApplicationLocale(L"")); | |
146 | |
147 SetICUDefaultLocale(L"xx"); | |
148 EXPECT_EQ(L"en-US", l10n_util::GetApplicationLocale(L"")); | |
149 | |
150 SetICUDefaultLocale(L"en-US"); | |
151 EXPECT_EQ(L"fr", l10n_util::GetApplicationLocale(L"fr")); | |
152 EXPECT_EQ(L"fr", l10n_util::GetApplicationLocale(L"fr-CA")); | |
153 | |
154 SetICUDefaultLocale(L"en-US"); | |
155 // Aliases iw, no, tl to he, nb, fil. | |
156 EXPECT_EQ(L"he", l10n_util::GetApplicationLocale(L"iw")); | |
157 EXPECT_EQ(L"nb", l10n_util::GetApplicationLocale(L"no")); | |
158 EXPECT_EQ(L"fil", l10n_util::GetApplicationLocale(L"tl")); | |
159 // es-419 and es-XX (where XX is not Spain) should be | |
160 // mapped to es-419 (Latin American Spanish). | |
161 EXPECT_EQ(L"es-419", l10n_util::GetApplicationLocale(L"es-419")); | |
162 EXPECT_EQ(L"es", l10n_util::GetApplicationLocale(L"es-ES")); | |
163 EXPECT_EQ(L"es-419", l10n_util::GetApplicationLocale(L"es-AR")); | |
164 | |
165 SetICUDefaultLocale(L"es-MX"); | |
166 EXPECT_EQ(L"es-419", l10n_util::GetApplicationLocale(L"")); | |
167 | |
168 SetICUDefaultLocale(L"es-AR"); | |
169 EXPECT_EQ(L"es-419", l10n_util::GetApplicationLocale(L"")); | |
170 EXPECT_EQ(L"es", l10n_util::GetApplicationLocale(L"es")); | |
171 | |
172 SetICUDefaultLocale(L"es-ES"); | |
173 EXPECT_EQ(L"es", l10n_util::GetApplicationLocale(L"")); | |
174 | |
175 SetICUDefaultLocale(L"es"); | |
176 EXPECT_EQ(L"es", l10n_util::GetApplicationLocale(L"")); | |
177 | |
178 SetICUDefaultLocale(L"zh-HK"); | |
179 EXPECT_EQ(L"zh-TW", l10n_util::GetApplicationLocale(L"")); | |
180 EXPECT_EQ(L"zh-CN", l10n_util::GetApplicationLocale(L"zh-CN")); | |
181 | |
182 SetICUDefaultLocale(L"zh-MK"); | |
183 EXPECT_EQ(L"zh-TW", l10n_util::GetApplicationLocale(L"")); | |
184 | |
185 SetICUDefaultLocale(L"zh-SG"); | |
186 EXPECT_EQ(L"zh-CN", l10n_util::GetApplicationLocale(L"")); | |
187 | |
188 SetICUDefaultLocale(L"he"); | |
189 EXPECT_EQ(L"en-US", l10n_util::GetApplicationLocale(L"en")); | |
190 | |
191 #if defined(OS_WIN) | |
192 // Oriya should be blocked unless OS is Vista or newer. | |
193 if (win_util::GetWinVersion() < win_util::WINVERSION_VISTA) { | |
194 SetICUDefaultLocale(L"or"); | |
195 EXPECT_EQ(L"en-US", l10n_util::GetApplicationLocale(L"")); | |
196 SetICUDefaultLocale(L"en-GB"); | |
197 EXPECT_EQ(L"en-GB", l10n_util::GetApplicationLocale(L"or")); | |
198 } else { | |
199 SetICUDefaultLocale(L"or"); | |
200 EXPECT_EQ(L"or", l10n_util::GetApplicationLocale(L"")); | |
201 SetICUDefaultLocale(L"en-GB"); | |
202 EXPECT_EQ(L"or", l10n_util::GetApplicationLocale(L"or")); | |
203 } | |
204 #endif | |
205 | |
206 // Clean up. | |
207 PathService::Override(chrome::DIR_LOCALES, orig_locale_dir.ToWStringHack()); | |
208 file_util::Delete(new_locale_dir, true); | |
209 UErrorCode error_code = U_ZERO_ERROR; | |
210 Locale::setDefault(locale, error_code); | |
211 } | |
212 #endif | |
213 | |
214 TEST_F(L10nUtilTest, SortStringsUsingFunction) { | |
215 std::vector<StringWrapper*> strings; | |
216 strings.push_back(new StringWrapper(L"C")); | |
217 strings.push_back(new StringWrapper(L"d")); | |
218 strings.push_back(new StringWrapper(L"b")); | |
219 strings.push_back(new StringWrapper(L"a")); | |
220 l10n_util::SortStringsUsingMethod(L"en-US", &strings, &StringWrapper::string); | |
221 ASSERT_TRUE(L"a" == strings[0]->string()); | |
222 ASSERT_TRUE(L"b" == strings[1]->string()); | |
223 ASSERT_TRUE(L"C" == strings[2]->string()); | |
224 ASSERT_TRUE(L"d" == strings[3]->string()); | |
225 STLDeleteElements(&strings); | |
226 } | |
227 | |
228 TEST_F(L10nUtilTest, GetFirstStrongCharacterDirection) { | |
229 // Test pure LTR string. | |
230 std::wstring string(L"foo bar"); | |
231 EXPECT_EQ(l10n_util::LEFT_TO_RIGHT, | |
232 l10n_util::GetFirstStrongCharacterDirection(string)); | |
233 | |
234 // Test bidi string in which the first character with strong directionality | |
235 // is a character with type L. | |
236 string.assign(L"foo \x05d0 bar"); | |
237 EXPECT_EQ(l10n_util::LEFT_TO_RIGHT, | |
238 l10n_util::GetFirstStrongCharacterDirection(string)); | |
239 | |
240 // Test bidi string in which the first character with strong directionality | |
241 // is a character with type R. | |
242 string.assign(L"\x05d0 foo bar"); | |
243 EXPECT_EQ(l10n_util::RIGHT_TO_LEFT, | |
244 l10n_util::GetFirstStrongCharacterDirection(string)); | |
245 | |
246 // Test bidi string which starts with a character with weak directionality | |
247 // and in which the first character with strong directionality is a character | |
248 // with type L. | |
249 string.assign(L"!foo \x05d0 bar"); | |
250 EXPECT_EQ(l10n_util::LEFT_TO_RIGHT, | |
251 l10n_util::GetFirstStrongCharacterDirection(string)); | |
252 | |
253 // Test bidi string which starts with a character with weak directionality | |
254 // and in which the first character with strong directionality is a character | |
255 // with type R. | |
256 string.assign(L",\x05d0 foo bar"); | |
257 EXPECT_EQ(l10n_util::RIGHT_TO_LEFT, | |
258 l10n_util::GetFirstStrongCharacterDirection(string)); | |
259 | |
260 // Test bidi string in which the first character with strong directionality | |
261 // is a character with type LRE. | |
262 string.assign(L"\x202a \x05d0 foo bar"); | |
263 EXPECT_EQ(l10n_util::LEFT_TO_RIGHT, | |
264 l10n_util::GetFirstStrongCharacterDirection(string)); | |
265 | |
266 // Test bidi string in which the first character with strong directionality | |
267 // is a character with type LRO. | |
268 string.assign(L"\x202d \x05d0 foo bar"); | |
269 EXPECT_EQ(l10n_util::LEFT_TO_RIGHT, | |
270 l10n_util::GetFirstStrongCharacterDirection(string)); | |
271 | |
272 // Test bidi string in which the first character with strong directionality | |
273 // is a character with type RLE. | |
274 string.assign(L"\x202b foo \x05d0 bar"); | |
275 EXPECT_EQ(l10n_util::RIGHT_TO_LEFT, | |
276 l10n_util::GetFirstStrongCharacterDirection(string)); | |
277 | |
278 // Test bidi string in which the first character with strong directionality | |
279 // is a character with type RLO. | |
280 string.assign(L"\x202e foo \x05d0 bar"); | |
281 EXPECT_EQ(l10n_util::RIGHT_TO_LEFT, | |
282 l10n_util::GetFirstStrongCharacterDirection(string)); | |
283 | |
284 // Test bidi string in which the first character with strong directionality | |
285 // is a character with type AL. | |
286 string.assign(L"\x0622 foo \x05d0 bar"); | |
287 EXPECT_EQ(l10n_util::RIGHT_TO_LEFT, | |
288 l10n_util::GetFirstStrongCharacterDirection(string)); | |
289 | |
290 // Test a string without strong directionality characters. | |
291 string.assign(L",!.{}"); | |
292 EXPECT_EQ(l10n_util::LEFT_TO_RIGHT, | |
293 l10n_util::GetFirstStrongCharacterDirection(string)); | |
294 | |
295 // Test empty string. | |
296 string.assign(L""); | |
297 EXPECT_EQ(l10n_util::LEFT_TO_RIGHT, | |
298 l10n_util::GetFirstStrongCharacterDirection(string)); | |
299 | |
300 // Test characters in non-BMP (e.g. Phoenician letters. Please refer to | |
301 // http://demo.icu-project.org/icu-bin/ubrowse?scr=151&b=10910 for more | |
302 // information). | |
303 #if defined(WCHAR_T_IS_UTF32) | |
304 string.assign(L" ! \x10910" L"abc 123"); | |
305 #elif defined(WCHAR_T_IS_UTF16) | |
306 string.assign(L" ! \xd802\xdd10" L"abc 123"); | |
307 #else | |
308 #error wchar_t should be either UTF-16 or UTF-32 | |
309 #endif | |
310 EXPECT_EQ(l10n_util::RIGHT_TO_LEFT, | |
311 l10n_util::GetFirstStrongCharacterDirection(string)); | |
312 | |
313 #if defined(WCHAR_T_IS_UTF32) | |
314 string.assign(L" ! \x10401" L"abc 123"); | |
315 #elif defined(WCHAR_T_IS_UTF16) | |
316 string.assign(L" ! \xd801\xdc01" L"abc 123"); | |
317 #else | |
318 #error wchar_t should be either UTF-16 or UTF-32 | |
319 #endif | |
320 EXPECT_EQ(l10n_util::LEFT_TO_RIGHT, | |
321 l10n_util::GetFirstStrongCharacterDirection(string)); | |
322 } | |
323 | |
324 typedef struct { | |
325 std::wstring path; | |
326 std::wstring wrapped_path; | |
327 } PathAndWrappedPath; | |
328 | |
329 TEST_F(L10nUtilTest, WrapPathWithLTRFormatting) { | |
330 std::wstring kSeparator; | |
331 kSeparator.push_back(static_cast<wchar_t>(FilePath::kSeparators[0])); | |
332 const PathAndWrappedPath test_data[] = { | |
333 // Test common path, such as "c:\foo\bar". | |
334 { L"c:" + kSeparator + L"foo" + kSeparator + L"bar", | |
335 L"\x202a"L"c:" + kSeparator + L"foo" + kSeparator + | |
336 L"bar\x202c" | |
337 }, | |
338 // Test path with file name, such as "c:\foo\bar\test.jpg". | |
339 { L"c:" + kSeparator + L"foo" + kSeparator + L"bar" + kSeparator + | |
340 L"test.jpg", | |
341 L"\x202a"L"c:" + kSeparator + L"foo" + kSeparator + | |
342 L"bar" + kSeparator + L"test.jpg\x202c" | |
343 }, | |
344 // Test path ending with punctuation, such as "c:\(foo)\bar.". | |
345 { L"c:" + kSeparator + L"(foo)" + kSeparator + L"bar.", | |
346 L"\x202a"L"c:" + kSeparator + L"(foo)" + kSeparator + | |
347 L"bar.\x202c" | |
348 }, | |
349 // Test path ending with separator, such as "c:\foo\bar\". | |
350 { L"c:" + kSeparator + L"foo" + kSeparator + L"bar" + kSeparator, | |
351 L"\x202a"L"c:" + kSeparator + L"foo" + kSeparator + | |
352 L"bar" + kSeparator + L"\x202c", | |
353 }, | |
354 // Test path with RTL character. | |
355 { L"c:" + kSeparator + L"\x05d0", | |
356 L"\x202a"L"c:" + kSeparator + L"\x05d0\x202c", | |
357 }, | |
358 // Test path with 2 level RTL directory names. | |
359 { L"c:" + kSeparator + L"\x05d0" + kSeparator + L"\x0622", | |
360 L"\x202a"L"c:" + kSeparator + L"\x05d0" + kSeparator + | |
361 L"\x0622\x202c", | |
362 }, | |
363 // Test path with mixed RTL/LTR directory names and ending with punctuation. | |
364 { L"c:" + kSeparator + L"\x05d0" + kSeparator + L"\x0622" + kSeparator + | |
365 L"(foo)" + kSeparator + L"b.a.r.", | |
366 L"\x202a"L"c:" + kSeparator + L"\x05d0" + kSeparator + | |
367 L"\x0622" + kSeparator + L"(foo)" + kSeparator + | |
368 L"b.a.r.\x202c", | |
369 }, | |
370 // Test path without driver name, such as "/foo/bar/test/jpg". | |
371 { kSeparator + L"foo" + kSeparator + L"bar" + kSeparator + L"test.jpg", | |
372 L"\x202a" + kSeparator + L"foo" + kSeparator + L"bar" + | |
373 kSeparator + L"test.jpg" + L"\x202c" | |
374 }, | |
375 // Test path start with current directory, such as "./foo". | |
376 { L"." + kSeparator + L"foo", | |
377 L"\x202a"L"." + kSeparator + L"foo" + L"\x202c" | |
378 }, | |
379 // Test path start with parent directory, such as "../foo/bar.jpg". | |
380 { L".." + kSeparator + L"foo" + kSeparator + L"bar.jpg", | |
381 L"\x202a"L".." + kSeparator + L"foo" + kSeparator + | |
382 L"bar.jpg" + L"\x202c" | |
383 }, | |
384 // Test absolute path, such as "//foo/bar.jpg". | |
385 { kSeparator + kSeparator + L"foo" + kSeparator + L"bar.jpg", | |
386 L"\x202a" + kSeparator + kSeparator + L"foo" + kSeparator + | |
387 L"bar.jpg" + L"\x202c" | |
388 }, | |
389 // Test path with mixed RTL/LTR directory names. | |
390 { L"c:" + kSeparator + L"foo" + kSeparator + L"\x05d0" + kSeparator + | |
391 L"\x0622" + kSeparator + L"\x05d1.jpg", | |
392 L"\x202a"L"c:" + kSeparator + L"foo" + kSeparator + L"\x05d0" + | |
393 kSeparator + L"\x0622" + kSeparator + L"\x05d1.jpg" + L"\x202c", | |
394 }, | |
395 // Test empty path. | |
396 { L"", | |
397 L"\x202a\x202c" | |
398 } | |
399 }; | |
400 for (unsigned int i = 0; i < arraysize(test_data); ++i) { | |
401 string16 localized_file_path_string; | |
402 FilePath path = FilePath::FromWStringHack(test_data[i].path); | |
403 l10n_util::WrapPathWithLTRFormatting(path, &localized_file_path_string); | |
404 std::wstring wrapped_path = UTF16ToWide(localized_file_path_string); | |
405 EXPECT_EQ(wrapped_path, test_data[i].wrapped_path); | |
406 } | |
407 } | |
408 | |
409 TEST_F(L10nUtilTest, GetTextDirection) { | |
410 EXPECT_EQ(l10n_util::RIGHT_TO_LEFT, GetTextDirection("ar")); | |
411 EXPECT_EQ(l10n_util::RIGHT_TO_LEFT, GetTextDirection("ar_EG")); | |
412 EXPECT_EQ(l10n_util::RIGHT_TO_LEFT, GetTextDirection("he")); | |
413 EXPECT_EQ(l10n_util::RIGHT_TO_LEFT, GetTextDirection("he_IL")); | |
414 // iw is an obsolete code for Hebrew. | |
415 EXPECT_EQ(l10n_util::RIGHT_TO_LEFT, GetTextDirection("iw")); | |
416 #if 0 | |
417 // Enable these when we localize to Farsi, Urdu, Azerbaijani | |
418 // written in Arabic and Dhivehi. At the moment, our copy of | |
419 // ICU data does not have entry for them. | |
420 EXPECT_EQ(l10n_util::RIGHT_TO_LEFT, GetTextDirection("fa")); | |
421 EXPECT_EQ(l10n_util::RIGHT_TO_LEFT, GetTextDirection("ur")); | |
422 EXPECT_EQ(l10n_util::RIGHT_TO_LEFT, GetTextDirection("az_Arab")); | |
423 // Dhivehi that uses Thaana script. | |
424 EXPECT_EQ(l10n_util::RIGHT_TO_LEFT, GetTextDirection("dv")); | |
425 #endif | |
426 EXPECT_EQ(l10n_util::LEFT_TO_RIGHT, GetTextDirection("en")); | |
427 // Chinese in China with '-'. | |
428 EXPECT_EQ(l10n_util::LEFT_TO_RIGHT, GetTextDirection("zh-CN")); | |
429 // Filipino : 3-letter code | |
430 EXPECT_EQ(l10n_util::LEFT_TO_RIGHT, GetTextDirection("fil")); | |
431 // Russian | |
432 EXPECT_EQ(l10n_util::LEFT_TO_RIGHT, GetTextDirection("ru")); | |
433 // Japanese that uses multiple scripts | |
434 EXPECT_EQ(l10n_util::LEFT_TO_RIGHT, GetTextDirection("ja")); | |
435 } | |
OLD | NEW |