blob: b260b7fa0b106352d4d249d0507a2a72137508f3 [file] [log] [blame]
////////////////////////////////////////////////////////////////////////////////
//
// 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)] || "";
}
}