| Index: src/extensions/i18n/i18n-utils.js
|
| diff --git a/src/extensions/i18n/i18n-utils.js b/src/extensions/i18n/i18n-utils.js
|
| deleted file mode 100644
|
| index 545082ecbba4d6ba9755c9639234a28ba4889cf5..0000000000000000000000000000000000000000
|
| --- a/src/extensions/i18n/i18n-utils.js
|
| +++ /dev/null
|
| @@ -1,536 +0,0 @@
|
| -// Copyright 2013 the V8 project authors. All rights reserved.
|
| -// Redistribution and use in source and binary forms, with or without
|
| -// modification, are permitted provided that the following conditions are
|
| -// met:
|
| -//
|
| -// * Redistributions of source code must retain the above copyright
|
| -// notice, this list of conditions and the following disclaimer.
|
| -// * Redistributions in binary form must reproduce the above
|
| -// copyright notice, this list of conditions and the following
|
| -// disclaimer in the documentation and/or other materials provided
|
| -// with the distribution.
|
| -// * Neither the name of Google Inc. nor the names of its
|
| -// contributors may be used to endorse or promote products derived
|
| -// from this software without specific prior written permission.
|
| -//
|
| -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
| -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
| -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
| -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
| -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
| -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
| -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
| -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
| -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
| -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
| -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
| -// limitations under the License.
|
| -
|
| -// ECMAScript 402 API implementation is broken into separate files for
|
| -// each service. The build system combines them together into one
|
| -// Intl namespace.
|
| -
|
| -/**
|
| - * Adds bound method to the prototype of the given object.
|
| - */
|
| -function addBoundMethod(obj, methodName, implementation, length) {
|
| - function getter() {
|
| - if (!this || typeof this !== 'object' ||
|
| - this.__initializedIntlObject === undefined) {
|
| - throw new TypeError('Method ' + methodName + ' called on a ' +
|
| - 'non-object or on a wrong type of object.');
|
| - }
|
| - var internalName = '__bound' + methodName + '__';
|
| - if (this[internalName] === undefined) {
|
| - var that = this;
|
| - var boundMethod;
|
| - if (length === undefined || length === 2) {
|
| - boundMethod = function(x, y) {
|
| - if (%_IsConstructCall()) {
|
| - throw new TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR);
|
| - }
|
| - return implementation(that, x, y);
|
| - }
|
| - } else if (length === 1) {
|
| - boundMethod = function(x) {
|
| - if (%_IsConstructCall()) {
|
| - throw new TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR);
|
| - }
|
| - return implementation(that, x);
|
| - }
|
| - } else {
|
| - boundMethod = function() {
|
| - if (%_IsConstructCall()) {
|
| - throw new TypeError(ORDINARY_FUNCTION_CALLED_AS_CONSTRUCTOR);
|
| - }
|
| - // DateTimeFormat.format needs to be 0 arg method, but can stil
|
| - // receive optional dateValue param. If one was provided, pass it
|
| - // along.
|
| - if (arguments.length > 0) {
|
| - return implementation(that, arguments[0]);
|
| - } else {
|
| - return implementation(that);
|
| - }
|
| - }
|
| - }
|
| - %FunctionSetName(boundMethod, internalName);
|
| - %FunctionRemovePrototype(boundMethod);
|
| - %SetNativeFlag(boundMethod);
|
| - this[internalName] = boundMethod;
|
| - }
|
| - return this[internalName];
|
| - }
|
| -
|
| - %FunctionSetName(getter, methodName);
|
| - %FunctionRemovePrototype(getter);
|
| - %SetNativeFlag(getter);
|
| -
|
| - Object.defineProperty(obj.prototype, methodName, {
|
| - get: getter,
|
| - enumerable: false,
|
| - configurable: true
|
| - });
|
| -}
|
| -
|
| -
|
| -/**
|
| - * Returns an intersection of locales and service supported locales.
|
| - * Parameter locales is treated as a priority list.
|
| - */
|
| -function supportedLocalesOf(service, locales, options) {
|
| - if (service.match(SERVICE_RE) === null) {
|
| - throw new Error('Internal error, wrong service type: ' + service);
|
| - }
|
| -
|
| - // Provide defaults if matcher was not specified.
|
| - if (options === undefined) {
|
| - options = {};
|
| - } else {
|
| - options = toObject(options);
|
| - }
|
| -
|
| - var matcher = options.localeMatcher;
|
| - if (matcher !== undefined) {
|
| - matcher = String(matcher);
|
| - if (matcher !== 'lookup' && matcher !== 'best fit') {
|
| - throw new RangeError('Illegal value for localeMatcher:' + matcher);
|
| - }
|
| - } else {
|
| - matcher = 'best fit';
|
| - }
|
| -
|
| - var requestedLocales = initializeLocaleList(locales);
|
| -
|
| - // Cache these, they don't ever change per service.
|
| - if (AVAILABLE_LOCALES[service] === undefined) {
|
| - AVAILABLE_LOCALES[service] = getAvailableLocalesOf(service);
|
| - }
|
| -
|
| - // Use either best fit or lookup algorithm to match locales.
|
| - if (matcher === 'best fit') {
|
| - return initializeLocaleList(bestFitSupportedLocalesOf(
|
| - requestedLocales, AVAILABLE_LOCALES[service]));
|
| - }
|
| -
|
| - return initializeLocaleList(lookupSupportedLocalesOf(
|
| - requestedLocales, AVAILABLE_LOCALES[service]));
|
| -}
|
| -
|
| -
|
| -/**
|
| - * Returns the subset of the provided BCP 47 language priority list for which
|
| - * this service has a matching locale when using the BCP 47 Lookup algorithm.
|
| - * Locales appear in the same order in the returned list as in the input list.
|
| - */
|
| -function lookupSupportedLocalesOf(requestedLocales, availableLocales) {
|
| - var matchedLocales = [];
|
| - for (var i = 0; i < requestedLocales.length; ++i) {
|
| - // Remove -u- extension.
|
| - var locale = requestedLocales[i].replace(UNICODE_EXTENSION_RE, '');
|
| - do {
|
| - if (availableLocales[locale] !== undefined) {
|
| - // Push requested locale not the resolved one.
|
| - matchedLocales.push(requestedLocales[i]);
|
| - break;
|
| - }
|
| - // Truncate locale if possible, if not break.
|
| - var pos = locale.lastIndexOf('-');
|
| - if (pos === -1) {
|
| - break;
|
| - }
|
| - locale = locale.substring(0, pos);
|
| - } while (true);
|
| - }
|
| -
|
| - return matchedLocales;
|
| -}
|
| -
|
| -
|
| -/**
|
| - * Returns the subset of the provided BCP 47 language priority list for which
|
| - * this service has a matching locale when using the implementation
|
| - * dependent algorithm.
|
| - * Locales appear in the same order in the returned list as in the input list.
|
| - */
|
| -function bestFitSupportedLocalesOf(requestedLocales, availableLocales) {
|
| - // TODO(cira): implement better best fit algorithm.
|
| - return lookupSupportedLocalesOf(requestedLocales, availableLocales);
|
| -}
|
| -
|
| -
|
| -/**
|
| - * Returns a getOption function that extracts property value for given
|
| - * options object. If property is missing it returns defaultValue. If value
|
| - * is out of range for that property it throws RangeError.
|
| - */
|
| -function getGetOption(options, caller) {
|
| - if (options === undefined) {
|
| - throw new Error('Internal ' + caller + ' error. ' +
|
| - 'Default options are missing.');
|
| - }
|
| -
|
| - var getOption = function getOption(property, type, values, defaultValue) {
|
| - if (options[property] !== undefined) {
|
| - var value = options[property];
|
| - switch (type) {
|
| - case 'boolean':
|
| - value = Boolean(value);
|
| - break;
|
| - case 'string':
|
| - value = String(value);
|
| - break;
|
| - case 'number':
|
| - value = Number(value);
|
| - break;
|
| - default:
|
| - throw new Error('Internal error. Wrong value type.');
|
| - }
|
| - if (values !== undefined && values.indexOf(value) === -1) {
|
| - throw new RangeError('Value ' + value + ' out of range for ' + caller +
|
| - ' options property ' + property);
|
| - }
|
| -
|
| - return value;
|
| - }
|
| -
|
| - return defaultValue;
|
| - }
|
| -
|
| - return getOption;
|
| -}
|
| -
|
| -
|
| -/**
|
| - * Compares a BCP 47 language priority list requestedLocales against the locales
|
| - * in availableLocales and determines the best available language to meet the
|
| - * request. Two algorithms are available to match the locales: the Lookup
|
| - * algorithm described in RFC 4647 section 3.4, and an implementation dependent
|
| - * best-fit algorithm. Independent of the locale matching algorithm, options
|
| - * specified through Unicode locale extension sequences are negotiated
|
| - * separately, taking the caller's relevant extension keys and locale data as
|
| - * well as client-provided options into consideration. Returns an object with
|
| - * a locale property whose value is the language tag of the selected locale,
|
| - * and properties for each key in relevantExtensionKeys providing the selected
|
| - * value for that key.
|
| - */
|
| -function resolveLocale(service, requestedLocales, options) {
|
| - requestedLocales = initializeLocaleList(requestedLocales);
|
| -
|
| - var getOption = getGetOption(options, service);
|
| - var matcher = getOption('localeMatcher', 'string',
|
| - ['lookup', 'best fit'], 'best fit');
|
| - var resolved;
|
| - if (matcher === 'lookup') {
|
| - resolved = lookupMatcher(service, requestedLocales);
|
| - } else {
|
| - resolved = bestFitMatcher(service, requestedLocales);
|
| - }
|
| -
|
| - return resolved;
|
| -}
|
| -
|
| -
|
| -/**
|
| - * Returns best matched supported locale and extension info using basic
|
| - * lookup algorithm.
|
| - */
|
| -function lookupMatcher(service, requestedLocales) {
|
| - if (service.match(SERVICE_RE) === null) {
|
| - throw new Error('Internal error, wrong service type: ' + service);
|
| - }
|
| -
|
| - // Cache these, they don't ever change per service.
|
| - if (AVAILABLE_LOCALES[service] === undefined) {
|
| - AVAILABLE_LOCALES[service] = getAvailableLocalesOf(service);
|
| - }
|
| -
|
| - for (var i = 0; i < requestedLocales.length; ++i) {
|
| - // Remove all extensions.
|
| - var locale = requestedLocales[i].replace(ANY_EXTENSION_RE, '');
|
| - do {
|
| - if (AVAILABLE_LOCALES[service][locale] !== undefined) {
|
| - // Return the resolved locale and extension.
|
| - var extensionMatch = requestedLocales[i].match(UNICODE_EXTENSION_RE);
|
| - var extension = (extensionMatch === null) ? '' : extensionMatch[0];
|
| - return {'locale': locale, 'extension': extension, 'position': i};
|
| - }
|
| - // Truncate locale if possible.
|
| - var pos = locale.lastIndexOf('-');
|
| - if (pos === -1) {
|
| - break;
|
| - }
|
| - locale = locale.substring(0, pos);
|
| - } while (true);
|
| - }
|
| -
|
| - // Didn't find a match, return default.
|
| - if (DEFAULT_ICU_LOCALE === undefined) {
|
| - DEFAULT_ICU_LOCALE = %GetDefaultICULocale();
|
| - }
|
| -
|
| - return {'locale': DEFAULT_ICU_LOCALE, 'extension': '', 'position': -1};
|
| -}
|
| -
|
| -
|
| -/**
|
| - * Returns best matched supported locale and extension info using
|
| - * implementation dependend algorithm.
|
| - */
|
| -function bestFitMatcher(service, requestedLocales) {
|
| - // TODO(cira): implement better best fit algorithm.
|
| - return lookupMatcher(service, requestedLocales);
|
| -}
|
| -
|
| -
|
| -/**
|
| - * Parses Unicode extension into key - value map.
|
| - * Returns empty object if the extension string is invalid.
|
| - * We are not concerned with the validity of the values at this point.
|
| - */
|
| -function parseExtension(extension) {
|
| - var extensionSplit = extension.split('-');
|
| -
|
| - // Assume ['', 'u', ...] input, but don't throw.
|
| - if (extensionSplit.length <= 2 ||
|
| - (extensionSplit[0] !== '' && extensionSplit[1] !== 'u')) {
|
| - return {};
|
| - }
|
| -
|
| - // Key is {2}alphanum, value is {3,8}alphanum.
|
| - // Some keys may not have explicit values (booleans).
|
| - var extensionMap = {};
|
| - var previousKey = undefined;
|
| - for (var i = 2; i < extensionSplit.length; ++i) {
|
| - var length = extensionSplit[i].length;
|
| - var element = extensionSplit[i];
|
| - if (length === 2) {
|
| - extensionMap[element] = undefined;
|
| - previousKey = element;
|
| - } else if (length >= 3 && length <=8 && previousKey !== undefined) {
|
| - extensionMap[previousKey] = element;
|
| - previousKey = undefined;
|
| - } else {
|
| - // There is a value that's too long, or that doesn't have a key.
|
| - return {};
|
| - }
|
| - }
|
| -
|
| - return extensionMap;
|
| -}
|
| -
|
| -
|
| -/**
|
| - * Converts parameter to an Object if possible.
|
| - */
|
| -function toObject(value) {
|
| - if (value === undefined || value === null) {
|
| - throw new TypeError('Value cannot be converted to an Object.');
|
| - }
|
| -
|
| - return Object(value);
|
| -}
|
| -
|
| -
|
| -/**
|
| - * Populates internalOptions object with boolean key-value pairs
|
| - * from extensionMap and options.
|
| - * Returns filtered extension (number and date format constructors use
|
| - * Unicode extensions for passing parameters to ICU).
|
| - * It's used for extension-option pairs only, e.g. kn-normalization, but not
|
| - * for 'sensitivity' since it doesn't have extension equivalent.
|
| - * Extensions like nu and ca don't have options equivalent, so we place
|
| - * undefined in the map.property to denote that.
|
| - */
|
| -function setOptions(inOptions, extensionMap, keyValues, getOption, outOptions) {
|
| - var extension = '';
|
| -
|
| - var updateExtension = function updateExtension(key, value) {
|
| - return '-' + key + '-' + String(value);
|
| - }
|
| -
|
| - var updateProperty = function updateProperty(property, type, value) {
|
| - if (type === 'boolean' && (typeof value === 'string')) {
|
| - value = (value === 'true') ? true : false;
|
| - }
|
| -
|
| - if (property !== undefined) {
|
| - defineWEProperty(outOptions, property, value);
|
| - }
|
| - }
|
| -
|
| - for (var key in keyValues) {
|
| - if (keyValues.hasOwnProperty(key)) {
|
| - var value = undefined;
|
| - var map = keyValues[key];
|
| - if (map.property !== undefined) {
|
| - // This may return true if user specifies numeric: 'false', since
|
| - // Boolean('nonempty') === true.
|
| - value = getOption(map.property, map.type, map.values);
|
| - }
|
| - if (value !== undefined) {
|
| - updateProperty(map.property, map.type, value);
|
| - extension += updateExtension(key, value);
|
| - continue;
|
| - }
|
| - // User options didn't have it, check Unicode extension.
|
| - // Here we want to convert strings 'true', 'false' into proper Boolean
|
| - // values (not a user error).
|
| - if (extensionMap.hasOwnProperty(key)) {
|
| - value = extensionMap[key];
|
| - if (value !== undefined) {
|
| - updateProperty(map.property, map.type, value);
|
| - extension += updateExtension(key, value);
|
| - } else if (map.type === 'boolean') {
|
| - // Boolean keys are allowed not to have values in Unicode extension.
|
| - // Those default to true.
|
| - updateProperty(map.property, map.type, true);
|
| - extension += updateExtension(key, true);
|
| - }
|
| - }
|
| - }
|
| - }
|
| -
|
| - return extension === ''? '' : '-u' + extension;
|
| -}
|
| -
|
| -
|
| -/**
|
| - * Converts all OwnProperties into
|
| - * configurable: false, writable: false, enumerable: true.
|
| - */
|
| -function freezeArray(array) {
|
| - array.forEach(function(element, index) {
|
| - Object.defineProperty(array, index, {value: element,
|
| - configurable: false,
|
| - writable: false,
|
| - enumerable: true});
|
| - });
|
| -
|
| - Object.defineProperty(array, 'length', {value: array.length,
|
| - writable: false});
|
| -
|
| - return array;
|
| -}
|
| -
|
| -
|
| -/**
|
| - * It's sometimes desireable to leave user requested locale instead of ICU
|
| - * supported one (zh-TW is equivalent to zh-Hant-TW, so we should keep shorter
|
| - * one, if that was what user requested).
|
| - * This function returns user specified tag if its maximized form matches ICU
|
| - * resolved locale. If not we return ICU result.
|
| - */
|
| -function getOptimalLanguageTag(original, resolved) {
|
| - // Returns Array<Object>, where each object has maximized and base properties.
|
| - // Maximized: zh -> zh-Hans-CN
|
| - // Base: zh-CN-u-ca-gregory -> zh-CN
|
| - // Take care of grandfathered or simple cases.
|
| - if (original === resolved) {
|
| - return original;
|
| - }
|
| -
|
| - var locales = %GetLanguageTagVariants([original, resolved]);
|
| - if (locales[0].maximized !== locales[1].maximized) {
|
| - return resolved;
|
| - }
|
| -
|
| - // Preserve extensions of resolved locale, but swap base tags with original.
|
| - var resolvedBase = new RegExp('^' + locales[1].base);
|
| - return resolved.replace(resolvedBase, locales[0].base);
|
| -}
|
| -
|
| -
|
| -/**
|
| - * Returns an Object that contains all of supported locales for a given
|
| - * service.
|
| - * In addition to the supported locales we add xx-ZZ locale for each xx-Yyyy-ZZ
|
| - * that is supported. This is required by the spec.
|
| - */
|
| -function getAvailableLocalesOf(service) {
|
| - var available = %AvailableLocalesOf(service);
|
| -
|
| - for (var i in available) {
|
| - if (available.hasOwnProperty(i)) {
|
| - var parts = i.match(/^([a-z]{2,3})-([A-Z][a-z]{3})-([A-Z]{2})$/);
|
| - if (parts !== null) {
|
| - // Build xx-ZZ. We don't care about the actual value,
|
| - // as long it's not undefined.
|
| - available[parts[1] + '-' + parts[3]] = null;
|
| - }
|
| - }
|
| - }
|
| -
|
| - return available;
|
| -}
|
| -
|
| -
|
| -/**
|
| - * Defines a property and sets writable and enumerable to true.
|
| - * Configurable is false by default.
|
| - */
|
| -function defineWEProperty(object, property, value) {
|
| - Object.defineProperty(object, property,
|
| - {value: value, writable: true, enumerable: true});
|
| -}
|
| -
|
| -
|
| -/**
|
| - * Adds property to an object if the value is not undefined.
|
| - * Sets configurable descriptor to false.
|
| - */
|
| -function addWEPropertyIfDefined(object, property, value) {
|
| - if (value !== undefined) {
|
| - defineWEProperty(object, property, value);
|
| - }
|
| -}
|
| -
|
| -
|
| -/**
|
| - * Defines a property and sets writable, enumerable and configurable to true.
|
| - */
|
| -function defineWECProperty(object, property, value) {
|
| - Object.defineProperty(object, property,
|
| - {value: value,
|
| - writable: true,
|
| - enumerable: true,
|
| - configurable: true});
|
| -}
|
| -
|
| -
|
| -/**
|
| - * Adds property to an object if the value is not undefined.
|
| - * Sets all descriptors to true.
|
| - */
|
| -function addWECPropertyIfDefined(object, property, value) {
|
| - if (value !== undefined) {
|
| - defineWECProperty(object, property, value);
|
| - }
|
| -}
|
| -
|
| -
|
| -/**
|
| - * Returns titlecased word, aMeRricA -> America.
|
| - */
|
| -function toTitleCaseWord(word) {
|
| - return word.substr(0, 1).toUpperCase() + word.substr(1).toLowerCase();
|
| -}
|
|
|