Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(103)

Side by Side Diff: app/l10n_util.cc

Issue 449077: Setting the ICU default locale is made explicit. This leads to a few more... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | app/l10n_util_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "app/l10n_util.h" 5 #include "app/l10n_util.h"
6 6
7 #include <cstdlib> 7 #include <cstdlib>
8 #include "app/app_paths.h" 8 #include "app/app_paths.h"
9 #include "app/app_switches.h" 9 #include "app/app_switches.h"
10 #include "app/gfx/canvas.h" 10 #include "app/gfx/canvas.h"
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 "zh-TW", // Chinese (Traditional) 181 "zh-TW", // Chinese (Traditional)
182 "zu", // Zulu 182 "zu", // Zulu
183 }; 183 };
184 184
185 185
186 // Get language and region from the OS. 186 // Get language and region from the OS.
187 void GetLanguageAndRegionFromOS(std::string* lang, std::string* region) { 187 void GetLanguageAndRegionFromOS(std::string* lang, std::string* region) {
188 // Later we may have to change this to be OS-dependent so that 188 // Later we may have to change this to be OS-dependent so that
189 // it's not affected by ICU's default locale. It's all right 189 // it's not affected by ICU's default locale. It's all right
190 // to do this way because SetICUDefaultLocale is internal 190 // to do this way because SetICUDefaultLocale is internal
191 // to this file and we know where/when it's called. 191 // to this file and we know that it's not yet called when this function
192 // is called.
192 icu::Locale locale = icu::Locale::getDefault(); 193 icu::Locale locale = icu::Locale::getDefault();
193 const char* language = locale.getLanguage(); 194 const char* language = locale.getLanguage();
194 const char* country = locale.getCountry(); 195 const char* country = locale.getCountry();
195 DCHECK(language); 196 DCHECK(language);
196 *lang = language; 197 *lang = language;
197 *region = country; 198 *region = country;
198 } 199 }
199 200
200 // Convert Chrome locale name to ICU locale name 201 // Convert Chrome locale name to ICU locale name
201 std::string ICULocaleName(const std::string& locale_string) { 202 std::string ICULocaleName(const std::string& locale_string) {
(...skipping 16 matching lines...) Expand all
218 return lang; 219 return lang;
219 } 220 }
220 return "es-MX"; 221 return "es-MX";
221 } 222 }
222 // Currently, Chrome has only "es" and "es-419", but later we may have 223 // Currently, Chrome has only "es" and "es-419", but later we may have
223 // more specific "es-RR". 224 // more specific "es-RR".
224 return locale_string; 225 return locale_string;
225 } 226 }
226 227
227 // Sets the default locale of ICU. 228 // Sets the default locale of ICU.
228 // When the application locale (UI locale) of Chrome is specified with 229 // Once the application locale of Chrome in GetApplicationLocale is determined,
229 // '--lang' command line flag or 'intl.app_locale' entry in the "Preferences",
230 // the default locale of ICU need to be changed to match the application locale 230 // the default locale of ICU need to be changed to match the application locale
231 // so that ICU functions work correctly in a locale-dependent manner. 231 // so that ICU functions work correctly in a locale-dependent manner.
232 // This is handy in that we don't have to call GetApplicationLocale() 232 // This is handy in that we don't have to call GetApplicationLocale()
233 // everytime we call locale-dependent ICU APIs as long as we make sure 233 // everytime we call locale-dependent ICU APIs as long as we make sure
234 // that this is called before any locale-dependent API is called. 234 // that this is called before any locale-dependent API is called.
235 UBool SetICUDefaultLocale(const std::string& locale_string) { 235 void SetICUDefaultLocale(const std::string& locale_string) {
236 icu::Locale locale(ICULocaleName(locale_string).c_str()); 236 icu::Locale locale(ICULocaleName(locale_string).c_str());
237 UErrorCode error_code = U_ZERO_ERROR; 237 UErrorCode error_code = U_ZERO_ERROR;
238 icu::Locale::setDefault(locale, error_code); 238 icu::Locale::setDefault(locale, error_code);
239 // This return value is actually bogus because Locale object is 239 // This return value is actually bogus because Locale object is
240 // an ID and setDefault seems to always succeed (regardless of the 240 // an ID and setDefault seems to always succeed (regardless of the
241 // presence of actual locale data). However, 241 // presence of actual locale data). However,
242 // it does not hurt to have it as a sanity check. 242 // it does not hurt to have it as a sanity check.
243 return U_SUCCESS(error_code); 243 DCHECK(U_SUCCESS(error_code));
244 } 244 }
245 245
246 // Returns true if |locale_name| has an alias in the ICU data file. 246 // Returns true if |locale_name| has an alias in the ICU data file.
247 bool IsDuplicateName(const std::string& locale_name) { 247 bool IsDuplicateName(const std::string& locale_name) {
248 static const char* const kDuplicateNames[] = { 248 static const char* const kDuplicateNames[] = {
249 "en", 249 "en",
250 "pt", 250 "pt",
251 "zh", 251 "zh",
252 "zh_hans_cn", 252 "zh_hans_cn",
253 "zh_hant_tw" 253 "zh_hant_tw"
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
290 return !IsLocaleNameTranslated("en", locale_name); 290 return !IsLocaleNameTranslated("en", locale_name);
291 } 291 }
292 292
293 bool IsLocaleAvailable(const std::string& locale, 293 bool IsLocaleAvailable(const std::string& locale,
294 const FilePath& locale_path) { 294 const FilePath& locale_path) {
295 // If locale has any illegal characters in it, we don't want to try to 295 // If locale has any illegal characters in it, we don't want to try to
296 // load it because it may be pointing outside the locale data file directory. 296 // load it because it may be pointing outside the locale data file directory.
297 if (!file_util::IsFilenameLegal(ASCIIToUTF16(locale))) 297 if (!file_util::IsFilenameLegal(ASCIIToUTF16(locale)))
298 return false; 298 return false;
299 299
300 // IsLocalePartiallyPopulated() can be called here for an early return w/o
301 // checking the resource availability below. It'd help when Chrome is run
302 // under a system locale Chrome is not localized to (e.g.Farsi on Linux),
303 // but it'd slow down the start up time a little bit for locales Chrome is
304 // localized to. So, we don't call it here.
300 if (!l10n_util::IsLocaleSupportedByOS(locale)) 305 if (!l10n_util::IsLocaleSupportedByOS(locale))
301 return false; 306 return false;
302 307
303 FilePath test_path = locale_path; 308 FilePath test_path = locale_path;
304 test_path = 309 test_path =
305 test_path.AppendASCII(locale).ReplaceExtension(kLocaleFileExtension); 310 test_path.AppendASCII(locale).ReplaceExtension(kLocaleFileExtension);
306 return file_util::PathExists(test_path) && SetICUDefaultLocale(locale); 311 return file_util::PathExists(test_path);
307 } 312 }
308 313
309 bool CheckAndResolveLocale(const std::string& locale, 314 bool CheckAndResolveLocale(const std::string& locale,
310 const FilePath& locale_path, 315 const FilePath& locale_path,
311 std::string* resolved_locale) { 316 std::string* resolved_locale) {
312 if (IsLocaleAvailable(locale, locale_path)) { 317 if (IsLocaleAvailable(locale, locale_path)) {
313 *resolved_locale = locale; 318 *resolved_locale = locale;
314 return true; 319 return true;
315 } 320 }
316 // If the locale matches language but not country, use that instead. 321 // If the locale matches language but not country, use that instead.
317 // TODO(jungshik) : Nothing is done about languages that Chrome 322 // TODO(jungshik) : Nothing is done about languages that Chrome
318 // does not support but available on Windows. We fall 323 // does not support but available on Windows. We fall
319 // back to en-US in GetApplicationLocale so that it's a not critical, 324 // back to en-US in GetApplicationLocale so that it's a not critical,
320 // but we can do better. 325 // but we can do better.
321 std::string::size_type hyphen_pos = locale.find(L'-'); 326 std::string::size_type hyphen_pos = locale.find('-');
322 if (hyphen_pos != std::string::npos && hyphen_pos > 0) { 327 if (hyphen_pos != std::string::npos && hyphen_pos > 0) {
323 std::string lang(locale, 0, hyphen_pos); 328 std::string lang(locale, 0, hyphen_pos);
324 std::string region(locale, hyphen_pos + 1); 329 std::string region(locale, hyphen_pos + 1);
325 std::string tmp_locale(lang); 330 std::string tmp_locale(lang);
326 // Map es-RR other than es-ES to es-419 (Chrome's Latin American 331 // Map es-RR other than es-ES to es-419 (Chrome's Latin American
327 // Spanish locale). 332 // Spanish locale).
328 if (LowerCaseEqualsASCII(lang, "es") && !LowerCaseEqualsASCII(region, "es")) 333 if (LowerCaseEqualsASCII(lang, "es") && !LowerCaseEqualsASCII(region, "es"))
329 tmp_locale.append("-419"); 334 tmp_locale.append("-419");
330 else if (LowerCaseEqualsASCII(lang, "zh")) { 335 else if (LowerCaseEqualsASCII(lang, "zh")) {
331 // Map zh-HK and zh-MK to zh-TW. Otherwise, zh-FOO is mapped to zh-CN. 336 // Map zh-HK and zh-MK to zh-TW. Otherwise, zh-FOO is mapped to zh-CN.
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
456 #elif defined(OS_LINUX) 461 #elif defined(OS_LINUX)
457 // On Linux, we also check LANGUAGE environment variable, which is supported 462 // On Linux, we also check LANGUAGE environment variable, which is supported
458 // by gettext to specify a priority list of prefered languages. 463 // by gettext to specify a priority list of prefered languages.
459 const char* env_language = ::getenv("LANGUAGE"); 464 const char* env_language = ::getenv("LANGUAGE");
460 if (env_language) 465 if (env_language)
461 SplitAndNormalizeLanguageList(env_language, &candidates); 466 SplitAndNormalizeLanguageList(env_language, &candidates);
462 467
463 // Only fallback to the system locale if LANGUAGE is not specified. 468 // Only fallback to the system locale if LANGUAGE is not specified.
464 // We emulate gettext's behavior here, which ignores LANG/LC_MESSAGES/LC_ALL 469 // We emulate gettext's behavior here, which ignores LANG/LC_MESSAGES/LC_ALL
465 // when LANGUAGE is specified. If no language specified in LANGUAGE is valid, 470 // when LANGUAGE is specified. If no language specified in LANGUAGE is valid,
466 // then just fallback to the default language, which is en-US for us. 471 // then just fallback to the locale based on LC_ALL/LANG.
467 if (candidates.empty()) 472 if (candidates.empty())
468 candidates.push_back(system_locale); 473 candidates.push_back(system_locale);
469 #endif 474 #endif
470 475
471 std::vector<std::string>::const_iterator i = candidates.begin(); 476 std::vector<std::string>::const_iterator i = candidates.begin();
472 for (; i != candidates.end(); ++i) { 477 for (; i != candidates.end(); ++i) {
473 if (CheckAndResolveLocale(*i, locale_path, &resolved_locale)) 478 if (CheckAndResolveLocale(*i, locale_path, &resolved_locale)) {
479 SetICUDefaultLocale(resolved_locale);
474 return resolved_locale; 480 return resolved_locale;
481 }
475 } 482 }
476 483
477 // Fallback on en-US. 484 // Fallback on en-US.
478 const std::string fallback_locale("en-US"); 485 const std::string fallback_locale("en-US");
479 if (IsLocaleAvailable(fallback_locale, locale_path)) 486 if (IsLocaleAvailable(fallback_locale, locale_path)) {
487 SetICUDefaultLocale(fallback_locale);
480 return fallback_locale; 488 return fallback_locale;
489 }
481 490
482 // No locale data file was found; we shouldn't get here. 491 // No locale data file was found; we shouldn't get here.
483 NOTREACHED(); 492 NOTREACHED();
484 493
485 return std::string(); 494 return std::string();
486 495
487 #else // !defined(OS_MACOSX) 496 #else // !defined(OS_MACOSX)
488 497
489 // Use any override (Cocoa for the browser), otherwise use the command line 498 // Use any override (Cocoa for the browser), otherwise use the command line
490 // argument. 499 // argument.
491 std::string app_locale = l10n_util::GetLocaleOverride(); 500 std::string app_locale = l10n_util::GetLocaleOverride();
492 if (app_locale.empty()) { 501 if (app_locale.empty()) {
493 const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess(); 502 const CommandLine& parsed_command_line = *CommandLine::ForCurrentProcess();
494 app_locale = parsed_command_line.GetSwitchValueASCII(switches::kLang); 503 app_locale = parsed_command_line.GetSwitchValueASCII(switches::kLang);
495 } 504 }
496 505
497 // The above should handle all of the cases Chrome normally hits, but for some 506 // The above should handle all of the cases Chrome normally hits, but for some
498 // unit tests, we need something to fall back too. 507 // unit tests, we need something to fall back too.
499 if (app_locale.empty()) 508 if (app_locale.empty())
500 app_locale = "en-US"; 509 app_locale = "en-US";
501 510
502 // Windows/Linux call CheckAndResolveLocale which calls IsLocaleAvailable 511 // Windows/Linux call SetICUDefaultLocale after determining the actual locale
503 // which calls SetICUDefaultLocale to let ICU use the same locale. Mac 512 // with CheckAndResolveLocal to make ICU APIs work in that locale.
504 // doesn't use a locale directory tree of resources (it uses Mac style 513 // Mac doesn't use a locale directory tree of resources (it uses Mac style
505 // resources), so mirror that ICU behavior by calling SetICUDefaultLocale 514 // resources), so mirror the Windows/Linux behavior of calling
506 // directly. 515 // SetICUDefaultLocale.
507 UBool icu_set = SetICUDefaultLocale(app_locale); 516 SetICUDefaultLocale(app_locale);
508 DCHECK(icu_set);
509 return app_locale; 517 return app_locale;
510 #endif // !defined(OS_MACOSX) 518 #endif // !defined(OS_MACOSX)
511 } 519 }
512 520
513 string16 GetDisplayNameForLocale(const std::string& locale_code, 521 string16 GetDisplayNameForLocale(const std::string& locale_code,
514 const std::string& display_locale, 522 const std::string& display_locale,
515 bool is_for_ui) { 523 bool is_for_ui) {
516 UErrorCode error = U_ZERO_ERROR; 524 UErrorCode error = U_ZERO_ERROR;
517 const int buffer_size = 1024; 525 const int buffer_size = 1024;
518 526
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after
777 (gtk_dir == GTK_TEXT_DIR_LTR) ? LEFT_TO_RIGHT : RIGHT_TO_LEFT; 785 (gtk_dir == GTK_TEXT_DIR_LTR) ? LEFT_TO_RIGHT : RIGHT_TO_LEFT;
778 #else 786 #else
779 const icu::Locale& locale = icu::Locale::getDefault(); 787 const icu::Locale& locale = icu::Locale::getDefault();
780 g_text_direction = GetTextDirectionForLocale(locale.getName()); 788 g_text_direction = GetTextDirectionForLocale(locale.getName());
781 #endif 789 #endif
782 } 790 }
783 return g_text_direction; 791 return g_text_direction;
784 } 792 }
785 793
786 TextDirection GetTextDirectionForLocale(const char* locale_name) { 794 TextDirection GetTextDirectionForLocale(const char* locale_name) {
787 UScriptCode scripts[10]; // 10 scripts should be enough for any locale. 795 UErrorCode status = U_ZERO_ERROR;
788 UErrorCode error = U_ZERO_ERROR; 796 ULayoutType layout_dir = uloc_getCharacterOrientation(locale_name, &status);
789 int n = uscript_getCode(locale_name, scripts, 10, &error); 797 DCHECK(U_SUCCESS(status));
790 DCHECK(U_SUCCESS(error) && n > 0); 798 // Treat anything other than RTL as LTR.
791 799 return (layout_dir != ULOC_LAYOUT_RTL) ? LEFT_TO_RIGHT : RIGHT_TO_LEFT;
792 // Checking Arabic and Hebrew scripts cover Arabic, Hebrew, Farsi,
793 // Urdu and Azerbaijani written in Arabic. Syriac script
794 // (another RTL) is not a living script and we didn't yet localize
795 // to locales using other living RTL scripts such as Thaana and N'ko.
796 // TODO(jungshik): Use a new ICU API, uloc_getCharacterOrientation to avoid
797 // 'hardcoded-comparision' with Arabic and Hebrew scripts once we
798 // upgrade ICU to 4.0 or later or port it to our copy of ICU.
799 if (scripts[0] == USCRIPT_ARABIC || scripts[0] == USCRIPT_HEBREW)
800 return RIGHT_TO_LEFT;
801 return LEFT_TO_RIGHT;
802 } 800 }
803 801
804 TextDirection GetFirstStrongCharacterDirection(const std::wstring& text) { 802 TextDirection GetFirstStrongCharacterDirection(const std::wstring& text) {
805 #if defined(WCHAR_T_IS_UTF32) 803 #if defined(WCHAR_T_IS_UTF32)
806 string16 text_utf16 = WideToUTF16(text); 804 string16 text_utf16 = WideToUTF16(text);
807 const UChar* string = text_utf16.c_str(); 805 const UChar* string = text_utf16.c_str();
808 #else 806 #else
809 const UChar* string = text.c_str(); 807 const UChar* string = text.c_str();
810 #endif 808 #endif
811 size_t length = text.length(); 809 size_t length = text.length();
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after
1060 } 1058 }
1061 1059
1062 void BiDiLineIterator::GetLogicalRun(int start, 1060 void BiDiLineIterator::GetLogicalRun(int start,
1063 int* end, 1061 int* end,
1064 UBiDiLevel* level) { 1062 UBiDiLevel* level) {
1065 DCHECK(bidi_ != NULL); 1063 DCHECK(bidi_ != NULL);
1066 ubidi_getLogicalRun(bidi_, start, end, level); 1064 ubidi_getLogicalRun(bidi_, start, end, level);
1067 } 1065 }
1068 1066
1069 } // namespace l10n_util 1067 } // namespace l10n_util
OLDNEW
« no previous file with comments | « no previous file | app/l10n_util_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698