| Index: src/js/i18n.js
|
| diff --git a/src/js/i18n.js b/src/js/i18n.js
|
| index 845289a91f10cf1416c4cff4b6698e27f412d6be..7d623926e75a98abbb5e265cb27f889ddc92d5f9 100644
|
| --- a/src/js/i18n.js
|
| +++ b/src/js/i18n.js
|
| @@ -144,6 +144,13 @@ var AVAILABLE_LOCALES = {
|
| */
|
| var DEFAULT_ICU_LOCALE = UNDEFINED;
|
|
|
| +function GetDefaultICULocaleJS() {
|
| + if (IS_UNDEFINED(DEFAULT_ICU_LOCALE)) {
|
| + DEFAULT_ICU_LOCALE = %GetDefaultICULocale();
|
| + }
|
| + return DEFAULT_ICU_LOCALE;
|
| +}
|
| +
|
| /**
|
| * Unicode extension regular expression.
|
| */
|
| @@ -448,11 +455,7 @@ function lookupMatcher(service, requestedLocales) {
|
| }
|
|
|
| // Didn't find a match, return default.
|
| - if (IS_UNDEFINED(DEFAULT_ICU_LOCALE)) {
|
| - DEFAULT_ICU_LOCALE = %GetDefaultICULocale();
|
| - }
|
| -
|
| - return {'locale': DEFAULT_ICU_LOCALE, 'extension': '', 'position': -1};
|
| + return {'locale': GetDefaultICULocaleJS(), 'extension': '', 'position': -1};
|
| }
|
|
|
|
|
| @@ -722,21 +725,23 @@ function toTitleCaseTimezoneLocation(location) {
|
| */
|
| function canonicalizeLanguageTag(localeID) {
|
| // null is typeof 'object' so we have to do extra check.
|
| - if (typeof localeID !== 'string' && typeof localeID !== 'object' ||
|
| + if ((typeof localeID !== 'string' && typeof localeID !== 'object') ||
|
| IS_NULL(localeID)) {
|
| throw MakeTypeError(kLanguageID);
|
| }
|
|
|
| + // Optimize for the most common case; a language code alone in
|
| + // the canonical form/lowercase (e.g. "en", "fil").
|
| + if (typeof localeID === 'string' &&
|
| + !IS_NULL(InternalRegExpMatch(/^[a-z]{2,3}$/, localeID)))
|
| + return localeID;
|
| +
|
| var localeString = GlobalString(localeID);
|
|
|
| if (isValidLanguageTag(localeString) === false) {
|
| throw MakeRangeError(kInvalidLanguageTag, localeString);
|
| }
|
|
|
| - // This call will strip -kn but not -kn-true extensions.
|
| - // ICU bug filled - http://bugs.icu-project.org/trac/ticket/9265.
|
| - // TODO(cira): check if -u-kn-true-kc-true-kh-true still throws after
|
| - // upgrade to ICU 4.9.
|
| var tag = %CanonicalizeLanguageTag(localeString);
|
| if (tag === 'invalid-tag') {
|
| throw MakeRangeError(kInvalidLanguageTag, localeString);
|
| @@ -1992,6 +1997,36 @@ function cachedOrNewService(service, locales, options, defaults) {
|
| return new savedObjects[service](locales, useOptions);
|
| }
|
|
|
| +function getCaseConversionLanguageId(locales) {
|
| + var language;
|
| + // Optimize for the most common two cases. initializeLocaleList() can handle
|
| + // them as well, but it's rather slow accounting for over 60% of
|
| + // toLocale{U,L}Case() and about 40% of toLocale{U,L}Case("<locale>").
|
| + if (IS_UNDEFINED(locales)) {
|
| + language = GetDefaultICULocaleJS();
|
| + } else if (typeof locales === 'string') {
|
| + language = canonicalizeLanguageTag(locales);
|
| + } else {
|
| + var locales = initializeLocaleList(locales);
|
| + language = locales.length > 0 ? locales[0] : GetDefaultICULocaleJS();
|
| + }
|
| +
|
| + // StringSplit is slwoer than this.
|
| + var pos = %_Call(StringIndexOf, language, '-');
|
| + if (pos != -1)
|
| + language = %_Call(StringSubstring, language, 0, pos);
|
| +
|
| + var CUSTOM_CASE_LANGUAGES = ['az', 'el', 'lt', 'tr'];
|
| + return %_Call(ArrayIndexOf, CUSTOM_CASE_LANGUAGES, language);
|
| +}
|
| +
|
| +function localeConvertCase(s, locales, isToUpper) {
|
| + var caseConversionLanguageId = getCaseConversionLanguageId(locales);
|
| + if (caseConversionLanguageId == -1)
|
| + return isToUpper ? %StringToUpperCaseI18N(s) : %StringToLowerCaseI18N(s);
|
| + return %StringLocaleConvertCase(s, isToUpper, caseConversionLanguageId);
|
| +}
|
| +
|
| /**
|
| * Compares this and that, and returns less than 0, 0 or greater than 0 value.
|
| * Overrides the built-in method.
|
| @@ -2044,6 +2079,45 @@ OverrideFunction(GlobalString.prototype, 'normalize', function() {
|
| }
|
| );
|
|
|
| +OverrideFunction(GlobalString.prototype, 'toLowerCase', function() {
|
| + if (!IS_UNDEFINED(new.target)) {
|
| + throw MakeTypeError(kOrdinaryFunctionCalledAsConstructor);
|
| + }
|
| + CHECK_OBJECT_COERCIBLE(this, "String.prototype.toLowerCase");
|
| + var s = TO_STRING(this);
|
| + return %StringToLowerCaseI18N(s);
|
| + }
|
| +);
|
| +
|
| +OverrideFunction(GlobalString.prototype, 'toUpperCase', function() {
|
| + if (!IS_UNDEFINED(new.target)) {
|
| + throw MakeTypeError(kOrdinaryFunctionCalledAsConstructor);
|
| + }
|
| + CHECK_OBJECT_COERCIBLE(this, "String.prototype.toLowerCase");
|
| + var s = TO_STRING(this);
|
| + return %StringToUpperCaseI18N(s);
|
| + }
|
| +);
|
| +
|
| +OverrideFunction(GlobalString.prototype, 'toLocaleLowerCase', function() {
|
| + if (!IS_UNDEFINED(new.target)) {
|
| + throw MakeTypeError(kOrdinaryFunctionCalledAsConstructor);
|
| + }
|
| + CHECK_OBJECT_COERCIBLE(this, "String.prototype.toLocaleLowerCase");
|
| + return localeConvertCase(TO_STRING(this), arguments[0], false);
|
| + }
|
| +);
|
| +
|
| +
|
| +OverrideFunction(GlobalString.prototype, 'toLocaleUpperCase', function() {
|
| + if (!IS_UNDEFINED(new.target)) {
|
| + throw MakeTypeError(kOrdinaryFunctionCalledAsConstructor);
|
| + }
|
| + CHECK_OBJECT_COERCIBLE(this, "String.prototype.toLocaleUpperCase");
|
| + return localeConvertCase(TO_STRING(this), arguments[0], true);
|
| + }
|
| +);
|
| +
|
|
|
| /**
|
| * Formats a Number object (this) using locale and options values.
|
|
|