123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727 |
- define(["./List", "./Record",
- "requirejs-text/text!../cldr/config/availableLocales.json",
- "requirejs-text/text!../cldr/supplemental/aliases.json",
- "requirejs-text/text!../cldr/supplemental/localeAliases.json",
- "requirejs-text/text!../cldr/supplemental/parentLocales.json",
- "requirejs-text/text!../cldr/supplemental/likelySubtags.json",
- "requirejs-text/text!../cldr/supplemental/calendarPreferenceData.json",
- ],
- function (List, Record, availableLocalesJson, aliasesJson, localeAliasesJson,
- parentLocalesJson, likelySubtagsJson, calendarPreferenceDataJson) {
- var aliases = JSON.parse(aliasesJson).supplemental.metadata.alias;
- var localeAliases = JSON.parse(localeAliasesJson).supplemental.metadata.alias;
- var parentLocales = JSON.parse(parentLocalesJson).supplemental.parentLocales.parentLocale;
- var likelySubtags = JSON.parse(likelySubtagsJson).supplemental.likelySubtags;
- var calendarPreferenceData = JSON.parse(calendarPreferenceDataJson).supplemental.calendarPreferenceData;
- var common = {
- unicodeLocaleExtensions : /-u(-[a-z0-9]{2,8})+/g,
-
- _toUpperCaseIdentifier : function (identifier) {
- var match = /[a-z]/g;
- return identifier.replace(match, function (m) {
- return m.toUpperCase();
- });
- },
-
- _toLowerCaseIdentifier : function (identifier) {
- var match = /[A-Z]/g;
- return identifier.replace(match, function (m) {
- return m.toLowerCase();
- });
- },
-
- _getRegion : function (locale) {
- var region = "001";
- var regionPos = locale.search(/(?:-)([A-Z]{2})(?=(-|$))/);
- if (regionPos >= 0) {
- region = locale.substr(regionPos + 1, 2);
- } else {
- var likelySubtag = likelySubtags[locale];
- if (likelySubtag) {
- region = likelySubtag.substr(-2);
- }
- }
- return region;
- },
-
- _getSupportedCalendars : function (region) {
- var supportedCalendars = [ "gregory", "buddhist", "hebrew", "japanese", "roc",
- "islamic", "islamic-civil", "islamic-tbla", "islamic-umalqura"];
- var calendarPreferences = [];
- if (calendarPreferenceData[region]) {
- var prefs = calendarPreferenceData[region].toString().split(" ");
- prefs.forEach(function (pref) {
- var thisPref = pref.replace("gregorian", "gregory");
- if (supportedCalendars.indexOf(thisPref) !== -1) {
- calendarPreferences.push(thisPref);
- }
- });
- }
-
- if (calendarPreferences.indexOf("gregory") === -1) {
- calendarPreferences.push("gregory");
- }
- return calendarPreferences;
- },
-
- isStructurallyValidLanguageTag : function (locale) {
- if (typeof locale !== "string") {
- return false;
- }
- var identifier = this._toLowerCaseIdentifier(locale);
- var langtag = new RegExp(
- "^([a-z]{2,3}(-[a-z]{3}){0,3}|[a-z]{4,8})" +
- "(-[a-z]{4})?" +
- "(-([a-z]{2}|\\d{3}))?" +
- "(-([a-z0-9]{5,8}|\\d[a-z0-9]{3}))*" +
- "(-[a-wyz0-9](-[a-z0-9]{2,8})+)*(-x(-[a-z0-9]{1,8})+)?$");
- var privateuse = /x(-[a-z0-9]{1,8})+/;
- var grandfathered = new RegExp(
- "en-gb-oed|(i-(ami|bnn|default|enochian|hak|klingon|lux|mingo|navajo|pwn|tao|tay|tsu))|" +
- "sgn-((be-(fr|nl))|(ch-de))");
- if (privateuse.test(identifier) || grandfathered.test(identifier)) {
- return true;
- }
-
- function _isUniqueVariant(element) {
- var firstSingletonPosition = identifier.search(/-[a-z0-9]-/);
- if (firstSingletonPosition > 0) {
- return identifier.indexOf(element) > firstSingletonPosition
- || identifier.indexOf(element) === identifier.lastIndexOf(element,
- firstSingletonPosition);
- }
- return identifier.indexOf(element) === identifier.lastIndexOf(element);
- }
-
- function _isUniqueSingleton(element) {
- var firstXPosition = identifier.search(/-x-/);
- if (firstXPosition > 0) {
- return identifier.indexOf(element) === identifier.lastIndexOf(element, firstXPosition);
- }
- return identifier.indexOf(element) === identifier.lastIndexOf(element);
- }
- if (langtag.test(identifier)) {
- var varianttag = /-[a-z0-9]{5,8}|\d[a-z0-9]{3}/g;
- var variants = varianttag.exec(identifier);
- var singletontag = /-[a-wyz0-9]-/g;
- var singletons = singletontag.exec(identifier);
- var variantsOK = !variants || variants.every(_isUniqueVariant);
- var singletonsOK = !singletons || singletons.every(_isUniqueSingleton);
-
- return variantsOK && singletonsOK;
- }
- return false;
- },
-
- CanonicalizeLanguageTag : function (locale) {
- var result = locale.toLowerCase();
- var firstSingletonPosition = result.search(/(^|-)[a-z0-9]-/);
- var languageTag = /^([a-z]{2,3}(-[a-z]{3}){0,3}|[a-z]{4,8})(?=(-|$))/;
- var scriptTag = /(?:-)([a-z]{4})(?=(-|$))/;
- var regionTag = /(?:-)([a-z]{2})(?=(-|$))/g;
- var variantTag = /(?:-)([a-z0-9]{5,8}|\d[a-z0-9]{3})/;
- var extlangTag = /^([a-z]{2,3}(-[a-z]{3}))(?=(-|$))/;
-
- result = result.replace(languageTag, function (m) {
- var lookupAlias = aliases.languageAlias[m];
- if (lookupAlias && lookupAlias._reason !== "macrolanguage") {
- m = lookupAlias._replacement ? lookupAlias._replacement : m;
- }
- return m;
- });
-
- result = result.replace(scriptTag, function (m) {
- if (firstSingletonPosition === -1 || result.indexOf(m) < firstSingletonPosition) {
- m = m.substring(0, 2).toUpperCase() + m.substring(2);
- var script = m.substring(1);
- var lookupAlias = aliases.scriptAlias[script];
- if (lookupAlias) {
- m = lookupAlias._replacement ? "-" + lookupAlias._replacement : m;
- }
- }
- return m;
- });
-
- result = result.replace(regionTag, function (m) {
- if (firstSingletonPosition === -1 || result.indexOf(m) < firstSingletonPosition) {
- m = m.toUpperCase();
- var region = m.substring(1);
- var lookupAlias = aliases.territoryAlias[region];
- if (lookupAlias) {
- var repl = lookupAlias._replacement;
- if (repl.indexOf(" ") >= 0) {
- repl = repl.substring(0, repl.indexOf(" "));
- }
- m = repl ? "-" + repl : m;
- }
- }
- return m;
- });
-
- result = result.replace(variantTag, function (m) {
-
- var variant = common._toUpperCaseIdentifier(m.substring(1));
- var lookupAlias = aliases.variantAlias[variant];
- if (lookupAlias) {
- var repl = lookupAlias._replacement;
- m = repl ? "-" + common._toLowerCaseIdentifier(repl) : m;
- }
- return m;
- });
-
- result = result.replace(result, function (m) {
- var lookupAlias = aliases.languageAlias[m];
- if (lookupAlias && lookupAlias._reason !== "macrolanguage") {
- m = lookupAlias._replacement ? lookupAlias._replacement : m;
- }
- return m;
- });
-
- if (extlangTag.test(result)) {
- result = result.replace(/^[a-z]{2,3}-/, "");
- }
- return result;
- },
-
- DefaultLocale : function () {
- var result;
- var global = (function () {return this; })();
- var navigator = global.navigator;
- if (navigator && this.isStructurallyValidLanguageTag(navigator.language)) {
- result = this.BestFitAvailableLocale(this.availableLocalesList, this
- .CanonicalizeLanguageTag(navigator.language));
- }
- if (!result && navigator && this.isStructurallyValidLanguageTag(navigator.userLanguage)) {
- result = this.BestFitAvailableLocale(this.availableLocalesList, this
- .CanonicalizeLanguageTag(navigator.userLanguage));
- }
- if (!result) {
- result = "root";
- }
- return result;
- },
-
- IsWellFormedCurrencyCode : function (currency) {
- var wellFormed = /^[A-Za-z]{3}$/;
- return wellFormed.test(currency.toString());
- },
-
- CanonicalizeLocaleList : function (locales) {
- if (locales === undefined) {
- return new List();
- }
- if (locales === null) {
- throw new TypeError("Locale list can not be null");
- }
- var seen = new List();
- if (typeof locales === "string") {
- locales = new Array(locales);
- }
- var O = Object(locales);
- var lenValue = O.length;
- var len = lenValue >>> 0;
- for (var k = 0; k < len ; k++) {
- var Pk = k.toString();
- var kPresent = Pk in O;
- if (kPresent) {
- var kValue = O[Pk];
- if (typeof kValue !== "string" && typeof kValue !== "object") {
- throw new TypeError(kValue + " must be a string or an object.");
- }
- var tag = kValue.toString();
- if (!this.isStructurallyValidLanguageTag(tag)) {
- throw new RangeError(tag + " is not a structurally valid language tag.");
- }
- tag = this.CanonicalizeLanguageTag(tag);
- if (seen.indexOf(tag) < 0) {
- seen.push(tag);
- }
- }
- }
- return seen;
- },
-
- BestAvailableLocale : function (availableLocales, locale) {
- var candidate = locale;
- while (true) {
- if (availableLocales.indexOf(candidate) >= 0) {
- return candidate;
- }
- var pos = candidate.lastIndexOf("-");
- if (pos < 0) {
- return undefined;
- }
- if (pos >= 2 && candidate.charAt(pos - 2) === "-") {
- pos -= 2;
- }
- candidate = candidate.substring(0, pos);
- }
- },
-
- LookupMatcher : function (availableLocales, requestedLocales) {
- var i = 0;
- var len = requestedLocales.length;
- var availableLocale = null;
- var locale = null;
- var noExtensionsLocale = null;
- while (i < len && availableLocale === null) {
- locale = requestedLocales[i];
- noExtensionsLocale = locale.replace(this.unicodeLocaleExtensions, "");
- availableLocale = this.BestAvailableLocale(availableLocales, noExtensionsLocale);
- i++;
- }
- var result = new Record();
- if (availableLocale) {
- result.set("locale", availableLocale);
- if (locale !== noExtensionsLocale) {
- result.set("extension", locale.match(this.unicodeLocaleExtensions)[0]);
- result.set("extensionIndex", locale.search(this.unicodeLocaleExtensions));
- }
- } else {
- result.set("locale", this.DefaultLocale());
- }
- return result;
- },
-
- BestFitAvailableLocale : function (availableLocales, locale) {
- var candidate = locale;
- while (true) {
- var langtag = candidate.substring(0, candidate.indexOf("-"));
- var lookupAlias = aliases.languageAlias[langtag];
- if (lookupAlias && lookupAlias._reason === "macrolanguage") {
- candidate = candidate.replace(langtag, lookupAlias._replacement);
- }
- lookupAlias = localeAliases.localeAlias[candidate];
- if (lookupAlias) {
- candidate = lookupAlias._replacement;
- }
- if (availableLocales.indexOf(candidate) >= 0) {
- return candidate;
- }
- var parentLocale = parentLocales[candidate];
- if (parentLocale) {
- candidate = parentLocale;
- } else {
- var pos = candidate.lastIndexOf("-");
- if (pos < 0) {
- return undefined;
- }
- if (pos >= 2 && candidate.charAt(pos - 2) === "-") {
- pos -= 2;
- }
- candidate = candidate.substring(0, pos);
- }
- }
- },
-
- BestFitMatcher : function (availableLocales, requestedLocales) {
- var i = 0;
- var len = requestedLocales.length;
- var availableLocale = null;
- var locale = null;
- var noExtensionsLocale = null;
- while (i < len && availableLocale === null) {
- locale = requestedLocales[i];
- noExtensionsLocale = locale.replace(this.unicodeLocaleExtensions, "");
- availableLocale = this.BestFitAvailableLocale(availableLocales, noExtensionsLocale);
- i++;
- }
- var result = new Record();
- if (availableLocale) {
- result.set("locale", availableLocale);
- if (locale !== noExtensionsLocale) {
- result.set("extension", locale.match(this.unicodeLocaleExtensions)[0]);
- result.set("extensionIndex", locale.search(this.unicodeLocaleExtensions));
- }
- } else {
- result.set("locale", this.DefaultLocale());
- }
- return result;
- },
-
-
- ResolveLocale : function (availableLocales, requestedLocales, options, relevantExtensionKeys,
- localeData) {
- var matcher = options.localeMatcher;
- var r = matcher === "lookup" ? this.LookupMatcher(availableLocales, requestedLocales) : this
- .BestFitMatcher(availableLocales, requestedLocales);
- var foundLocale = r.locale;
- var extension = "";
- var extensionSubtags = [];
- var extensionSubtagsLength = 0;
- var extensionIndex = 0;
- if (r.extension !== undefined) {
- extension = r.extension;
- extensionIndex = r.extensionIndex;
- extensionSubtags = extension.split("-");
- extensionSubtagsLength = extensionSubtags.length;
- }
- var result = new Record();
- result.set("dataLocale", foundLocale);
- var supportedExtension = "-u";
- var i = 0;
- var len = relevantExtensionKeys.length;
- while (i < len) {
- var key = relevantExtensionKeys[String(i)];
- var foundLocaleData = localeData[foundLocale];
- var keyLocaleData = foundLocaleData[key];
- var value = keyLocaleData["0"];
- var supportedExtensionAddition = "";
- if (typeof extensionSubtags !== "undefined") {
- var keyPos = extensionSubtags.indexOf(key);
- var valuePos;
- if (keyPos !== -1) {
- if (keyPos + 1 < extensionSubtagsLength
- && extensionSubtags[String(keyPos + 1)].length > 2) {
- var requestedValue = extensionSubtags[String(keyPos + 1)];
-
- if (requestedValue === "islamic" && extensionSubtags[String(keyPos + 2)]) {
- requestedValue += "-" + extensionSubtags[String(keyPos + 2)];
- }
- valuePos = keyLocaleData.indexOf(requestedValue);
- if (valuePos !== -1) {
- value = requestedValue;
- supportedExtensionAddition = "-" + key + "-" + value;
- }
- } else {
- valuePos = keyLocaleData.indexOf("true");
- if (valuePos !== -1) {
- value = "true";
- }
- }
- }
- }
- var optionsValue = options[key];
- if (optionsValue !== undefined) {
- if (keyLocaleData.indexOf(optionsValue) !== -1) {
- if (optionsValue !== value) {
- value = optionsValue;
- supportedExtensionAddition = "";
- }
- }
- }
- result.set(key, value);
- supportedExtension += supportedExtensionAddition;
- i++;
- }
- if (supportedExtension.length > 2) {
- var preExtension = foundLocale.substring(0, extensionIndex);
- var postExtension = foundLocale.substring(extensionIndex);
- foundLocale = preExtension + supportedExtension + postExtension;
- }
- result.set("locale", foundLocale);
- return result;
- },
-
-
- LookupSupportedLocales : function (availableLocales, requestedLocales) {
- var len = requestedLocales.length;
- var subset = new List();
- var k = 0;
- while (k < len) {
- var locale = requestedLocales[k];
- var noExtensionsLocale = locale.replace(this.unicodeLocaleExtensions, "");
- var availableLocale = this.BestAvailableLocale(availableLocales, noExtensionsLocale);
- if (availableLocale !== undefined) {
- subset.push(locale);
- }
- k++;
- }
- var subsetArray = subset.toArray();
- return subsetArray;
- },
-
- BestFitSupportedLocales : function (availableLocales, requestedLocales) {
- var len = requestedLocales.length;
- var subset = new List();
- var k = 0;
- while (k < len) {
- var locale = requestedLocales[k];
- var noExtensionsLocale = locale.replace(this.unicodeLocaleExtensions, "");
- var availableLocale = this.BestFitAvailableLocale(availableLocales, noExtensionsLocale);
- if (availableLocale !== undefined) {
- subset.push(locale);
- }
- k++;
- }
- var subsetArray = subset.toArray();
- return subsetArray;
- },
-
- SupportedLocales : function (availableLocales, requestedLocales, options) {
- var matcher;
- var subset;
- if (options !== undefined) {
- options = Object(options);
- matcher = options.localeMatcher;
- if (matcher !== undefined) {
- matcher = String(matcher);
- if (matcher !== "lookup" && matcher !== "best fit") {
- throw new RangeError("Matching algorithm must be 'lookup' or 'best fit'.");
- }
- }
- }
- if (matcher === undefined || matcher === "best fit") {
- subset = this.BestFitSupportedLocales(availableLocales, requestedLocales);
- } else {
- subset = this.LookupSupportedLocales(availableLocales, requestedLocales);
- }
- for (var P in Object.getOwnPropertyNames(subset)) {
- var desc = Object.getOwnPropertyDescriptor(subset, P);
- if (desc !== undefined) {
- desc.writable = false;
- desc.configurable = false;
- Object.defineProperty(subset, P, desc);
- }
- }
- Object.defineProperty(subset, "length", {
- writable : false,
- configurable : false
- });
- return subset;
- },
-
- GetOption : function (options, property, type, values, fallback) {
- var value = options[property];
- if (value !== undefined) {
- if (type === "boolean") {
- value = Boolean(value);
- }
- if (type === "string") {
- value = String(value);
- }
- if (values !== undefined) {
- for (var v in values) {
- if (values[v] === value) {
- return value;
- }
- }
- throw new RangeError("The specified value " + value + " for property " + property
- + " is invalid.");
- }
- return value;
- }
- return fallback;
- },
-
- GetNumberOption : function (options, property, minimum, maximum, fallback) {
- var value = options[property];
- if (value !== undefined) {
- value = Number(value);
- if (isNaN(value) || value < minimum || value > maximum) {
- throw new RangeError("The specified number value " + value + " is not in the allowed range");
- }
- return Math.floor(value);
- }
- return fallback;
- }
- };
- common.availableLocalesList = common.CanonicalizeLocaleList(JSON.parse(availableLocalesJson).availableLocales);
- return common;
- });
|