| //////////////////////////////////////////////////////////////////////////////// |
| // |
| // Licensed to the Apache Software Foundation (ASF) under one or more |
| // contributor license agreements. See the NOTICE file distributed with |
| // this work for additional information regarding copyright ownership. |
| // The ASF licenses this file to You under the Apache License, Version 2.0 |
| // (the "License"); you may not use this file except in compliance with |
| // the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| package mx.resources |
| { |
| |
| [ExcludeClass] |
| |
| /** |
| * @private |
| * The APIs of the LocaleSorter class provides the sorting functionality |
| * of application locales against system preferences. |
| */ |
| public class LocaleSorter |
| { |
| include "../core/Version.as"; |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Class methods |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| * Sorts a list of locales using the order specified |
| * by the user preferences. |
| * |
| * @param appLocales An Array of locales supported by the application. |
| * |
| * @param systemPreferences The locale chain of user-preferred locales. |
| * |
| * @param ultimateFallbackLocale The ultimate fallback locale |
| * that will be used when no locale from systemPreference matches |
| * a locale from application supported locale list. |
| * |
| * @param addAll When true, adds all the non-matching locales |
| * at the end of the result list preserving the given order. |
| * |
| * @return A locale chain that matches user preferences order. |
| */ |
| public static function sortLocalesByPreference( |
| appLocales:Array, systemPreferences:Array, |
| ultimateFallbackLocale:String = null, |
| addAll:Boolean = false):Array |
| { |
| var result:Array = []; |
| |
| var hasLocale:Object = {}; |
| |
| var i:int; |
| var j:int; |
| |
| var locales:Array = trimAndNormalize(appLocales); |
| var preferenceLocales:Array = trimAndNormalize(systemPreferences); |
| |
| addUltimateFallbackLocale(preferenceLocales, ultimateFallbackLocale); |
| |
| var noLocales:int = locales.length; |
| var noPreferenceLocales:int = preferenceLocales.length; |
| |
| // For better performance, save the locales in a lookup table. |
| for (j = 0; j < noLocales; j++) |
| { |
| hasLocale[locales[j]] = j; |
| } |
| |
| function promote(locale:String):void |
| { |
| if (typeof hasLocale[locale] != "undefined") |
| { |
| result.push(appLocales[hasLocale[locale]]); |
| delete hasLocale[locale]; |
| } |
| } |
| |
| var preferenceLocalesID:Vector.<LocaleID> = new Vector.<LocaleID>(noPreferenceLocales); |
| for (i = 0; i < noPreferenceLocales; i++) |
| { |
| preferenceLocalesID[i] = LocaleID.fromString(preferenceLocales[i]); |
| } |
| |
| var localesID:Vector.<LocaleID> = new Vector.<LocaleID>(noLocales); |
| for (i = 0; i < noLocales; i++) |
| { |
| localesID[i] = LocaleID.fromString(locales[i]); |
| } |
| |
| for (i = 0; i < noPreferenceLocales; i++) |
| { |
| var plocale:LocaleID = preferenceLocalesID[i].clone(); |
| |
| // Step 1: Promote the perfect match. |
| promote(preferenceLocales[i]); |
| |
| promote(plocale.toString()); |
| |
| // Step 2: Promote the parent chain. |
| while (plocale.transformToParent()) |
| { |
| promote(plocale.toString()); |
| } |
| |
| // Parse it again. |
| plocale = preferenceLocalesID[i].clone(); |
| |
| // Step 3: Promote the order of siblings from preferenceLocales. |
| for (j = 0; j < noPreferenceLocales; j++) |
| { |
| if (plocale.isSiblingOf(preferenceLocalesID[j])) |
| promote(preferenceLocales[j]); |
| } |
| |
| // Step 4: Promote all remaining siblings |
| // (aka not in preferenceLocales) |
| // eg. push en_UK after en_US and en if the user |
| // doesn't have en_UK in the preference list |
| for (j = 0; j < noLocales; j++) |
| { |
| if (plocale.isSiblingOf(localesID[j])) |
| promote(locales[j]); |
| } |
| } |
| |
| if (addAll) |
| { |
| // Check what locales are not already loaded |
| // and push them preserving the order. |
| for (j = 0; j < noLocales; j++) |
| { |
| promote(locales[j]); |
| } |
| } |
| |
| return result; |
| } |
| |
| /** |
| * @private |
| */ |
| private static function trimAndNormalize(list:Array):Array |
| { |
| var resultList:Array = []; |
| |
| for (var i:int = 0; i < list.length; i++) |
| { |
| resultList.push(normalizeLocale(list[i])); |
| } |
| |
| return resultList; |
| } |
| |
| /** |
| * @private |
| */ |
| private static function normalizeLocale(locale:String):String |
| { |
| return locale.toLowerCase().replace(/-/g, "_"); |
| } |
| |
| /** |
| * @private |
| */ |
| private static function addUltimateFallbackLocale( |
| preferenceLocales:Array, |
| ultimateFallbackLocale:String):void |
| { |
| if (ultimateFallbackLocale != null && ultimateFallbackLocale != "") |
| { |
| var locale:String = normalizeLocale(ultimateFallbackLocale); |
| |
| if (preferenceLocales.indexOf(locale) == -1) |
| { |
| // Add the locale to the end of the chain. |
| preferenceLocales.push(locale); |
| } |
| } |
| } |
| } |
| |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| // |
| // Helper class: LocaleID |
| // |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| /** |
| * @private |
| * The APIs of the internal LocaleID class parse a locale string |
| * according to: |
| * RFC 4646: http://www.ietf.org/rfc/rfc4646.txt |
| * RFC 4647: http://www.ietf.org/rfc/rfc4647.txt |
| * IANA Language Subtag Registry: |
| * http://www.iana.org/assignments/language-subtag-registry |
| */ |
| class LocaleID |
| { |
| //-------------------------------------------------------------------------- |
| // |
| // Class constants |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| */ |
| public static const STATE_PRIMARY_LANGUAGE:int = 0; |
| |
| /** |
| * @private |
| */ |
| public static const STATE_EXTENDED_LANGUAGES:int = 1; |
| |
| /** |
| * @private |
| */ |
| public static const STATE_SCRIPT:int = 2; |
| |
| /** |
| * @private |
| */ |
| public static const STATE_REGION:int = 3; |
| |
| /** |
| * @private |
| */ |
| public static const STATE_VARIANTS:int = 4; |
| |
| /** |
| * @private |
| */ |
| public static const STATE_EXTENSIONS:int = 5; |
| |
| /** |
| * @private |
| */ |
| public static const STATE_PRIVATES:int = 6; |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Class methods |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| */ |
| private static function appendElements(dest:Array, src:Array):void |
| { |
| for (var i:uint = 0, argc:uint = src.length; i < argc; i++) |
| { |
| dest.push(src[i]); |
| } |
| } |
| |
| /** |
| * @private |
| */ |
| public static function fromString(str:String):LocaleID |
| { |
| var localeID:LocaleID = new LocaleID(); |
| |
| var state:int = STATE_PRIMARY_LANGUAGE; |
| var subtags:Array = str.replace(/-/g, '_').split('_'); |
| |
| var last_extension:Array; |
| |
| for (var i:int = 0, l:int = subtags.length; i < l; i++) |
| { |
| var subtag:String = subtags[i].toLowerCase(); |
| |
| if (state == STATE_PRIMARY_LANGUAGE) |
| { |
| if (subtag == "x") |
| { |
| localeID.privateLangs = true; |
| // not used in our implementation, |
| // but makes the tag private |
| } |
| else if (subtag == "i") |
| { |
| localeID.lang += "i-"; |
| // and wait the next subtag |
| // to complete the language name |
| } |
| else |
| { |
| localeID.lang += subtag; |
| state = STATE_EXTENDED_LANGUAGES; |
| } |
| } |
| else |
| { |
| // looking for: |
| // an extended language - 3 chars |
| // a script - 4 chars |
| // a region - 2-3 chars |
| // a variant - alpha with at least 5 chars |
| // or numeric with at least 4 chars |
| // an extension/private singleton - 1 char |
| |
| var subtag_length:int = subtag.length; |
| if (subtag_length == 0) |
| continue; // skip zero-lengthed subtags |
| |
| var firstChar:String = subtag.charAt(0).toLowerCase(); |
| |
| if (state <= STATE_EXTENDED_LANGUAGES && |
| subtag_length == 3) |
| { |
| localeID.extended_langs.push(subtag); |
| if (localeID.extended_langs.length == 3) |
| { |
| // Allow a maximum of 3 extended langs. |
| state = STATE_SCRIPT; |
| } |
| } |
| else if (state <= STATE_SCRIPT && |
| subtag_length == 4) |
| { |
| localeID.script = subtag; |
| state = STATE_REGION; |
| } |
| else if (state <= STATE_REGION && |
| (subtag_length == 2 || subtag_length == 3)) |
| { |
| localeID.region = subtag; |
| state = STATE_VARIANTS; |
| } |
| else if (state <= STATE_VARIANTS && |
| ((firstChar >= "a" && firstChar <= "z" && |
| subtag_length >= 5) || |
| (firstChar >= "0" && firstChar <= "9" && |
| subtag_length >= 4))) |
| { |
| // variant |
| localeID.variants.push(subtag); |
| state = STATE_VARIANTS; |
| } |
| else if (state < STATE_PRIVATES && |
| subtag_length == 1) |
| { |
| // singleton |
| if (subtag == "x") |
| { |
| state = STATE_PRIVATES; |
| last_extension = localeID.privates; |
| } |
| else |
| { |
| state = STATE_EXTENSIONS; |
| last_extension = localeID.extensions[subtag] || []; |
| localeID.extensions[subtag] = last_extension; |
| } |
| } |
| else if (state >= STATE_EXTENSIONS) |
| { |
| last_extension.push(subtag); |
| } |
| } |
| } |
| |
| localeID.canonicalize(); |
| |
| return localeID; |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Constructor |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * Constructor. |
| * |
| * @langversion 3.0 |
| * @playerversion Flash 9 |
| * @playerversion AIR 1.1 |
| * @productversion Flex 3 |
| */ |
| public function LocaleID() |
| { |
| super(); |
| } |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Variables |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| */ |
| private var lang:String = ""; |
| |
| /** |
| * @private |
| */ |
| private var script:String = ""; |
| |
| /** |
| * @private |
| */ |
| private var region:String = ""; |
| |
| /** |
| * @private |
| */ |
| private var extended_langs:Array = []; |
| |
| /** |
| * @private |
| */ |
| private var variants:Array = []; |
| |
| /** |
| * @private |
| */ |
| private var extensions:Object = {}; |
| |
| /** |
| * @private |
| */ |
| private var privates:Array = []; |
| |
| /** |
| * @private |
| */ |
| private var privateLangs:Boolean = false; |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Methods |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| */ |
| public function clone():LocaleID { |
| |
| var copy:LocaleID = new LocaleID(); |
| copy.lang = lang; |
| copy.script = script; |
| copy.region = region; |
| copy.extended_langs = extended_langs.concat(); |
| copy.variants = variants.concat(); |
| copy.extensions = {}; |
| for (var i:String in extensions) |
| { |
| if (extensions.hasOwnProperty(i)) |
| { |
| copy.extensions[i] = extensions[i].concat(); |
| } |
| } |
| |
| copy.privates = privates.concat(); |
| copy.privateLangs = privateLangs; |
| |
| return copy; |
| } |
| |
| /** |
| * @private |
| */ |
| public function canonicalize():void |
| { |
| for (var i:String in extensions) |
| { |
| if (extensions.hasOwnProperty(i)) |
| { |
| // Also clear zero length extensions. |
| if (extensions[i].length == 0) |
| delete extensions[i]; |
| else |
| extensions[i] = extensions[i].sort(); |
| } |
| } |
| |
| extended_langs = extended_langs.sort(); |
| variants = variants.sort(); |
| privates = privates.sort(); |
| |
| if (script == "") |
| script = LocaleRegistry.getScriptByLang(lang); |
| |
| // Still no script, check the region. |
| if (script == "" && region != "") |
| script = LocaleRegistry.getScriptByLangAndRegion(lang, region); |
| |
| if (region == "" && script != "") |
| { |
| region = LocaleRegistry.getDefaultRegionForLangAndScript( |
| lang, script); |
| } |
| } |
| |
| /** |
| * @private |
| */ |
| public function toString():String |
| { |
| var stack:Array = [ lang ]; |
| |
| appendElements(stack, extended_langs); |
| |
| if (script != "") |
| stack.push(script); |
| |
| if (region != "") |
| stack.push(region); |
| |
| appendElements(stack, variants); |
| |
| for (var i:String in extensions) |
| { |
| if (extensions.hasOwnProperty(i)) |
| { |
| stack.push(i); |
| appendElements(stack, extensions[i]); |
| } |
| } |
| |
| if (privates.length > 0) |
| { |
| stack.push("x"); |
| appendElements(stack, privates); |
| } |
| |
| return stack.join("_"); |
| } |
| |
| /** |
| * @private |
| */ |
| public function equals(locale:LocaleID):Boolean |
| { |
| return toString() == locale.toString(); |
| } |
| |
| /** |
| * @private |
| */ |
| public function isSiblingOf(other:LocaleID):Boolean |
| { |
| return lang == other.lang && script == other.script; |
| } |
| |
| /** |
| * @private |
| */ |
| public function transformToParent():Boolean |
| { |
| if (privates.length > 0) |
| { |
| privates.splice(privates.length - 1, 1); |
| return true; |
| } |
| |
| var lastExtensionName:String = null; |
| for (var i:String in extensions) |
| { |
| if (extensions.hasOwnProperty(i)) |
| lastExtensionName = i; |
| } |
| |
| if (lastExtensionName) |
| { |
| var lastExtension:Array = extensions[lastExtensionName]; |
| if (lastExtension.length == 1) |
| { |
| delete extensions[lastExtensionName]; |
| return true; |
| } |
| lastExtension.splice(lastExtension.length - 1, 1); |
| return true; |
| } |
| |
| if (variants.length > 0) |
| { |
| variants.splice(variants.length - 1, 1); |
| return true; |
| } |
| |
| if (script != "") |
| { |
| // Check if we can suppress the script. |
| if (LocaleRegistry.getScriptByLang(lang) != "") |
| { |
| script = ""; |
| return true; |
| } |
| else if (region == "") |
| { |
| // Maybe the default region can suppress the script. |
| var defaultRegion:String = |
| LocaleRegistry.getDefaultRegionForLangAndScript( |
| lang, script); |
| if (defaultRegion != "") |
| { |
| region = defaultRegion; |
| script = ""; |
| return true; |
| } |
| } |
| } |
| |
| if (region != "") |
| { |
| if (!(script == "" && LocaleRegistry.getScriptByLang(lang) == "")) |
| { |
| region = ""; |
| return true; |
| } |
| } |
| |
| if (extended_langs.length > 0) |
| { |
| extended_langs.splice(extended_langs.length - 1, 1); |
| return true; |
| } |
| |
| return false; |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////////// |
| // |
| // Helper class: LocaleRegistry |
| // |
| //////////////////////////////////////////////////////////////////////////////// |
| |
| /** |
| * @private |
| */ |
| class LocaleRegistry |
| { |
| //-------------------------------------------------------------------------- |
| // |
| // Class constants |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| * A list of codes representing writing systems, in arbitrary order. |
| * For example, "latn" represents the Latin alphabet, used for |
| * writing languages such as English, French, Indonesian, and Swahili, |
| * and "arab" represents the Arabic script, used for writing |
| * Arabic, Persian, Pashto, and Urdu. |
| */ |
| private static const SCRIPTS:Array = |
| [ |
| "", // 0 |
| "latn", // 1 Latin |
| "ethi", // 2 Ethiopian |
| "arab", // 3 Arabic |
| "beng", // 4 Bengali |
| "cyrl", // 5 Cyrillic |
| "thaa", // 6 Thaana |
| "tibt", // 7 Tibetan |
| "grek", // 8 Greek |
| "gujr", // 9 Gujarati |
| "hebr", // 10 Hebrew |
| "deva", // 11 Devanagari |
| "armn", // 12 Armenian |
| "jpan", // 13 Japanese |
| "geor", // 14 Georgian |
| "khmr", // 15 Khmer |
| "knda", // 16 Kannada |
| "kore", // 17 Korean |
| "laoo", // 18 Lao |
| "mlym", // 19 Malayalam |
| "mymr", // 20 Burmese |
| "orya", // 21 Oriya |
| "guru", // 22 Punjabi |
| "sinh", // 23 Sinhalese |
| "taml", // 24 Tamil |
| "telu", // 25 Telugu |
| "thai", // 26 Thai |
| "nkoo", // 27 N'Ko |
| "blis", // 28 Bliss |
| "hans", // 29 Simplified Chinese |
| "hant", // 30 Traditional Chinese |
| "mong", // 31 Mongolian |
| "syrc" // 32 Syriac |
| ]; |
| |
| /** |
| * @private |
| * The inverse of the SCRIPT Array. |
| * Maps a script code (like "jpan" for Japanese) |
| * to its index in the SCRIPT Array. |
| */ |
| private static const SCRIPT_BY_ID:Object = |
| { |
| latn: 1, |
| ethi: 2, |
| arab: 3, |
| beng: 4, |
| cyrl: 5, |
| thaa: 6, |
| tibt: 7, |
| grek: 8, |
| gujr: 9, |
| hebr: 10, |
| deva: 11, |
| armn: 12, |
| jpan: 13, |
| geor: 14, |
| khmr: 15, |
| knda: 16, |
| kore: 17, |
| laoo: 18, |
| mlym: 19, |
| mymr: 20, |
| orya: 21, |
| guru: 22, |
| sinh: 23, |
| taml: 24, |
| telu: 25, |
| thai: 26, |
| nkoo: 27, |
| blis: 28, |
| hans: 29, |
| hant: 30, |
| mong: 31, |
| syrc: 32 |
| }; |
| |
| /** |
| * @private |
| * This table maps a language and a script to the most |
| * prominent region where that combination is used. |
| * |
| * Note: "is" must be quoted because it is a reserved word. |
| */ |
| private static const DEFAULT_REGION_BY_LANG_AND_SCRIPT:Object = |
| { |
| bg: { 5: "bg" }, // Bulgarian / Cyrillic -> Bulgaria |
| ca: { 1: "es" }, // Catalan / Latin -> Spain |
| zh: { 30: "tw", 29: "cn" }, // Chinese / Traditional Chinese -> Taiwan |
| // Chinese / Simplified Chinese -> China |
| cs: { 1: "cz" }, // Czech / Latin -> Czech Republic |
| da: { 1: "dk" }, // Danish / Latin -> Denmark |
| de: { 1: "de" }, // German / Latin -> Germany |
| el: { 8: "gr" }, // Greek / Greek -> Greece |
| en: { 1: "us" }, // English / Latin -> United States |
| es: { 1: "es" }, // Spanish / Latin -> Spain |
| fi: { 1: "fi" }, // Finnish / Latin -> Finland |
| fr: { 1: "fr" }, // French / Latin -> France |
| he: { 10: "il" }, // Hebrew / Hebrew -> Israel |
| hu: { 1: "hu" }, // Hungarian / Latin -> Hungary |
| "is": { 1: "is" }, // Icelandic / Latin -> Iceland |
| it: { 1: "it" }, // Italian / Latin -> Italy |
| ja: { 13: "jp" }, // Japanese / Japanese -> Japan |
| ko: { 17: "kr" }, // Korean / Korean -> Korea |
| nl: { 1: "nl" }, // Dutch / Latin -> Netherlands |
| nb: { 1: "no" }, // Norwegian Bokmaal / Latin -> Norway |
| pl: { 1: "pl" }, // Polish / Latin -> Poland |
| pt: { 1: "br" }, // Portuguese / Latin -> Brazil |
| ro: { 1: "ro" }, // Romanian / Latin -> Romania |
| ru: { 5: "ru" }, // Russian / Cyrillic -> Russia |
| hr: { 1: "hr" }, // Croatian / Latin -> Croatia |
| sk: { 1: "sk" }, // Slovak / Latin -> Slovakia |
| sq: { 1: "al" }, // Albanian / Latin -> Albania |
| sv: { 1: "se" }, // Swedish / Latin -> Sweden |
| th: { 26: "th" }, // Thai / Thai -> Thailand |
| tr: { 1: "tr" }, // Turkish / Latin -> Turkey |
| ur: { 3: "pk" }, // Urdu / Arabic -> Pakistan |
| id: { 1: "id" }, // Indonesian / Latin -> Indonesia |
| uk: { 5: "ua" }, // Ukrainian / Cyrillic -> Ukraine |
| be: { 5: "by" }, // Byelorussian / Cyrillic -> Belarus |
| sl: { 1: "si" }, // Slovenian / Latin -> Slovenia |
| et: { 1: "ee" }, // Estonian / Latin -> Estonia |
| lv: { 1: "lv" }, // Latvian / Latin -> Latvia |
| lt: { 1: "lt" }, // Lithuanian / Latin -> Lithuania |
| fa: { 3: "ir" }, // Persian / Arabic -> Iran |
| vi: { 1: "vn" }, // Vietnamese / Latin -> Vietnam |
| hy: { 12: "am"}, // Armenian / Armenian -> Armenia |
| az: { 1: "az", 5: "az" }, // Azerbaijani / Latin -> Azerbaijan |
| // Azerbaijani / Cyrillic -> Azerbaijan |
| eu: { 1: "es" }, // Basque / Latin -> Spain |
| mk: { 5: "mk" }, // Macedonian / Cyrillic -> Macedonia |
| af: { 1: "za" }, // Afrikaans / Latin -> South Africa |
| ka: { 14: "ge" }, // Georgian / Georgian -> Georgia |
| fo: { 1: "fo" }, // Faeroese / Latin -> Faroe Islands |
| hi: { 11: "in" }, // Hindi / Devanagari -> India |
| ms: { 1: "my" }, // Malay / Latin -> Malaysia |
| kk: { 5: "kz" }, // Kazakh / Cyrillic -> Kazakhstan |
| ky: { 5: "kg" }, // Kirghiz / Cyrillic -> Kyrgyzstan |
| sw: { 1: "ke" }, // Swahili / Latin -> Kenya |
| uz: { 1: "uz", 5: "uz" }, // Uzbek / Latin -> Uzbekistan |
| // Uzbek / Cyrillic -> Uzbekistan |
| tt: { 5: "ru" }, // Tatar / Cyrillic -> Russia |
| pa: { 22: "in" }, // Punjabi / Punjabi -> India |
| gu: { 9: "in" }, // Gujarati / Gujarati -> India |
| ta: { 24: "in" }, // Tamil / Tamil -> India |
| te: { 25: "in" }, // Telugu / Telugu -> India |
| kn: { 16: "in" }, // Kannada / Kannada -> India |
| mr: { 11: "in" }, // Marathi / Devanagari -> India |
| sa: { 11: "in" }, // Sanskrit / Devanagari -> India |
| mn: { 5: "mn" }, // Mongolian / Cyrillic -> Mongolia |
| gl: { 1: "es" }, // Galician / Latin -> Spain |
| kok: { 11: "in" }, // Konkani / Devanagari -> India |
| syr: { 32: "sy" }, // Syriac / Syriac -> Syria |
| dv: { 6: "mv" }, // Dhivehi / Thaana -> Maldives |
| nn: { 1: "no" }, // Norwegian Nynorsk / Latin -> Norway |
| sr: { 1: "cs", 5: "cs" }, // Serbian / Latin -> Serbia |
| // Serbian / Cyrillic -> Serbia |
| cy: { 1: "gb" }, // Welsh / Latin -> United Kingdom |
| mi: { 1: "nz" }, // Maori / Latin -> New Zealand |
| mt: { 1: "mt" }, // Maltese / Latin -> Malta |
| quz: { 1: "bo" }, // Quechua / Latin -> Bolivia |
| tn: { 1: "za" }, // Tswana / Latin -> South Africa |
| xh: { 1: "za" }, // Xhosa / Latin -> South Africa |
| zu: { 1: "za" }, // Zulu / Latin -> South Africa |
| nso: { 1: "za" }, // Northern Sotho / Latin -> South Africa |
| se: { 1: "no" }, // Northern Saami / Latin -> Norway |
| smj: { 1: "no" }, // Lule Saami / Latin -> Norway |
| sma: { 1: "no" }, // Southern Saami / Latin -> Norway |
| sms: { 1: "fi" }, // Skolt Saami / Latin -> Finland |
| smn: { 1: "fi" }, // Inari Saami / Latin -> Finland |
| bs: { 1: "ba" } // Bosnia / Latin -> Bosnia |
| }; |
| |
| /** |
| * @private |
| * This table maps a language to a script. |
| * It was derived from the entries at |
| * http://www.iana.org/assignments/language-subtag-registry |
| * which have a Suppress-Script property. |
| * |
| * Note: "as", "in", and "is" must be quoted |
| * because they are reserved words. |
| */ |
| private static const SCRIPT_ID_BY_LANG:Object = |
| { |
| ab: 5, // Abkhazian -> Cyrillic |
| af: 1, // Afrikaans -> Latin |
| am: 2, // Amharic -> Ethiopian |
| ar: 3, // Arabic -> Arabic |
| "as": 4, // Assamese -> Bengali |
| ay: 1, // Aymara -> Latin |
| be: 5, // Belarusian -> Cyrillic |
| bg: 5, // Bulgarian -> Cyrillic |
| bn: 4, // Bengali -> Bengali |
| bs: 1, // Bosnian -> Latin |
| ca: 1, // Catalan / Valencian -> Latin |
| ch: 1, // Chamorro -> Latin |
| cs: 1, // Czech -> Latin |
| cy: 1, // Welsh -> Latin |
| da: 1, // Danish -> Latin |
| de: 1, // German -> Latin |
| dv: 6, // Dhivehi / Maldivian -> Thaana |
| dz: 7, // Dzongkha -> Tibetan |
| el: 8, // Modern Greek -> Greek |
| en: 1, // English -> Latin |
| eo: 1, // Esperanto -> Latin |
| es: 1, // Spanish / Castilian -> Latin |
| et: 1, // Estonian -> Latin |
| eu: 1, // Basque -> Latin |
| fa: 3, // Persian -> Arabic |
| fi: 1, // Finnish -> Latin |
| fj: 1, // Fijian -> Latin |
| fo: 1, // Faroese -> Latin |
| fr: 1, // French -> Latin |
| frr: 1, // Northern Frisian -> Latin |
| fy: 1, // Western Frisian -> Latin |
| ga: 1, // Irish -> Latin |
| gl: 1, // Galician -> Latin |
| gn: 1, // Guarani -> Latin |
| gu: 9, // Gujarati -> Gujarati |
| gv: 1, // Manx -> Latin |
| he: 10, // Hebrew -> Hebrew |
| hi: 11, // Hindi -> Devanagari |
| hr: 1, // Croatian -> Latin |
| ht: 1, // Haitian Creole -> Latin |
| hu: 1, // Hungarian -> Latin |
| hy: 12, // Armenian -> Armenian |
| id: 1, // Indonesian -> Latin |
| "in": 1, // Indonesian -> Latin |
| "is": 1, // Icelandic -> Latin |
| it: 1, // Italian -> Latin |
| iw: 10, // Hebrew -> Hebrew |
| ja: 13, // Japanese -> Japanese |
| ka: 14, // Georgian -> Georgian |
| kk: 5, // Kazakh -> Cyrillic |
| kl: 1, // Kalaallisut / Greenlandic -> Latin |
| km: 15, // Central Khmer -> Khmer |
| kn: 16, // Kannada -> Kannada |
| ko: 17, // Korean -> Korean |
| la: 1, // Latin -> Latin |
| lb: 1, // Luxembourgish -> Latin |
| ln: 1, // Lingala -> Latin |
| lo: 18, // Lao -> Lao |
| lt: 1, // Lithuanian -> Latin |
| lv: 1, // Latvian -> Latin |
| mg: 1, // Malagasy -> Latin |
| mh: 1, // Marshallese -> Latin |
| mk: 5, // Macedonian -> Cyrillic |
| ml: 19, // Malayalam -> Malayalam |
| mo: 1, // Moldavian -> Latin |
| mr: 11, // Marathi -> Devanagari |
| ms: 1, // Malay -> Latin |
| mt: 1, // Maltese -> Latin |
| my: 20, // Burmese -> Burmese |
| na: 1, // Nauru -> Latin |
| nb: 1, // Norwegian Bokmaal -> Latin |
| nd: 1, // North Ndebele -> Latin |
| ne: 11, // Nepali -> Devanagari |
| nl: 1, // Dutch / Flemish -> Latin |
| nn: 1, // Norwegian Nynorsk -> Latin |
| no: 1, // Norwegian -> Latin |
| nr: 1, // South Ndebele -> Latin |
| ny: 1, // Chichewa / Chewa / Nyanja -> Latin |
| om: 1, // Oromo -> Latin |
| or: 21, // Oriya -> Oriya |
| pa: 22, // Punjabi -> Punjabi |
| pl: 1, // Polish -> Latin |
| ps: 3, // Pashto -> Arabic |
| pt: 1, // Portuguese -> Latin |
| qu: 1, // Quechua -> Latin |
| rn: 1, // Rundi -> Latin |
| ro: 1, // Romanian -> Latin |
| ru: 5, // Russian -> Cyrillic |
| rw: 1, // Kinyarwanda -> Latin |
| sg: 1, // Sango -> Latin |
| si: 23, // Sinhalese -> Sinhalese |
| sk: 1, // Slovak -> Latin |
| sl: 1, // Slovenian -> Latin |
| sm: 1, // Samoan -> Latin |
| so: 1, // Somali -> Latin |
| sq: 1, // Albanian -> Latin |
| ss: 1, // Swati -> Latin |
| st: 1, // Southern Sotho -> Latin |
| sv: 1, // Swedish -> Latin |
| sw: 1, // Swahili -> Latin |
| ta: 24, // Tamil -> Tamil |
| te: 25, // Telugu -> Telugu |
| th: 26, // Thai -> Thai |
| ti: 2, // Tigrinya -> Ethiopian |
| tl: 1, // Tagalog -> Latin |
| tn: 1, // Tswana -> Latin |
| to: 1, // Tonga -> Latin |
| tr: 1, // Turkish -> Latin |
| ts: 1, // Tsonga -> Latin |
| uk: 5, // Ukrainian -> Cyrillic |
| ur: 3, // Urdu -> Arabic |
| ve: 1, // Venda -> Latin |
| vi: 1, // Vietnamese -> Latin |
| wo: 1, // Wolof -> Latin |
| xh: 1, // Xhosa -> Latin |
| yi: 10, // Yiddish -> Hebrew |
| zu: 1, // Zulu -> Latin |
| cpe: 1, // Creoles and pidgins -> Latin |
| dsb: 1, // Lower Sorbian -> Latin |
| frs: 1, // Eastern Frisian -> Latin |
| gsw: 1, // Swiss German / Alemaanic / Alsatian -> Latin |
| hsb: 1, // Upper Sorbian -> Latin |
| kok: 11, // Konkana -> Devanagari |
| mai: 11, // Maithili -> Devanagari |
| men: 1, // Mende -> Latin |
| nds: 1, // Low German -> Latin |
| niu: 1, // Niuean -> Latin |
| nqo: 27, // N'Ko -> N'Ko |
| nso: 1, // Northern Sotho / Pedi / Sepedi -> Latin |
| son: 1, // Songhai -> Latin |
| tem: 1, // Timne -> Latin |
| tkl: 1, // Tokelau -> Latin |
| tmh: 1, // Tamashek -> Latin |
| tpi: 1, // Tok Pisin -> Latin |
| tvl: 1, // Tuvalu -> Latin |
| zbl: 28 // Bliss -> Bliss |
| }; |
| |
| /** |
| * @private |
| * This table maps a language-as-spoken-in-a-region |
| * to the script used to write it. |
| * |
| * Chinese in China -> Simplified Chinese |
| * Chinese in Singapore -> Simplified Chinese |
| * Chinese in Taiwan -> Traditional Chinese |
| * Chinese in Hong Kong -> Traditional Chinese |
| * Chinese in Macao -> Traditional Chinese |
| * Mongolian in China -> Mongolian |
| * Mongolian in Singapore -> Cyrillic |
| * Punjabi in Pakistan -> Arabic |
| * Punjabi in India -> Punjabi |
| * Hausa in Ghana -> Latin |
| * Hausa in Niger -> Latin |
| */ |
| private static const SCRIPT_ID_BY_LANG_AND_REGION:Object = |
| { |
| zh: { cn: 29, sg: 29, tw: 30, hk: 30, mo: 30 }, |
| mn: { cn: 31, sg: 5 }, |
| pa: { pk: 3, "in": 22 }, // "in" is reserved word |
| ha: { gh: 1, ne: 1 } |
| }; |
| |
| //-------------------------------------------------------------------------- |
| // |
| // Class methods |
| // |
| //-------------------------------------------------------------------------- |
| |
| /** |
| * @private |
| * Given a language and a region, returns the script system |
| * used to write the language there. |
| * |
| * Examples: |
| * lang zh (Chinese), region cn (China) -> hans (Simplified Chinese) |
| * lang zh (Chinese), region tw (Taiwan) -> hast (Traditional Chinese) |
| */ |
| public static function getScriptByLangAndRegion( |
| lang:String, region:String):String |
| { |
| var langRegions:Object = SCRIPT_ID_BY_LANG_AND_REGION[lang]; |
| if (langRegions == null) |
| return ""; |
| |
| var scriptID:Object = langRegions[region]; |
| if (scriptID == null) |
| return ""; |
| |
| return SCRIPTS[int(scriptID)].toLowerCase(); |
| } |
| |
| /** |
| * @private |
| * Given a language, returns the script generally used to write it. |
| * |
| * Examples: |
| * lang bg (Bulgarian) -> cyrl (Cyrillic) |
| */ |
| public static function getScriptByLang(lang:String):String |
| { |
| var scriptID:Object = SCRIPT_ID_BY_LANG[lang]; |
| if (scriptID == null) |
| return ""; |
| |
| return SCRIPTS[int(scriptID)].toLowerCase(); |
| } |
| |
| /** |
| * @private |
| * Given a language and a script used for writing it, |
| * returns the most prominent region where that combination is used. |
| * |
| * Examples: |
| */ |
| public static function getDefaultRegionForLangAndScript( |
| lang:String, script:String):String |
| { |
| var langObj:Object = DEFAULT_REGION_BY_LANG_AND_SCRIPT[lang]; |
| var scriptID:Object = SCRIPT_BY_ID[script]; |
| if (langObj == null || scriptID == null) |
| return ""; |
| |
| return langObj[int(scriptID)] || ""; |
| } |
| } |