| Index: app/l10n_util.cc
|
| ===================================================================
|
| --- app/l10n_util.cc (revision 68996)
|
| +++ app/l10n_util.cc (working copy)
|
| @@ -29,6 +29,7 @@
|
| #include "build/build_config.h"
|
| #include "gfx/canvas.h"
|
| #include "unicode/rbbi.h"
|
| +#include "unicode/uloc.h"
|
|
|
| #if defined(OS_MACOSX)
|
| #include "app/l10n_util_mac.h"
|
| @@ -475,6 +476,97 @@
|
| return display_name;
|
| }
|
|
|
| +std::string NormalizeLocale(const std::string& locale) {
|
| + std::string normalized_locale(locale);
|
| + std::replace(normalized_locale.begin(), normalized_locale.end(), '-', '_');
|
| +
|
| + return normalized_locale;
|
| +}
|
| +
|
| +void GetParentLocales(const std::string& current_locale,
|
| + std::vector<std::string>* parent_locales) {
|
| + std::string locale(NormalizeLocale(current_locale));
|
| +
|
| + const int kNameCapacity = 256;
|
| + char parent[kNameCapacity];
|
| + base::strlcpy(parent, locale.c_str(), kNameCapacity);
|
| + parent_locales->push_back(parent);
|
| + UErrorCode err = U_ZERO_ERROR;
|
| + while (uloc_getParent(parent, parent, kNameCapacity, &err) > 0) {
|
| + if (U_FAILURE(err))
|
| + break;
|
| + parent_locales->push_back(parent);
|
| + }
|
| +}
|
| +
|
| +bool IsValidLocaleSyntax(const std::string& locale) {
|
| + // Check that the length is plausible.
|
| + if (locale.size() < 2 || locale.size() >= ULOC_FULLNAME_CAPACITY)
|
| + return false;
|
| +
|
| + // Strip off the part after an '@' sign, which might contain keywords,
|
| + // as in en_IE@currency=IEP or fr@collation=phonebook;calendar=islamic-civil.
|
| + // We don't validate that part much, just check that there's at least one
|
| + // equals sign in a plausible place.
|
| + std::string prefix = locale;
|
| + if (locale.find("@") != std::string::npos) {
|
| + size_t split_point = locale.find("@");
|
| + std::string keywords = locale.substr(split_point + 1);
|
| + prefix = locale.substr(0, split_point);
|
| +
|
| + size_t equals_loc = keywords.find("=");
|
| + if (equals_loc == std::string::npos ||
|
| + equals_loc < 1 || equals_loc > keywords.size() - 2)
|
| + return false;
|
| + }
|
| +
|
| + // Check that all characters before the at-sign are alphanumeric, hyphen,
|
| + // or underscore.
|
| + for (size_t i = 0; i < prefix.size(); i++) {
|
| + char ch = prefix[i];
|
| + if (!IsAsciiAlpha(ch) && !IsAsciiDigit(ch) && ch != '-' && ch != '_')
|
| + return false;
|
| + }
|
| +
|
| + // Check that the initial token (before the first hyphen/underscore)
|
| + // is 1 - 3 alphabetical characters (a language tag).
|
| + for (size_t i = 0; i < prefix.size(); i++) {
|
| + char ch = prefix[i];
|
| + if (ch == '-' || ch == '_') {
|
| + if (i < 1 || i > 3)
|
| + return false;
|
| + break;
|
| + }
|
| + if (!IsAsciiAlpha(ch))
|
| + return false;
|
| + }
|
| +
|
| + // Check that the all tokens after the initial token are 1 - 8 characters.
|
| + // (Tokenize/StringTokenizer don't work here, they collapse multiple
|
| + // delimiters into one.)
|
| + int token_len = 0;
|
| + int token_index = 0;
|
| + for (size_t i = 0; i < prefix.size(); i++) {
|
| + char ch = prefix[i];
|
| + if (ch == '-' || ch == '_') {
|
| + if (token_index > 0 && (token_len < 1 || token_len > 8)) {
|
| + return false;
|
| + }
|
| + token_index++;
|
| + token_len = 0;
|
| + } else {
|
| + token_len++;
|
| + }
|
| + }
|
| + if (token_index == 0 && (token_len < 1 || token_len > 3)) {
|
| + return false;
|
| + } else if (token_len < 1 || token_len > 8) {
|
| + return false;
|
| + }
|
| +
|
| + return true;
|
| +}
|
| +
|
| std::wstring GetString(int message_id) {
|
| return UTF16ToWide(GetStringUTF16(message_id));
|
| }
|
|
|