OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 #if defined(TOOLKIT_USES_GTK) | 7 #if defined(TOOLKIT_USES_GTK) |
8 #include <glib/gutils.h> | 8 #include <glib/gutils.h> |
9 #endif | 9 #endif |
10 | 10 |
(...skipping 11 matching lines...) Expand all Loading... |
22 #include "base/path_service.h" | 22 #include "base/path_service.h" |
23 #include "base/scoped_ptr.h" | 23 #include "base/scoped_ptr.h" |
24 #include "base/string16.h" | 24 #include "base/string16.h" |
25 #include "base/string_number_conversions.h" | 25 #include "base/string_number_conversions.h" |
26 #include "base/string_split.h" | 26 #include "base/string_split.h" |
27 #include "base/sys_string_conversions.h" | 27 #include "base/sys_string_conversions.h" |
28 #include "base/utf_string_conversions.h" | 28 #include "base/utf_string_conversions.h" |
29 #include "build/build_config.h" | 29 #include "build/build_config.h" |
30 #include "gfx/canvas.h" | 30 #include "gfx/canvas.h" |
31 #include "unicode/rbbi.h" | 31 #include "unicode/rbbi.h" |
| 32 #include "unicode/uloc.h" |
32 | 33 |
33 #if defined(OS_MACOSX) | 34 #if defined(OS_MACOSX) |
34 #include "app/l10n_util_mac.h" | 35 #include "app/l10n_util_mac.h" |
35 #elif defined(OS_WIN) | 36 #elif defined(OS_WIN) |
36 #include "app/l10n_util_win.h" | 37 #include "app/l10n_util_win.h" |
37 #endif | 38 #endif |
38 | 39 |
39 namespace { | 40 namespace { |
40 | 41 |
41 #if defined(OS_WIN) | 42 #if defined(OS_WIN) |
(...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
468 display_locale.c_str(), | 469 display_locale.c_str(), |
469 WriteInto(&display_name, buffer_size + 1), buffer_size, &error); | 470 WriteInto(&display_name, buffer_size + 1), buffer_size, &error); |
470 DCHECK(U_SUCCESS(error)); | 471 DCHECK(U_SUCCESS(error)); |
471 display_name.resize(actual_size); | 472 display_name.resize(actual_size); |
472 // Add an RTL mark so parentheses are properly placed. | 473 // Add an RTL mark so parentheses are properly placed. |
473 if (is_for_ui && base::i18n::IsRTL()) | 474 if (is_for_ui && base::i18n::IsRTL()) |
474 display_name.push_back(static_cast<char16>(base::i18n::kRightToLeftMark)); | 475 display_name.push_back(static_cast<char16>(base::i18n::kRightToLeftMark)); |
475 return display_name; | 476 return display_name; |
476 } | 477 } |
477 | 478 |
| 479 std::string NormalizeLocale(const std::string& locale) { |
| 480 std::string normalized_locale(locale); |
| 481 std::replace(normalized_locale.begin(), normalized_locale.end(), '-', '_'); |
| 482 |
| 483 return normalized_locale; |
| 484 } |
| 485 |
| 486 void GetParentLocales(const std::string& current_locale, |
| 487 std::vector<std::string>* parent_locales) { |
| 488 std::string locale(NormalizeLocale(current_locale)); |
| 489 |
| 490 const int kNameCapacity = 256; |
| 491 char parent[kNameCapacity]; |
| 492 base::strlcpy(parent, locale.c_str(), kNameCapacity); |
| 493 parent_locales->push_back(parent); |
| 494 UErrorCode err = U_ZERO_ERROR; |
| 495 while (uloc_getParent(parent, parent, kNameCapacity, &err) > 0) { |
| 496 if (U_FAILURE(err)) |
| 497 break; |
| 498 parent_locales->push_back(parent); |
| 499 } |
| 500 } |
| 501 |
| 502 bool IsValidLocaleSyntax(const std::string& locale) { |
| 503 // Check that the length is plausible. |
| 504 if (locale.size() < 2 || locale.size() >= ULOC_FULLNAME_CAPACITY) |
| 505 return false; |
| 506 |
| 507 // Strip off the part after an '@' sign, which might contain keywords, |
| 508 // as in en_IE@currency=IEP or fr@collation=phonebook;calendar=islamic-civil. |
| 509 // We don't validate that part much, just check that there's at least one |
| 510 // equals sign in a plausible place. |
| 511 std::string prefix = locale; |
| 512 if (locale.find("@") != std::string::npos) { |
| 513 size_t split_point = locale.find("@"); |
| 514 std::string keywords = locale.substr(split_point + 1); |
| 515 prefix = locale.substr(0, split_point); |
| 516 |
| 517 size_t equals_loc = keywords.find("="); |
| 518 if (equals_loc == std::string::npos || |
| 519 equals_loc < 1 || equals_loc > keywords.size() - 2) |
| 520 return false; |
| 521 } |
| 522 |
| 523 // Check that all characters before the at-sign are alphanumeric, hyphen, |
| 524 // or underscore. |
| 525 for (size_t i = 0; i < prefix.size(); i++) { |
| 526 char ch = prefix[i]; |
| 527 if (!IsAsciiAlpha(ch) && !IsAsciiDigit(ch) && ch != '-' && ch != '_') |
| 528 return false; |
| 529 } |
| 530 |
| 531 // Check that the initial token (before the first hyphen/underscore) |
| 532 // is 1 - 3 alphabetical characters (a language tag). |
| 533 for (size_t i = 0; i < prefix.size(); i++) { |
| 534 char ch = prefix[i]; |
| 535 if (ch == '-' || ch == '_') { |
| 536 if (i < 1 || i > 3) |
| 537 return false; |
| 538 break; |
| 539 } |
| 540 if (!IsAsciiAlpha(ch)) |
| 541 return false; |
| 542 } |
| 543 |
| 544 // Check that the all tokens after the initial token are 1 - 8 characters. |
| 545 // (Tokenize/StringTokenizer don't work here, they collapse multiple |
| 546 // delimiters into one.) |
| 547 int token_len = 0; |
| 548 int token_index = 0; |
| 549 for (size_t i = 0; i < prefix.size(); i++) { |
| 550 char ch = prefix[i]; |
| 551 if (ch == '-' || ch == '_') { |
| 552 if (token_index > 0 && (token_len < 1 || token_len > 8)) { |
| 553 return false; |
| 554 } |
| 555 token_index++; |
| 556 token_len = 0; |
| 557 } else { |
| 558 token_len++; |
| 559 } |
| 560 } |
| 561 if (token_index == 0 && (token_len < 1 || token_len > 3)) { |
| 562 return false; |
| 563 } else if (token_len < 1 || token_len > 8) { |
| 564 return false; |
| 565 } |
| 566 |
| 567 return true; |
| 568 } |
| 569 |
478 std::wstring GetString(int message_id) { | 570 std::wstring GetString(int message_id) { |
479 return UTF16ToWide(GetStringUTF16(message_id)); | 571 return UTF16ToWide(GetStringUTF16(message_id)); |
480 } | 572 } |
481 | 573 |
482 std::string GetStringUTF8(int message_id) { | 574 std::string GetStringUTF8(int message_id) { |
483 return UTF16ToUTF8(GetStringUTF16(message_id)); | 575 return UTF16ToUTF8(GetStringUTF16(message_id)); |
484 } | 576 } |
485 | 577 |
486 string16 GetStringUTF16(int message_id) { | 578 string16 GetStringUTF16(int message_id) { |
487 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); | 579 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); |
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
867 for (size_t i = 0; i < arraysize(kAcceptLanguageList); ++i) { | 959 for (size_t i = 0; i < arraysize(kAcceptLanguageList); ++i) { |
868 if (!IsLocaleNameTranslated(kAcceptLanguageList[i], display_locale)) | 960 if (!IsLocaleNameTranslated(kAcceptLanguageList[i], display_locale)) |
869 // TODO(jungshik) : Put them at the of the list with language codes | 961 // TODO(jungshik) : Put them at the of the list with language codes |
870 // enclosed by brackets instead of skipping. | 962 // enclosed by brackets instead of skipping. |
871 continue; | 963 continue; |
872 locale_codes->push_back(kAcceptLanguageList[i]); | 964 locale_codes->push_back(kAcceptLanguageList[i]); |
873 } | 965 } |
874 } | 966 } |
875 | 967 |
876 } // namespace l10n_util | 968 } // namespace l10n_util |
OLD | NEW |