User:So9q/Improved-xte.js

Hello, you have come here looking for the meaning of the word User:So9q/Improved-xte.js. In DICTIOUS you will not only get to know all the dictionary meanings for the word User:So9q/Improved-xte.js, but we will also tell you about its etymology, its characteristics and you will know how to say User:So9q/Improved-xte.js in singular and plural. Everything you need to know about the word User:So9q/Improved-xte.js you have here. The definition of the word User:So9q/Improved-xte.js will help you to be more precise and correct when speaking or writing your texts. Knowing the definition ofUser:So9q/Improved-xte.js, as well as those of other words, enriches your vocabulary and provides you with more and better linguistic resources.
// so9q's improved-xte.js
// original source: ]
/*jshint shadow:true, scripturl:true, undef:true, latedef:true, boss:true, loopfunc:true, unused:true */ // <nowiki>
/*global mw, jQuery */
mw.loader.using(, function() {
"use strict";
la
// PRO settings
// Warning if you enable this you have to carefully review the changes to ensure 
// that you do not introduce errors.
var xtepro = true;  // enable with caution!
// set these langs do disable adding {{attention}} for them automatically
var prolangs = ;


var code2nameLookup = null;
var code2scLookup = null;

var name2codeLookup = {
	// "false" values indicate translation groups, i.e. names with no own code under which
	// distinct languages are kept together, like Chinese which contains the Mandarin (cmn),
	// Cantonese (yue) and Min Nan (nan) varieties as sub-items. xte warns when translations
	// are found directly under group headers, and ignores them otherwise.
	// Greek (el) for example should not be added here, because translations directly under
	// "Greek" item are accepted, even though "Greek" serves as a parent for Ancient Greek (grc)
	"Apache"               : false,
	"Sorbian"              : false,
	"Berber"               : false,
	"Sami"                 : false,
	"Marquesan"            : false,
	"Miwok"                : false,
	// so9q speedup
	"Aghul" : "agx",
"Akhvakh" : "akv",
"Andi" : "ani",
"Angor" : "agg",
"Hebrew Classical Syriac" : "null",
"Asháninka" : "cni",
"Avestan" : "ae",
"Bactrian" : "xbc",
"Bagvalal" : "kva",
"Bakung" : "xkl",
"Banda" : "bnd",
"Banggai" : "bgz",
"Beja" : "bej",
"Bemba" : "bem",
"Bilba" : "bpz",
"Bintulu" : "bny",
"Botlikh" : "bph",
"Bouyei" : "pcc",
"Middle Breton Breton" : "null",
"Middle Breton" : "xbm",
"Brunei Bisaya" : "bsb",
"Budukh" : "bdk",
"Bunun" : "bnn",
"Car Nicobarese" : "caq",
"Carrier" : "crx",
"Chakma" : "ccp",
"Chamalal" : "cji",
"Chamorro" : "ch",
"Chru" : "cje",
"Cia-Cia" : "cia",
"Coastal Kadazan" : "kzj",
"Comanche" : "com",
"Dusner" : "dsn",
"Middle Dutch Dutch" : "null",
"Middle Dutch" : "dum",
"Dyirbal" : "dbl",
"Eritai" : "ert",
"Eshtehardi" : "esh",
"Even" : "eve",
"Old French Middle French" : "null",
"North Frisian Frisian" : "null",
"Old Frisian North Frisian" : "null",
"Old Frisian" : "ofs",
"Saterland Frisian Old Frisian" : "null",
"West Frisian Saterland Frisian" : "null",
"Gallurese" : "sdn",
"Gaulish" : "cel-gau",
"Gayo" : "gay",
"Ge'ez" : "gez",
"Middle High German German" : "null",
"Middle High German" : "gmh",
"Old High German Middle High German" : "null",
"Old High German" : "goh",
"Guerrero Amuzgo" : "amu",
"Gurindji" : "gue",
"Guugu Yimidhirr" : "kky",
"Hadrami" : "xhd",
"Han" : "haa",
"Havasupai-Walapai-Yavapai" : "yuf",
"Hunzib" : "huz",
"Igbo" : "ig",
"Ilocano" : "ilo",
"Iranun" : "ill",
"Isthmus Zapotec" : "zai",
"Old Javanese Javanese" : "null",
"Old Javanese" : "kaw",
"Karata" : "kpt",
"Kemak" : "kem",
"Khasi" : "kha",
"Khinalug" : "kjj",
"Kickapoo" : "kic",
"Kimaragang" : "kqr",
"Klallam" : "clm",
"Kongo" : "kg",
"Krisa" : "ksi",
"Kuna" : "cuk",
"Kwanyama" : "kj",
"Munsee Lenape" : "null",
"Leti (Indonesia)" : "lti",
"Middle Low German German Low German" : "null",
"Middle Low German" : "gml",
"Loxicha Zapotec" : "ztp",
"Maasai" : "mas",
"Madurese" : "mad",
"Makasar" : "mak",
"Jawi Malay" : "null",
"Jawi" : "null",
"Rumi Malay" : "null",
"Rumi" : "null",
"Mansi" : "mns",
"Marshallese" : "mh",
"Mayo" : "mfy",
"Mbabaram" : "vmb",
"Old Median" : "xme-old",
"Mende" : "men",
"Middle English" : "enm",
"Minangkabau" : "min",
"Mingo" : "iro-min",
"Miskito" : "miq",
"Mon" : "mnw",
"Montana Salish" : "fla",
"Nauruan" : "na",
"Negidal" : "neg",
"Nenets" : "yrk",
"Newar" : "new",
"Ngiyambaa" : "wyb",
"Nias" : "nia",
"Northern Amami-Oshima" : "ryn",
"Nuer" : "nus",
"Manitoba Saulteux Ojibwe" : "null",
"Manitoba Saulteux" : "null",
"Oroch" : "oac",
"Orok" : "oaa",
"Pamona" : "pmf",
"Pangasinan" : "pag",
"Paulohi" : "plh",
"Middle Persian Persian" : "null",
"Middle Persian" : "pal",
"Phoenician" : "phn",
"Phrygian" : "xpg",
"Pohnpeian" : "pon",
"Draweno-Polabian Polabian" : "null",
"Draweno-Polabian" : "null",
"Modern Polabian Polabian" : "null",
"Modern Polabian" : "null",
"Old Polabian Polabian" : "null",
"Old Polabian" : "null",
"Rade" : "rad",
"Rutul" : "rut",
"Rwanda-Rundi" : "rw",
"S'gaw Karen" : "ksw",
"Sabaean" : "xsa",
"Santali" : "sat",
"Campidanese Sardinian" : "sc",
"Sassarese" : "sdc",
"Sebop" : "sib",
"Seri" : "sei",
"Sherpa" : "xsr",
"Simeulue" : "smr",
"Siraya" : "fos",
"Southern Amami-Oshima" : "ams",
"Southern Puebla Mixtec" : "mit",
"Southern Thai" : "sou",
"Sumbawa" : "smw",
"Swazi" : "ss",
"Tae'" : "rob",
"Tagal Murut" : "mvv",
"Tat" : "ttt",
"Ter Sami" : "sjt",
"Tigre" : "tig",
"Tiwi" : "tiw",
"Toba Batak" : "bbc",
"Tontemboan" : "tnt",
"Tsakhur" : "tkr",
"Tulu" : "tcy",
"Uab Meto" : "aoz",
"Udi" : "udi",
"Ulch" : "ulc",
"Middle Welsh Welsh" : "null",
"Middle Welsh" : "wlm",
"Western Maninkakan" : "mlq",
"Yaeyama" : "rys",
"Yakan" : "yka",
"Yamdena" : "jmd",
"Yan-nhangu" : "jay",
"Yapese" : "yap",
"Yaweyuha" : "yby",
"Yonaguni" : "yoi",
"Yuchi" : "yuc",
"Záparo" : "zro",
"Old French French" : "null",
"Pirahã" : "myp",
	"Abaza" : "abq",
"Atayal" : "tay",
"Baekje" : "pkc",
"Bahnar" : "bdq",
"Bats" : "bbl",
"Bau Bidayuh" : "sne",
"Bezhta" : "kap",
"Chepang" : "cdm",
"Min-nan Min Dong" : "null",
"Min-nan" : "null",
"Min-nan Chinese" : "null",
"Wu Min Dong" : "null",
"Chipewyan" : "chp",
"Northern East Cree" : "crl",
"Plains Northern East" : "null",
"Plains" : "null",
"Plains Cree" : "crk",
"Southern East Plains" : "null",
"Southern East" : "null",
"Southern East Cree" : "crj",
"Dargwa" : "dar",
"Dzongkha" : "dz",
"Eastern Cham" : "cjm",
"Frisian" : "fy",
"Saterland North" : "null",
"Saterland" : "null",
"Saterland Frisian" : "stq",
"West Saterland" : "null",
"West" : "null",
"Godoberi" : "gdo",
"Pontic Greek Ancient" : "null",
"Pontic Greek" : "pnt",
"Itelmen" : "itl",
"Jingpho" : "kac",
"Kabardian" : "kbd",
"Karaim" : "kdr",
"Karakhanid" : "xqa",
"Ket" : "ket",
"Komi-Zyrian" : "kpv",
"Koryak" : "kpy",
"Lak" : "lbe",
"Lenape" : "null",
"Munsee null" : "null",
"Unami Munsee" : "null",
"Lolopo" : "ycl",
"Machiguenga" : "mcb",
"Mazanderani" : "mzn",
"Montagnais" : "moe",
"Muong" : "mtq",
"Nanai" : "gld",
"Nganasan" : "nio",
"Nivkh" : "niv",
"Northern Sotho" : "nso",
"Northern Yukaghir" : "ykg",
"Old Saxon" : "osx",
"Oroqen" : "orh",
"Ottawa" : "otw",
"Pacoh" : "pac",
"Plautdietsch" : "pdt",
"Kildin Inari" : "null",
"Kildin" : "null",
"Kildin Sami" : "sjd",
"Northern Kildin" : "null",
"Selkup" : "sel",
"Shuswap" : "shs",
"Southern Kam" : "kmc",
"Svan" : "sva",
"Tabasaran" : "tab",
"Tachawit" : "shy",
"Tindi" : "tin",
"Tofa" : "kim",
"Tsez" : "ddo",
"Tundra Enets" : "enh",
"Ugaritic" : "uga",
"Yurok" : "yur",
	"Aba" : "utp",
"Abanyom" : "abm",
"Abau" : "aau",
"Abenaki" : "abe",
"Abenlen Ayta" : "abp",
"Abua" : "abn",
"Abung" : "abl",
"Acatepec Me'phaa" : "tpx",
"Achagua" : "aca",
"Agarabi" : "agd",
"Agi" : "aif",
"Ahtna" : "aht",
"Aisi" : "mmq",
"Aklanon" : "akl",
"Akolet" : "akt",
"Akoye" : "miw",
"Akuwagel" : "bey",
"Alaba" : "alw",
"Alak" : "alk",
"Algonquin" : "alq",
"Alsea" : "aes",
"Alune" : "alp",
"Alutiiq" : "ems",
"Amahuaca" : "amc",
"Amal" : "aad",
"Amasi" : "alv-ama",
"Amele" : "aey",
"Amondawa" : "adw",
"Anaang" : "anw",
"Angolar" : "aoa",
"Anmatyerre" : "amx",
"Annobonese" : "fab",
"Antigua and Barbuda Creole English" : "aig",
"Antillean Creole" : "gcf",
"Anuki" : "aui",
"Anus" : "auq",
"Anuta" : "aud",
"Ao" : "njo",
"Apiaká" : "api",
"Apinayé" : "apn",
"Apurinã" : "apu",
"Aputai" : "apx",
"Moroccan Arabic Egyptian Arabic" : "null",
"Araki" : "akr",
"Classical Syriac Aramaic" : "null",
"Arapaho" : "arp",
"Archi" : "aqc",
"Are" : "mwc",
"Arhuaco" : "arh",
"Ari" : "aac",
"Arifama-Miniafia" : "aai",
"Arikara" : "ari",
"Aruop" : "lsr",
"Ashéninka Perené" : "prq",
"Assiniboine" : "asb",
"Asumboa" : "aua",
"Atakapa" : "aqp",
"Atong (India)" : "aot",
"Au" : "avt",
"Aukan" : "djk",
"Avikam" : "avi",
"Awa-Cuaiquer" : "kwi",
"Awadhi" : "awa",
"Awtuw" : "kmn",
"Ayabadhu" : "ayd",
"Aynu" : "aib",
"Bagusa" : "bqb",
"Baldemu" : "bdn",
"Bambam" : "ptu",
"Bamu" : "bcf",
"Baniwa" : "bwi",
"Bankon" : "abb",
"Bantawa" : "bap",
"Barasana" : "bsn",
"Barbareño" : "boi",
"Bardi" : "bcj",
"Bargam" : "mlp",
"Bari" : "bfa",
"Bariai" : "bch",
"Bariji" : "bjc",
"Barok" : "bjk",
"Barí" : "mot",
"Batad Ifugao" : "ifb",
"Batu" : "btu",
"Bau" : "bbd",
"Bauro" : "bxa",
"Beezen" : "bnz",
"Belizean Creole" : "bzj",
"Bende" : "bdp",
"Berbice Creole Dutch" : "brc",
"Biak" : "bhw",
"Bibaali" : "bcn",
"Biem" : "bmc",
"Bih" : "ibh",
"Bilbil" : "brz",
"Biliau" : "bcu",
"Biloxi" : "bll",
"Bilur" : "bxf",
"Binukid" : "bkd",
"Bitare" : "brt",
"Bogaya" : "boq",
"Bole" : "bol",
"Bonggo" : "bpg",
"Bora" : "boa",
"Borôro" : "bor",
"Boselewa" : "bwf",
"Bourguignon" : "roa-brg",
"Bughotu" : "bgt",
"Buhutu" : "bxh",
"Bukawa" : "buk",
"Bukusu" : "bxk",
"Buli (Ghana)" : "bwu",
"Buli (Indonesia)" : "bzq",
"Bulu (New Guinea)" : "bjl",
"Bunama" : "bdd",
"Buwal" : "bhs",
"Bwaidoka" : "bwd",
"Bwanabwana" : "tte",
"Bwatoo" : "bwa",
"Cacua" : "cbv",
"Caddo" : "cad",
"Cahuilla" : "chl",
"Caka" : "ckx",
"Camarines Norte Agta" : "abd",
"Cameroon Pidgin" : "wes",
"Camsá" : "kbh",
"Carapana" : "cbc",
"Carijona" : "cbd",
"Casiguran Dumagat Agta" : "dgc",
"Cavineña" : "cav",
"Cayuga" : "cay",
"Cebuano" : "ceb",
"Cemuhî" : "cam",
"Central Bai" : "bca",
"Central Bontoc" : "lbk",
"Central Cagayan Agta" : "agt",
"Central Pomo" : "poo",
"Central Tunebo" : "tuf",
"Ch'orti'" : "caa",
"Chachi" : "cbi",
"Chaha" : "sem-cha",
"Champenois" : "roa-cha",
"Chavacano" : "cbk",
"Chayahuita" : "cbt",
"Chewong" : "cwg",
"Chichicapan Zapotec" : "zpv",
"Chickasaw" : "cic",
"Chimila" : "cbg",
"Chimwiini" : "bnt-cmw",
"Chinook Jargon" : "chn",
"Chiquihuitlán Mazatec" : "maq",
"Chiquimulilla" : "nai-chi",
"Chitimacha" : "ctm",
"Chrau" : "crw",
"Chuukese" : "chk",
"Cimbrian" : "cim",
"Cinta Larga" : "cin",
"Coast Miwok" : "csi",
"Coatzospan Mixtec" : "miz",
"Cocama" : "cod",
"Cocopa" : "coc",
"Cogui" : "kog",
"Coos" : "csz",
"Copainalá Zoque" : "zoc",
"Cora" : "crn",
"Corsican" : "co",
"Creek" : "mus",
"Cruzeño" : "crz",
"Cubeo" : "cub",
"Cuiba" : "cui",
"Culli" : "sai-cul",
"Curripaco" : "kpc",
"Daasanach" : "dsh",
"Dakota" : "dak",
"Dawawa" : "dww",
"Day" : "dai",
"Deccani" : "dcc",
"Deg Xinag" : "ing",
"Dena'ina" : "tfn",
"Dení" : "dny",
"Desano" : "des",
"Dia" : "dia",
"Dibiyaso" : "dby",
"Dilling" : "dil",
"Dime" : "dim",
"Diodio" : "ddi",
"Dobu" : "dob",
"Doga" : "dgg",
"Dogrib" : "dgr",
"Dongolawi" : "kzh",
"Dorig" : "wwo",
"Drehu" : "dhv",
"Duau" : "dva",
"Dumi" : "dus",
"Dupaningan Agta" : "duo",
"Duwet" : "gve",
"East Futuna" : "fud",
"Eastern Arrernte" : "aer",
"Efik" : "efi",
"Efutop" : "ofu",
"Ega" : "ega",
"Ekajuk" : "eka",
"Elfdalian" : "ovd",
"Elkei" : "elk",
"Eman" : "emn",
"Emberá-Catío" : "cto",
"Emberá-Chamí" : "cmi",
"Emberá-Tadó" : "tdc",
"Emerillon" : "eme",
"Ende" : "end",
"Epena" : "sja",
"Ese Ejja" : "ese",
"Esimbi" : "ags",
"Eton (Cameroon)" : "eto",
"Evant" : "bzz",
"Fagani" : "faf",
"Fala" : "fax",
"Folopa" : "ppo",
"Fon" : "fon",
"Fox" : "sac",
"Middle French French" : "null",
"Middle French" : "frm",
"Fulniô" : "fun",
"Gabadi" : "kbt",
"Gagadu" : "gbu",
"Gallo" : "roa-gal",
"Gapapaiwa" : "pwg",
"Gedaged" : "gdd",
"Gela" : "nlg",
"Rhine Franconian Alemannic German" : "null",
"Rhine Franconian" : "gmw-rfr",
"Ghari" : "gri",
"Ghayavi" : "bmk",
"Gidar" : "gid",
"Gilbertese" : "gil",
"Girawa" : "bbr",
"Gobasi" : "goi",
"Goemai" : "ank",
"Golin" : "gvf",
"Gooniyandi" : "gni",
"Gottscheerish" : "gmw-gts",
"Grass Koiari" : "kbk",
"Modern Ancient" : "null",
"Modern" : "null",
"Modern Greek" : "el",
"Grenadian Creole English" : "gcl",
"Gros Ventre" : "ats",
"Guahibo" : "guh",
"Guajajára" : "gub",
"Guambiano" : "gum",
"Guanano" : "gvc",
"Guayabero" : "guo",
"Guazacapán" : "nai-guz",
"Guianese Creole" : "gcr",
"Guinea-Bissau Creole" : "pov",
"Gullah" : "gul",
"Gumatj" : "gnn",
"Gweda" : "grw",
"Haida" : "hai",
"Hamtai" : "hmt",
"Hanunoo" : "hnn",
"Harsusi" : "hss",
"Hazaragi" : "haz",
"Hdi" : "xed",
"Hidatsa" : "hid",
"Highland Totonac" : "tos",
"Hiligaynon" : "hil",
"Hinukh" : "gin",
"Hiw" : "hiw",
"Hoava" : "hoa",
"Hote" : "hot",
"Hoyahoya" : "hhy",
"Huehuetla Tepehua" : "tee",
"Hupa" : "hup",
"Hupdë" : "jup",
"Iamalele" : "yml",
"Iau" : "tmu",
"Iceve-Maci" : "bec",
"Ida'an" : "dbj",
"Ignaciano" : "ign",
"Imonda" : "imn",
"Inebu One" : "oin",
"Ineseño" : "inz",
"Inga" : "inb",
"Ingrian" : "izh",
"Ipulo" : "ass",
"Iraqw" : "irk",
"Isan" : "tts",
"Islander Creole English" : "icr",
"Itzá" : "itz",
"Iwam" : "iwm",
"Ixil" : "ixl",
"Iyive" : "uiv",
"Izon" : "ijc",
"Jabutí" : "jbt",
"Jamaican Creole" : "jam",
"Jamamadí" : "jaa",
"Jaminjung" : "djd",
"Janday" : "jan",
"Jarai" : "jra",
"Jebero" : "jeb",
"Jehai" : "jhi",
"Jemez" : "tow",
"Jingulu" : "jig",
"Jola-Fonyi" : "dyo",
"Juǀ'hoan" : "ktz",
"Kabuverdianu" : "kea",
"Kadaru" : "kdu",
"Kadiwéu" : "kbc",
"Kaera" : "jka",
"Kahua" : "agw",
"Kaiep" : "kbw",
"Kairiru" : "kxa",
"Kakabai" : "kqf",
"Kala Lagaw Ya" : "mwp",
"Kamasau" : "kms",
"Kamayurá" : "kay",
"Kambera" : "xbr",
"Kamula" : "xla",
"Kandas" : "kqw",
"Kaninuwa" : "wat",
"Kankanaey" : "kne",
"Kanoé" : "kxo",
"Kansa" : "ksk",
"Kanufi" : "kni",
"Kap" : "ykm",
"Kapampangan" : "pam",
"Kara (New Guinea)" : "leu",
"Karajá" : "kpj",
"Karawa" : "xrw",
"Karitiâna" : "ktn",
"Karok" : "kyh",
"Kaska" : "kkz",
"Kaskihá" : "gva",
"Kasua" : "khs",
"Kathlamet" : "nai-kat",
"Kato" : "ktw",
"Kawaiisu" : "xaw",
"Kaxararí" : "ktx",
"Kayabí" : "kyz",
"Kayardild" : "gyd",
"Keapara" : "khz",
"Kedang" : "ksx",
"Kein" : "bmh",
"Kerewo" : "kxz",
"Khanty" : "kca",
"Khowar" : "khw",
"Kilivila" : "kij",
"Kinikinao" : "gqn",
"Kirikiri" : "kiy",
"Kis" : "kis",
"Kitsai" : "kii",
"Klamath-Modoc" : "kla",
"Koasati" : "cku",
"Koho" : "kpm",
"Kokota" : "kkk",
"Koluwawa" : "klx",
"Kom (Cameroon)" : "bkm",
"Kombio" : "xbi",
"Komering" : "kge",
"Komodo" : "kvh",
"Konomala" : "koa",
"Konomihu" : "nai-knm",
"Koreguaje" : "coe",
"Korlai Creole Portuguese" : "vkp",
"Koronadal Blaan" : "bpr",
"Kott" : "zko",
"Kovai" : "kqb",
"Kove" : "kvc",
"Koyra Chiini" : "khq",
"Koyraboro Senni" : "ses",
"Kpasam" : "pbn",
"Krio" : "kri",
"Kriol" : "rop",
"Kristang" : "mcm",
"Krobu" : "kxb",
"Kua-nsi" : "ykn",
"Kuamasi" : "yku",
"Kumak" : "nee",
"Kuman" : "kue",
"Central Kurdish Kurdish" : "null",
"Central Kurdish" : "ckb",
"Laki Central Kurdish" : "null",
"Laki" : "lki",
"Northern Kurdish Laki" : "null",
"Northern Kurdish" : "kmr",
"Southern Kurdish Northern Kurdish" : "null",
"Southern Kurdish" : "sdh",
"Kutenai" : "kut",
"Kwaio" : "kwd",
"Kwaza" : "xwa",
"Kwerba" : "kwe",
"Kwoma" : "kmo",
"Label" : "lbb",
"Lahu" : "lhu",
"Lake Miwok" : "lmw",
"Lama Bai" : "lay",
"Lamboya" : "lmy",
"Lamma" : "lev",
"Lampung Api" : "ljp",
"Larike-Wakasihu" : "alo",
"Lawangan" : "lbx",
"Leonese" : "roa-leo",
"Lepcha" : "lep",
"Li'o" : "ljl",
"Lillooet" : "lil",
"Limilngan" : "lmc",
"Lo-Toga" : "lht",
"Lombard" : "lmo",
"Loniu" : "los",
"Lorrain" : "roa-lor",
"Lou" : "loj",
"Louisiana Creole French" : "lou",
"Lovono" : "vnk",
"Lower Tanana" : "taa",
"Lushootseed" : "lut",
"Luvale" : "lue",
"Ma'anyan" : "mhy",
"Ma'di" : "mhi",
"Macaguán" : "mbn",
"Macuna" : "myy",
"Madak" : "mmx",
"Magori" : "zgr",
"Mahican" : "mjy",
"Makah" : "myh",
"Makalero" : "mjb",
"Malalí" : "sai-mal",
"Malecite-Passamaquoddy" : "pqm",
"Malila" : "mgq",
"Mamasa" : "mqj",
"Manam" : "mva",
"Mandan" : "mhq",
"Mandara" : "tbf",
"Mangarevan" : "mrv",
"Manipuri" : "mni",
"Maranungku" : "zmr",
"Maratino" : "sai-mar",
"Margi" : "mrt",
"Masakará" : "sai-msk",
"Massachusett" : "wam",
"Matlatzinca" : "mat",
"Mato" : "met",
"Matsés" : "mcf",
"Matukar" : "mjk",
"Mauwake" : "mhl",
"Maxakalí" : "mbl",
"Maybrat" : "ayz",
"Mbula" : "mna",
"Mbyá Guaraní" : "gun",
"Medebur" : "mjm",
"Media Lengua" : "mue",
"Mehek" : "nux",
"Mehri" : "gdq",
"Mele-Fila" : "mxe",
"Menya" : "mcr",
"Meramera" : "mxm",
"Merei" : "lmb",
"Mesaka" : "iyo",
"Mfumte" : "nfu",
"Miami" : "mia",
"Mian" : "mpt",
"Midob" : "mei",
"Mina" : "hna",
"Minaveha" : "mvn",
"Mindiri" : "mpn",
"Minica Huitoto" : "hto",
"Minigir" : "vmg",
"Misantla Totonac" : "tlc",
"Miyako" : "mvi",
"Mmani" : "buy",
"Mo" : "wkd",
"Mochica" : "omc",
"Molima" : "mox",
"Mondé" : "mnd",
"Mongghul" : "xgn-mgl",
"Mopan Maya" : "mop",
"Mori Atas" : "mzq",
"Mota" : "mtt",
"Mountain Koiari" : "kpx",
"Mubami" : "tsx",
"Muduapa" : "wiv",
"Muinane" : "bmr",
"Muna" : "mnb",
"Mundari" : "unr",
"Munsee" : "umu",
"Murui Huitoto" : "huu",
"Mussau-Emira" : "emi",
"Muyuw" : "myw",
"Mwani" : "wmw",
"Mwotlap" : "mlv",
"Nabi" : "mty",
"Classical Nahuatl" : "nci",
"Mecayapan Classical" : "null",
"Mecayapan" : "null",
"Mecayapan Nahuatl" : "nhx",
"Northern Puebla Mecayapan" : "null",
"Northern Puebla" : "null",
"Northern Puebla Nahuatl" : "ncj",
"Nakanai" : "nak",
"Nali" : "nss",
"Nambikwara" : "nab",
"Nanticoke" : "nnt",
"Narragansett" : "xnt",
"Nauna" : "ncn",
"Navarro-Aragonese" : "roa-oan",
"Nawaru" : "nwr",
"Nawathinehena" : "nwa",
"Nde-Nsele-Nta" : "ndd",
"Nehan" : "nsn",
"Neverver" : "lgk",
"Nez Perce" : "nez",
"Ngadha" : "nxg",
"Ngiemboon" : "nnh",
"Nicaraguan Creole" : "bzk",
"Nigerian Pidgin" : "pcm",
"Nihali" : "nll",
"Nimoa" : "nmw",
"Nisenan" : "nsz",
"Niuean" : "niu",
"Niwer Mil" : "hrc",
"Nkem-Nkum" : "isi",
"Nnam" : "nbp",
"Nomatsiguenga" : "not",
"Nootka" : "nuk",
"North Marquesan" : "mrq",
"North Muyu" : "kti",
"Northern Bai" : "bfc",
"Northern Emberá" : "emp",
"Northern Paiute" : "pao",
"Northern Pomo" : "pej",
"Northern Sierra Miwok" : "nsq",
"Nottoway" : "ntw",
"Nubi" : "kcn",
"Nukak Makú" : "mbr",
"Nukuoro" : "nkr",
"Nungon" : "paa-nun",
"Nyankole" : "nyn",
"Nzadi" : "nzd",
"Nüpode Huitoto" : "hux",
"Obispeño" : "obi",
"Ocaina" : "oca",
"Old Catalan" : "roa-oca",
"Old Leonese" : "roa-ole",
"Old Nubian" : "onw",
"Old Portuguese" : "roa-opt",
"Old Tupi" : "tpw",
"Olo" : "ong",
"Oneida" : "one",
"Onobasulu" : "onn",
"Ontong Java" : "ojv",
"Orejón" : "ore",
"Osage" : "osa",
"Otank" : "uta",
"Otomaco" : "sai-oto",
"Paama" : "pma",
"Pahi" : "lgt",
"Paiwan" : "pwn",
"Palawan Batak" : "bya",
"Palenquero" : "pln",
"Palu'e" : "ple",
"Pamosu" : "hih",
"Panare" : "pbh",
"Panim" : "pnr",
"Papapana" : "ppn",
"Papora" : "ppu",
"Parakanã" : "pak",
"Pare" : "asa",
"Pareci" : "pab",
"Pará Arára" : "aap",
"Patpatar" : "gfk",
"Paumarí" : "pad",
"Pawnee" : "paw",
"Pele-Ata" : "ata",
"Pemon" : "aoc",
"Penchal" : "pek",
"Penobscot" : "aaq",
"Pero" : "pip",
"Piapoco" : "pio",
"Picard" : "pcd",
"Pichinglis" : "fpe",
"Piedmontese" : "pms",
"Pijin" : "pis",
"Pima Bajo" : "pia",
"Piratapuyo" : "pir",
"Piscataway" : "psy",
"Plains Miwok" : "pmw",
"Playero" : "gob",
"Poitevin-Saintongeais" : "roa-poi",
"Pokangá" : "pok",
"Potawatomi" : "pot",
"Principense" : "pre",
"Puinave" : "pui",
"Purepecha" : "pua",
"Puyuma" : "pyu",
"Páez" : "pbb",
"Quapaw" : "qua",
"Quileute" : "qui",
"Quiripi" : "qyp",
"Rabha" : "rah",
"Raga" : "lml",
"Rama" : "rma",
"Ramoaaina" : "rai",
"Rarotongan" : "rar",
"Rasawa" : "rac",
"Rendille" : "rel",
"Rennellese" : "mnv",
"Reshe" : "res",
"Resígaro" : "rgr",
"Rikbaktsa" : "rkb",
"Romagnol" : "rgn",
"Ronji" : "roe",
"Roro" : "rro",
"Rotokas" : "roo",
"Rukai" : "dru",
"Sabu" : "hvn",
"Salinan" : "sln",
"Pite Northern" : "null",
"Pite" : "null",
"Pite Sami" : "sje",
"Skolt Pite" : "null",
"Samo" : "smq",
"San Juan Atzingo Popoloca" : "poe",
"San Miguel El Grande Mixtec" : "mig",
"San Pedro Amuzgos Amuzgo" : "azg",
"San Pedro Quiatoni Zapotec" : "zpf",
"Sangir" : "sxn",
"Saniyo-Hiyewe" : "sny",
"Saramaccan" : "srm",
"Sasak" : "sas",
"Sauraseni Prakrit" : "psu",
"Sechura" : "sai-sec",
"Secoya" : "sey",
"Sepa (New Guinea)" : "spe",
"Sera" : "sry",
"Seta" : "stf",
"Seychellois Creole" : "crs",
"Shawnee" : "sjw",
"Shehri" : "shv",
"Shona" : "sn",
"Shoshone" : "shh",
"Siar-Lak" : "sjr",
"Sika" : "ski",
"Sikaiana" : "sky",
"Sikkimese" : "sip",
"Sinacantán" : "nai-sin",
"Sinaugoro" : "snc",
"Sio" : "xsi",
"Siona" : "snn",
"Sipakapense" : "qum",
"Siriano" : "sri",
"Siroi" : "ssd",
"Sissano" : "sso",
"Sobei" : "sob",
"Sochiapam Chinantec" : "cso",
"Sonaga" : "ysg",
"Soo" : "teu",
"Sori-Harengan" : "sbh",
"South Marquesan" : "mqm",
"Southeastern Puebla Nahuatl" : "npl",
"Southeastern Tepehuan" : "stp",
"Southern Bai" : "bfs",
"Southern Ohlone" : "css",
"Southern Yukaghir" : "yux",
"Old Spanish Spanish" : "null",
"Old Spanish" : "osp",
"Suabo" : "szp",
"Suau" : "swp",
"Sumerian" : "sux",
"Sunwar" : "suz",
"Saliba (Colombia)" : "slc",
"Sãotomense" : "cri",
"Tabo" : "knv",
"Takia" : "tbc",
"Takuu" : "nho",
"Talise" : "tlr",
"Tanimbili" : "tbe",
"Tanimuca-Retuarã" : "tnc",
"Taparita" : "sai-tpr",
"Taraon" : "mhu",
"Tariana" : "tae",
"Tarifit" : "rif",
"Tarok" : "yer",
"Taroko" : "trv",
"Tarpia" : "tpf",
"Tataltepec Chatino" : "cta",
"Tatuyo" : "tav",
"Taupota" : "tpa",
"Tausug" : "tsg",
"Tawala" : "tbo",
"Tawasa" : "nai-taw",
"Tayo" : "cks",
"Teanu" : "tkw",
"Tenharim" : "pah",
"Teribe" : "tfr",
"Tezoatlán Mixtec" : "mxb",
"Tiang" : "tbj",
"Timucua" : "tjm",
"Tipai" : "nai-tip",
"Tiri" : "cir",
"Tiruray" : "tiy",
"Titan" : "ttv",
"Tivi" : "tiv",
"Tlahuica" : "ocu",
"Tlingit" : "tli",
"To'abaita" : "mlu",
"Tocantins Asurini" : "asu",
"Tocharian A" : "xto",
"Tocharian B" : "txb",
"Tokelauan" : "tkl",
"Tolai" : "ksd",
"Tommo So" : "dto",
"Tonkawa" : "tqw",
"Torau" : "ttu",
"Toro" : "tdv",
"Torres Strait Creole" : "tcs",
"Totoro" : "ttk",
"Transylvanian Saxon" : "gmw-tsx",
"Trimuris" : "tip",
"Trinitario" : "trn",
"Trumai" : "tpy",
"Tsafiki" : "cof",
"Tsakonian" : "tsd",
"Tsimané" : "cas",
"Tsimshian" : "tsi",
"Tsonga" : "ts",
"Tucano" : "tuo",
"Tukang Besi North" : "khc",
"Tukang Besi South" : "bhq",
"Tuki" : "bag",
"Tulu-Bohuai" : "rak",
"Tumleo" : "tmq",
"Tundra Nenets" : "yrk",
"Tungag" : "lcm",
"Tunica" : "tun",
"Tunjung" : "tjg",
"Tuscarora" : "tus",
"Tuyuca" : "tue",
"Tz'utujil" : "tzj",
"Tzeltal" : "tzh",
"Tzotzil" : "tzo",
"Ubir" : "ubr",
"Udihe" : "ude",
"Ulau-Suain" : "svb",
"Unami" : "unm",
"Uneapa" : "bbn",
"Unserdeutsch" : "uln",
"Ura (Vanuatu)" : "uur",
"Urarina" : "ura",
"Urat" : "urt",
"Uru-Eu-Wau-Wau" : "urz",
"Urubú-Kaapor" : "urb",
"Uyajitaya" : "duk",
"Venda" : "ve",
"Wab" : "wab",
"Wagi" : "fad",
"Wakhi" : "wbl",
"Wala" : "lgl",
"Wandamen" : "wad",
"Wardaman" : "wrr",
"Warekena" : "gae",
"Waris" : "wrs",
"Warungu" : "wrg",
"Wayampi" : "oym",
"Wayuu" : "guc",
"Wedau" : "wed",
"West Coast Bajau" : "bdr",
"West Tarangan" : "txn",
"Western Bukidnon Manobo" : "mbb",
"Wichita" : "wic",
"Wiwa" : "mbp",
"Wogeo" : "woc",
"Woleaian" : "woe",
"Wolio" : "wlo",
"Worora" : "wro",
"Woun Meu" : "noa",
"Wuvulu-Aua" : "wuv",
"Xingú Asuriní" : "asn",
"Yaa" : "iyx",
"Yagaria" : "ygr",
"Yakkha" : "ybh",
"Yanesha'" : "ame",
"Yanomamö" : "guu",
"Yaqui" : "yaq",
"Yareba" : "yrb",
"Yareni Zapotec" : "zae",
"Yawuru" : "ywr",
"Yelogu" : "ylg",
"Yeyi" : "yey",
"Yidiny" : "yii",
"Yimas" : "yee",
"Yola" : "yol",
"Yorta Yorta" : "xyy",
"Yucuna" : "ycn",
"Yukpa" : "yup",
"Yurumanguí" : "sai-yur",
"Yurutí" : "yui",
"Zaghawa" : "zag",
"Zande" : "zne",
"Zangskari" : "zau",
"Zoogocho Zapotec" : "zpq",
	"Abkhaz" : "ab",
	"Achuar" : "acu",
	"Aja" : "aja",
	"Aleut" : "ale",
	"Western Apache Apache" : "null",
	"Western Apache" : "apw",
	"Hijazi Arabic Egyptian Arabic" : "null",
	"Hijazi Arabic" : "acw",
	"Moroccan Arabic Hijazi Arabic" : "null",
	"Aragonese" : "an",
	"Aramaic" : "arc",
	"Hebrew Aramaic" : "null",
	"Syriac Hebrew" : "null",
	"Syriac" : "null",
	"Syriac Aramaic" : "null",
	"Atikamekw" : "atj",
	"Avar" : "av",
	"Kabyle Berber" : "null",
	"Tashelhit Kabyle" : "null",
	"Tashelhit" : "shi",
	"Bilua" : "blb",
	"Bislama" : "bi",
	"Catawba" : "chc",
	"Chechen" : "ce",
	"Chichewa" : "ny",
	"Hakka Dungan" : "null",
	"Chukchi" : "ckt",
	"Darkinjung" : "xda",
	"Emilian" : "egl",
	"Evenki" : "evn",
	"Ewe" : "ee",
	"Extremaduran" : "ext",
	"Haitian Creole" : "ht",
	"Hausa" : "ha",
	"Interlingue" : "ie",
	"Inuktitut" : "iu",
	"Old Irish Irish" : "null",
	"Old Irish" : "sga",
	"Isubu" : "szv",
	"Karelian" : "krl",
	"Komi-Permyak" : "koi",
	"Konkani" : "kok",
	"Lakota" : "lkt",
	"Lezgi" : "lez",
	"Ligurian" : "lij",
	"Luganda" : "lg",
	"Malagasy" : "mg",
	"Manchu" : "mnc",
	"Mapudungun" : "arn",
	"Mirandese" : "mwl",
	"Moksha" : "mdf",
	"Mòcheno" : "mhn",
	"Nahuatl" : "nah",
	"Neapolitan" : "nap",
	"Nogai" : "nog",
	"Novial" : "nov",
	"Old Church Slavonic" : "cu",
	"Glagolitic Old Church Slavonic" : "null",
	"Glagolitic" : "null",
	"Old Turkic" : "otk",
	"Ossetian" : "os",
	"Pali" : "pi",
	"Devanagari Pali" : "null",
	"Devanagari" : "null",
	"Papiamentu" : "pap",
	"Pipil" : "ppl",
	"Pitjantjatjara" : "pjt",
	"Polabian" : "pox",
	"Rapa Nui" : "rap",
	"Rohingya" : "rhg",
	"Samoan" : "sm",
	"Sanskrit" : "sa",
	"Seimat" : "ssg",
	"Silesian" : "szl",
	"Sindhi" : "sd",
	"Somali" : "so",
	"Southern Sierra Miwok" : "skd",
	"Sylheti" : "syl",
	"Tok Pisin" : "tpi",
	"Tongan" : "to",
	"Tuvaluan" : "tvl",
	"Veps" : "vep",
	"Votic" : "vot",
	"Vurës" : "msn",
	"Wallisian" : "wls",
	"Wauja" : "wau",
	"West Frisian" : "fy",
	"Wolof" : "wo",
	"Xhosa" : "xh",
	"Yoruba" : "yo",
	"Yucatec Maya" : "yua",
	"Zealandic" : "zea",
	"Aasax" : "aas",
	"Abu' Arapesh" : "aah",
	"Acehnese" : "ace",
	"Adyghe" : "ady",
	"Ahom" : "aho",
	"Akan" : "ak",
	"Akkadian" : "akk",
	"Alabama" : "akz",
	"Alutor" : "alr",
	"Alviri-Vidari" : "avd",
	"Ama" : "amm",
	"Imperial Aramaic Aramaic" : "null",
	"Imperial Aramaic" : "arc",
	"Classical Syriac Imperial Aramaic" : "null",
	"Classical Syriac" : "syc",
	"Mandaic Classical Syriac" : "null",
	"Mandaic" : "mid",
	"Samaritan Aramaic Mandaic" : "null",
	"Samaritan Aramaic" : "sam",
	"Arosi" : "aia",
	"Aymara" : "ay",
	"Bakhtiari" : "bqi",
	"Balinese" : "ban",
	"Baluchi" : "bal",
	"Bambara" : "bm",
	"Banjarese" : "bjn",
	"Baure" : "brg",
	"Betoi" : "sai-bet",
	"Blackfoot" : "bla",
	"Buginese" : "bug",
	"Bukiyip" : "ape",
	"Bulu (Cameroon)" : "bum",
	"Buryat" : "bua",
	"Central Atlas Tamazight" : "tzm",
	"Cheyenne" : "chy",
	"Teochew Min Nan" : "null",
	"Teochew" : "zhx-teo",
	"Wu Teochew" : "null",
	"Chiricahua" : "apm",
	"Choctaw" : "cho",
	"Chuave" : "cjv",
	"Cree" : "cr",
	"Crow" : "cro",
	"Dolgan" : "dlg",
	"East Central German" : "gmw-ecg",
	"Fijian" : "fj",
	"Fula" : "ff",
	"Futuna-Aniwa" : "fut",
	"Fuyug" : "fuy",
	"Alemannic German German" : "null",
	"Alemannic German" : "gsw",
	"Greenlandic" : "kl",
	"Guaraní" : "gn",
	"Hittite" : "hit",
	"Hopi" : "hop",
	"Indo-Portuguese" : "idb",
	"Ingush" : "inh",
	"Inupiak" : "ik",
	"Isnag" : "isd",
	"Istriot" : "ist",
	"Istro-Romanian" : "ruo",
	"Itawit" : "itv",
	"Jersey Dutch" : "gmw-jdt",
	"Jicarilla" : "apj",
	"Kaluli" : "bco",
	"Kamta" : "rkt",
	"Karipúna Creole French" : "kmv",
	"Kunigami" : "xug",
	"Ladin" : "lld",
	"Lavukaleve" : "lvk",
	"Laz" : "lzz",
	"Ledo Kaili" : "lew",
	"Livonian" : "liv",
	"Lote" : "uvl",
	"Lü" : "khb",
	"Mandar" : "mdr",
	"Maranao" : "mrw",
	"Watam" : "wax",
	"Megleno-Romanian" : "ruq",
	"Meänkieli" : "fit",
	"Mi'kmaq" : "mic",
	"Michif" : "crg",
	"Mingrelian" : "xmf",
	"Mohegan-Pequot" : "xpq",
	"Moroccan Amazigh" : "zgh",
	"Motu" : "meu",
	"Nama" : "naq",
	"Ngarrindjeri" : "nay",
	"North Slavey" : "scs",
	"Northern Ohlone" : "cst",
	"Nyunga" : "nys",
	"O'odham" : "ood",
	"Ojibwe" : "oj",
	"Oki-No-Erabu" : "okn",
	"Okinawan" : "ryu",
	"Old French" : "fro",
	"Old Occitan" : "pro",
	"Old Prussian" : "prg",
	"Ongota" : "bxe",
	"Ottoman Turkish" : "ota",
	"Pennsylvania German" : "pdc",
	"Pileni" : "piv",
	"Powhatan" : "pim",
	"Saanich" : "str",
	"Inari Sami" : "smn",
	"Northern Inari" : "null",
	"Northern" : "null",
	"Skolt Northern" : "null",
	"Skolt" : "null",
	"Southern Skolt" : "null",
	"Southern" : "null",
	"Savosavo" : "svs",
	"Slovincian" : "zlw-slv",
	"Sranan Tongo" : "srn",
	"Tahitian" : "ty",
	"Tai Nüa" : "tdd",
	"Talysh" : "tly",
	"Tetum" : "tet",
	"Tswana" : "tn",
	"Tupinambá" : "tpn",
	"Võro" : "vro",
	"Warlpiri" : "wbp",
	"Yagara" : "yxg",
	"Yoron" : "yox",
	"Zay" : "zwa",
	"ǃXóõ" : "nmn",
	"Central Sierra Miwok" : "csm",
	"Bavarian" : "bar",
	"Franco-Provençal" : "frp",
	"Gamilaraay" : "kld",
	"Kabyle" : "kab",
	"Kannada" : "kn",
	"Low German" : "nds",
	"German Low German Low German" : "null",
	"German Low German" : "nds-de",
	"Mapun" : "sjm",
	"Mari" : "chm",
	"Eastern Mari Mari" : "null",
	"Eastern Mari" : "chm",
	"Western Mari Eastern Mari" : "null",
	"Western Mari" : "mrj",
	"Norman" : "nrf",
	"Old Norse" : "non",
	"Samogitian" : "sgs",
	"Scots" : "sco",
	"Skolt Sami" : "sms",
	"Sundanese" : "su",
	"Westrobothnian" : "gmq-bot",
	"Kamkata-viri" : "bsh",
	"Prasuni" : "prn",
	"Tregami" : "trm",
	"Waigali" : "wbk",
	"Ainu" : "ain",
	"American Sign Language" : "ase",
	"Berawan" : "lod",
	"Tashelhit Berber" : "shi",
	"Central Melanau" : "mel",
	"Dungan Chinese" : "null",
	"Embaloh" : "emb",
	"Mandarin Cantonese" : "null",
	"Volapük" : "vo",
	"Afrikaans" : "af",
	"Arabic" : "ar",
	"Armenian" : "hy",
	"Asturian" : "ast",
	"Belarusian" : "be",
	"Bulgarian" : "bg",
	"Catalan" : "ca",
	"Chinese" : "zh",
	"Cantonese Chinese" : "null",
	"Cantonese" : "yue",
	"Gan Cantonese" : "null",
	"Gan" : "gan",
	"Hakka Gan" : "null",
	"Hakka" : "hak",
	"Mandarin Hakka" : "null",
	"Mandarin" : "cmn",
	"Min Dong Mandarin" : "null",
	"Min Dong" : "cdo",
	"Min Nan Min Dong" : "null",
	"Min Nan" : "nan",
	"Wu Min Nan" : "null",
	"Wu" : "wuu",
	"Czech" : "cs",
	"Danish" : "da",
	"Dutch" : "nl",
	"Esperanto" : "eo",
	"Finnish" : "fi",
	"French" : "fr",
	"Galician" : "gl",
	"Georgian" : "ka",
	"German" : "de",
	"Greek" : "el",
	"Ancient Greek" : "grc",
	"Hungarian" : "hu",
	"Ido" : "io",
	"Indonesian" : "id",
	"Irish" : "ga",
	"Italian" : "it",
	"Japanese" : "ja",
	"Javanese" : "jv",
	"Kashmiri" : "ks",
	"Kazakh" : "kk",
	"Korean" : "ko",
	"Ladino" : "lad",
	"Latgalian" : "ltg",
	"Latin" : "la",
	"Latvian" : "lv",
	"Lithuanian" : "lt",
	"Macedonian" : "mk",
	"Malay" : "ms",
	"Malayalam" : "ml",
	"Maori" : "mi",
	"Norwegian" : "no",
	"Bokmål Norwegian" : "null",
	"Bokmål" : "nb",
	"Nynorsk Bokmål" : "null",
	"Nynorsk" : "nn",
	"Occitan" : "oc",
	"Polish" : "pl",
	"Portuguese" : "pt",
	"Romanian" : "ro",
	"Russian" : "ru",
	"Serbo-Croatian" : "sh",
	"Slovak" : "sk",
	"Slovene" : "sl",
	"Spanish" : "es",
	"Swedish" : "sv",
	"Tagalog" : "tl",
	"Telugu" : "te",
	"Thai" : "th",
	"Turkish" : "tr",
	"Ukrainian" : "uk",
	"Vietnamese" : "vi",
	"Welsh" : "cy",
	"Albanian" : "sq",
	"Amharic" : "am",
	"Egyptian Arabic Arabic" : "null",
	"Egyptian Arabic" : "arz",
	"Gulf Arabic Egyptian Arabic" : "null",
	"Gulf Arabic" : "afb",
	"Iraqi Arabic Gulf Arabic" : "null",
	"Iraqi Arabic" : "acm",
	"Lebanese Arabic Iraqi Arabic" : "null",
	"Lebanese Arabic" : "null",
	"Lebanese Arabic Arabic" : "null",
	"Moroccan Arabic Iraqi Arabic" : "null",
	"Moroccan Arabic" : "ary",
	"Yemeni Arabic (San'ani) Moroccan Arabic" : "null",
	"Yemeni Arabic (San'ani)" : "null",
	"Yemeni Arabic (San'ani) Arabic" : "null",
	"Aromanian" : "rup",
	"Assamese" : "as",
	"Azerbaijani" : "az",
	"Baba Malay" : "mbf",
	"Bashkir" : "ba",
	"Basque" : "eu",
	"Bengali" : "bn",
	"Breton" : "br",
	"Brunei Malay" : "kxd",
	"Burmese" : "my",
	"Central Dusun" : "dtp",
	"Chagatai" : "chg",
	"Chamicuro" : "ccc",
	"Cherokee" : "chr",
	"Dungan Cantonese" : "null",
	"Dungan" : "dng",
	"Mandarin Dungan" : "null",
	"Min Nan Mandarin" : "null",
	"Chuvash" : "cv",
	"Comox" : "coo",
	"Coptic" : "cop",
	"Bohairic Coptic" : "null",
	"Bohairic" : "cop",
	"Sahidic Bohairic" : "null",
	"Sahidic" : "cop",
	"Cornish" : "kw",
	"Crimean Tatar" : "crh",
	"Dalmatian" : "dlm",
	"Dhivehi" : "dv",
	"Dongxiang" : "sce",
	"Drung" : "duu",
	"Egyptian" : "egy",
	"Erzya" : "myv",
	"Estonian" : "et",
	"Faroese" : "fo",
	"Friulian" : "fur",
	"Gagauz" : "gag",
	"Gothic" : "got",
	"Gujarati" : "gu",
	"Hawaiian" : "haw",
	"Hebrew" : "he",
	"Hindi" : "hi",
	"Hunsrik" : "hrx",
	"Iban" : "iba",
	"Icelandic" : "is",
	"Interlingua" : "ia",
	"Iu Mien" : "ium",
	"Kaingang" : "kgp",
	"Kalmyk" : "xal",
	"Kamba" : "kam",
	"Kaqchikel" : "cak",
	"Karachay-Balkar" : "krc",
	"Karakalpak" : "kaa",
	"Kashubian" : "csb",
	"Khakas" : "kjh",
	"Khmer" : "km",
	"Kikuyu" : "ki",
	"Kumyk" : "kum",
	"Kurdish" : "ku",
	"Kurmanji Kurdish" : "null",
	"Kurmanji" : "kmr",
	"Sorani Kurmanji" : "null",
	"Sorani" : "ckb",
	"Kyrgyz" : "ky",
	"Lao" : "lo",
	"Limburgish" : "li",
	"Lingala" : "ln",
	"Luhya" : "luy",
	"Luo" : "luo",
	"Luxembourgish" : "lb",
	"Maltese" : "mt",
	"Mandinka" : "mnk",
	"Manx" : "gv",
	"Marathi" : "mr",
	"Maricopa" : "mrc",
	"Mohawk" : "moh",
	"Mongolian" : "mn",
	"Navajo" : "nv",
	"Nepali" : "ne",
	"Ngazidja Comorian" : "zdj",
	"North Frisian" : "frr",
	"Northern Sami" : "se",
	"Northern Thai" : "nod",
	"Old East Slavic" : "orv",
	"Old English" : "ang",
	"Oriya" : "or",
	"Palauan" : "pau",
	"Pashto" : "ps",
	"Persian" : "fa",
	"Punjabi" : "pa",
	"Quechua" : "qu",
	"Romani" : "rom",
	"Romansch" : "rm",
	"Rusyn" : "rue",
	"Sardinian" : "sc",
	"Scottish Gaelic" : "gd",
	"Shan" : "shn",
	"Shor" : "cjs",
	"Sichuan Yi" : "ii",
	"Sicilian" : "scn",
	"Sinhalese" : "si",
	"Lower Sorbian" : "dsb",
	"Upper Sorbian Lower Sorbian" : "null",
	"Upper Sorbian" : "hsb",
	"Sotho" : "st",
	"Southern Altai" : "alt",
	"Southern Sami" : "sma",
	"Swahili" : "sw",
	"Tajik" : "tg",
	"Tamil" : "ta",
	"Taos" : "twf",
	"Tatar" : "tt",
	"Tibetan" : "bo",
	"Tigrinya" : "ti",
	"Turkmen" : "tk",
	"Tuvan" : "tyv",
	"Udmurt" : "udm",
	"Umbundu" : "umb",
	"Urdu" : "ur",
	"Uyghur" : "ug",
	"Uzbek" : "uz",
	"Venetian" : "vec",
	"Vilamovian" : "wym",
	"Walloon" : "wa",
	"Waray-Waray" : "war",
	"White Hmong" : "mww",
	"Winnebago" : "win",
	"Yagnobi" : "yai",
	"Yakut" : "sah",
	"Yiddish" : "yi",
	"Yup'ik" : "esu",
	"Zazaki" : "zza",
	"Zhuang" : "za",
	"Zulu" : "zu",
	"Mandarin Chinese" : "cmn",
	"Sorani Kurdish" : "null",
	// nulls are explicit negative entries to avtoid having xte round-trip
	// to servers with known bad names. why does it even try these? when encountering
	// a translation sub-item, xte prepends the sub-item name before the item name.
	// this works well for "Egyptian" (otherwise egy) under "Arabic" (otherwise ar)
	// = "Egyptian Arabic" (arz), but it also results in "Lower Sorbian Sorbian".
	"Lower Sorbian Sorbian": null,
	"Upper Sorbian Sorbian": null
};

/*
=== Scripts ===
 */
var scname2scLookup = {
	"Roman"    : "Latn",
	"Latin"    : "Latn",
	"Cyrillic" : "Cyrl",
	"Mandarin" :  null,
	"Cantonese":  null
};

function code2name(code) {
	if (code2nameLookup != 'null') {
		if (code in code2nameLookup) {
		//mw.notify('code2name: ' + code);
		return code2nameLookup;
		}
	} else {
		//mw.notify('code2name: ' + code);
		var api = new mw.Api();
		var result = null;
		api.get({
			'action': 'expandtemplates',
			'text': '{{#invoke:languages/templates|getByCode|' + code + '|getCanonicalName}}'
		}, {
			async: false,
			success: function (obj) {
				result = obj.expandtemplates;
				if (/class="error"/.test(result))
					result = null;
				code2nameLookup = result;
			}
		});
		return result;
	}
}

function name2code(name) {
	if (name in name2codeLookup) {
		//console.info('"' +name + '" : "' + name2codeLookup + '",');
		return name2codeLookup;
	} else {
		var api = new mw.Api();
		var result = null;
		api.get({
			'action': 'expandtemplates',
			'text': '{{#invoke:languages/templates|getByName|' + name + '}}'
		}, {
			async: false,
			success: function (obj) {
				result = obj.expandtemplates;
				if (result === '')
					result = null;
				if (/^\[\[/.test(result))
					result = null;
				if (/class="error"/.test(result))
					result = null;
				name2codeLookup = result;
				console.info('"' +name + '" : "' + name2codeLookup + '",');
			}
		});
		return result;
	}
}

function code2sc(code) {
	if (code in code2scLookup)
		return code2scLookup;
	else {
		//console.warn('script for "' + code + '" is missing from the lookup table; ignoring');
		var result = null;
		return result;
		/*console.warn('script for "' + code + '" is missing from the lookup table; falling back to API query');
		var api = new mw.Api();
		var result = null;
		api.get({
			'action': 'expandtemplates',
			'text': '{{#invoke:languages/templates|getByCode|' + code + '|getScripts|1}}'
		}, {
			async: false,
			success: function (obj) {
				result = obj.expandtemplates;
				if (/class="error"/.test(result))
					result = null;
				code2scLookup = result = obj.expandtemplates;
			}
		});
		return result;*/
	}
}

function scname2sc(scname) {
	if (scname in scname2scLookup)
		return scname2scLookup;
	else {
		//console.warn('script code for "' + scname + '" is missing from the lookup table; ignoring');
		var result = null;
		return result;
		/*console.warn('script code for "' + scname + '" is missing from the lookup table; falling back to API query');
		var api = new mw.Api();
		var result = null;
		api.get({
			'action': 'expandtemplates',
			'text': '{{scriptrev|' + scname + '}}'
		}, {
			async: false,
			success: function (obj) {
				result = obj.expandtemplates;
				if (result === '')
					result = null;
				scname2scLookup = result;
			}
		});
		return result;*/
	}
}

function el(tag, child, attr, events) {
	var node = document.createElement(tag);

	if (child) for (var i = 0; i < child.length; ++i) {
		var ch = child;
		if (typeof ch === 'string')
			ch = document.createTextNode(ch);
		else if ((ch === null) || (ch === void(null)))
			continue;
		node.appendChild(ch);
	}

	if (attr) for (var key in attr) {
		node.setAttribute(key, attr);
	}

	if (events) for (var key in events) {
		node.addEventListener(key, events, false);
	}

	return node;
}

function ih(name, val) {
	var it = el('input', null, { 'type': 'hidden', 'name': name });
	if (val)
		it.value = val;
	return it;
}

function count(subs, s) {
	var i = 0, j = -subs.length;
	while ((j = s.indexOf(subs, j + subs.length)) !== -1) ++i;
	return i;
}

// 500 lines somewhat messy workhorse
function fix(wikicode, susp, errors) {
	var i, dirty = false;
	var name = null, code = null, before, subbef;
	function addError(message) {
		console.error(message);
		errors = {
			'line': i + 1,
			'code': code,
			'mesg': message
		};
	}
	var m, lines = wikicode.split('\n');
	var mode = 0;
	if (!(susp instanceof Array))
		susp = ;
	if (!(errors instanceof Array))
		errors = ;
	for (i = 0; i < lines.length; ++i) {
		var ttbcline = false, issub = false, entrysc = '';
		if (m = /^\s*\{\{(checktrans|ttbc)-top(\||}})/.exec(lines)) {
			name = code = null;
			mode = 2;
			continue;
		} else if (m = /^\s*\{\{(checktrans|trans|ttbc)-bottom(\||}})\s*/.exec(lines)) {
			name = code = null;
			if (m !== lines)
				addError('Stray markup after translation table end');
			mode = 0;
			continue;
		} else if (m = /^\s*\{\{trans-top(?:-also)?(\||}})\s*/.exec(lines)) {
			name = code = null;
			mode = 1;
			continue;
		}
		if (mode === 0)
			continue;
		// what does this do?
		if (m = /^\*(?!)\s*(?:\+?)(?:\]\])?\s*:\s*/.exec(lines)) {
			before = subbef = m;
			name = m;
			code = name2code(m);
			if (code === false) { // language group, "Sorbian", which serves as a group for "Lower Sorbian" and "Upper Sorbian"
				if (lines !== m) {
					addError('Language group "' + m + '" has direct items; these should be placed under a more specific header.');
					susp.push('"' + m + '"');
					lines = '* {{ttbc|' + m + '}} {{attention|und|Wiktionary considers this a language group; please specify the language more precisely}}: ' + lines.substr(m.length);
					dirty = true;
					continue;
				} else continue;
			}
			if (!code) {
				if ((name === 'Serbian') || (name === 'Croatian') || (name === 'Bosnian')) {
					ttbcline = true;
					addError('Warning: converting "' + name + '" into "Serbo-Croatian" .');
					subbef = 'Serbo-Croatian {{attention|sh|was "' + name + '"; verify correctness, check for duplicates, mark script, sort and merge if appropriate}}:';
					name = 'Serbo-Croatian';
					code = 'sh';
					susp.push("sh");
				} /*else if (name === 'Ancient') {
					if (xtepro) {
						// what is name used for? 
						addError('Warning: converting "' + name + '" into "Ancient Greek".');
						name = 'Ancient Greek';
						subbef = 'Ancient Greek:';
					} else {
					ttbcline = true;
					addError('Warning: converting "' + name + '" into "Ancient Greek".');
					subbef = 'Ancient Greek {{attention|grc|was "' + name + '"; verify correctness, check for duplicates, mark script, sort and merge if appropriate}}:';
					name = 'Ancient Greek';
					//code = 'sh';
					susp.push("grc");
					}
				}*/ else {
					code = name = null;
					addError('"' + m + '" does not refer to a known language.');
					susp.push('"' + m + '"');
					//lines = '* {{ttbc|' + m + '}} {{attention|und|name not recognised by xte: update ] appropriately or report to ]}}: ' + lines.substr(m.length);
					dirty = true;
					continue;
				}
			}
			// add t-check if ttbc or attention on the line
			} else if (m = /^\*\s*(\{\{ttbc\s*\|(*?)}})(\s*\{\{\s*attention\s*\|.*?}})?\s*:\s*/.exec(lines)) {
			before = subbef = m;
			code = m;
			name = code2name(m);
			ttbcline = true;
			if (!name) {
				if (code = name2code(m)) {
					name = m;
					before = subbef = '{{ttbc|' + code + '}}';
				} else {
					code = name = null;
					addError('"' + m + '" under ttbc does not refer to a known language.');
					susp.push('"' + m + '"');
					continue;
				}
			}
		} else if (m = /^\*\s*(?:\+?)(?:\]\])?\s*:\s*/.exec(lines)) {
			subbef = m;
			var s;
			if (s = scname2sc(subbef)) {
				if (code === null)
					continue;
				entrysc = s;
			} 
			// this should not be neccesary now that module:languages contains information about ancestors
			/*else if (s = name2code(subbef + ' ' + name)) { // prepend sub-item name before group name: "Ancient" + "Greek", "Lower" + "Sorbian", etc.
				code = s;
				name = subbef;
			}*/ else if (s = name2code(subbef)) {
				code = s;
				name = subbef;
			} else if (s = name2code(subbef + ' ' + before)) {
				code = s;
				// Correct subbef like "Ancient" -> "Ancient Greek"
				name = subbef + ' ' + before;
				addError('Warning: converting' + subbef + ' into ' + name + '.');
				lines = '*: ' + name + ': ' + lines.substr(m.length);
				console.info('Line: ' + lines);
				//dirty = true;
				continue;
			} else {
				if (subbef === 'Teochew') {
					ttbcline = true;
					code = 'nan'; 
					addError('Warning: treating "Teochew" header as if it were Min Nan . If you want to merge it with Min Nan, use {{qualifier}}.');
					susp.push('nan (Teochew)');
				} else {
					addError('Failed to recognize "' + subbef + '" sub-item for "' + before + '"');
					/*lines = '*: {{ttbc|' + subbef + '}}<!-- name not recognised by xte: update ] or ] appropriately or report to ] -->: ' + lines.substr(m.length);
					dirty = true;*/
					continue;
				}
			}
			issub = true;
		} else if (m = /^\s*\{\{(checktrans|trans|ttbc)-mid(\||}})\s*/.exec(lines)) {
			name = code = null;
			if (m !== lines)
				addError('Stray markup after translation table midbreak');
			continue;
		} else if (m = /^\*\s*\{\{trreq\|(.*?)}}\s*?(?=\s|$)/.exec(lines)) {
			name = code = null;
			if (!(name = code2name(m))) {
				if (!(code = name2code(m))) {
					addError('"' + m + '" under {{trreq}} is not recognised');					
				} else {
					if (m !== lines)
						addError('Stray markup after {{trreq}}');
					lines = '* {{trreq|' + code + '}}' + lines.substr(m.length);
					continue;
				}
			}
			if (m !== lines)
				addError('Stray markup after {{trreq}}');
			continue;
		} else {
			addError('Line not recognised');
			continue;
		}
		var parsed = lines.substr(m.length);
		var token = '';
		var t9ns = ;
		var or = 0, oc = 0, os = 0, ot = 0;
		while (parsed !== '') {
			if (!(m = /\s*\s*/.exec(parsed))) {
				t9ns = token + parsed;
				break;
			}
			var pre = parsed.substr(0, parsed.indexOf(m));
			or += count('(', pre) - count(')', pre);
			oc += count('{', pre) - count('}', pre);
			os += count('', pre);
			ot += count('<', pre) - count('>', pre);
			if ((or === 0) && (oc === 0) && (os === 0) && (ot === 0)) {
				t9ns = token + pre;
				token = '';
			} else {
				token += pre + m;
			}
			parsed = parsed.substr(parsed.indexOf(m) + m.length);
		}
		var allok = true;
		// This loop adds t-check to lines being processed if they do not pass 
		// the validation.
		for (var j = 0; j < t9ns.length; ++j) {
			// skip if one of these
			if (/\{\{\s*(tcheck|t-needed)\|/.test(t9ns))
				continue;
				
			// mode 2 means that it is under a checktrans-top header
			var suspc = (mode === 2) || ttbcline;

			// validate (rudimentary!)
			// add qual and q to validation
			if (!t9ns.replace(/<!--(.*?)-->/g, '').replace(/\s*\{\{t\+?\|(\|tr=\{\{IPAchar\|+}}|)+}}\s*/, '').replace(/\s*\{\{(qualifier|qual|q|i)\|+}}\s*/g, '')) {
				if (suspc) {
					t9ns = t9ns.replace(/\{\{t(\+?)\|/, function (m, t) {
						// this adds check to t-template
						console.info('adding check to {{t}}');
						return '{{t' + (t ? '+' : '-') + 'check|';
					});
				}
				continue;
			}
			if (/\{\{t/.test(t9ns)) {
				addError('Translation item "' + t9ns + '" failed to validate despite containing {{t}}. Will reconstruct.');
				// This enables adding check to {{t}} when deconstructing
				if (xtepro)
					suspc = false;
				else
					suspc = true;
			}

			var inp = t9ns;
			// validation failed. deconstruct {{t}}s
			inp = inp.replace(/\{\{t\+?(\|+\|+)((\|tr=\{\{IPAchar\|+}}|\|+)*)}}(?!\))/g, function (m, ct, rest) {
				var newrest = '', g = '', tr = '';
				while (rest) {
					var r = rest.replace(/^(\|+)+(?=\||$)/, function (m) {
						g += m;
						return '';	
					}).replace(/^\|alt=(+)/, function (m, a) {
						if (newrest)
							return m;
						newrest = '|' + a;
						return '';
					}).replace(/^\|sc=(+)/, '');
					if (r === rest)
						return m; // failed to deconstruct {{t}}
					rest = r;
				}
				return '{{l' + ct + newrest + '}}' + (tr ? ' (' + tr + ')' : '') + (g ? ' {{g' + g + '}}' : '');
			});
			
			if (/\{\{t/.test(inp)) {
				addError('Deconstruction failed for "' + t9ns + '". Please fix it manually.');
				allok = false;
				continue;
			}

			console.info('transforming ', t9ns);
			var qual = '', word = '', gend = '', tr = '', sc = entrysc, alt = '', sense= '';
			inp = inp.replace(/\{\{l(+)\|(+(?:\|+)?)}}/g, function (m, lc, cont) {
				if (lc !== code) {
					// I have never actually encountered this, but just to be safe...
					addError('Warning: {{l}} template used with non-matching language code ' + lc);
					suspc = true;
					return m;
				}
				return ']';
			});
			// process the deconstructed line
			// todo: support parens also; refactor
			// if qual OR gloss OR sense times 4
			if (m = /\s*\{\{(?:qualifier|qual|q|sense|gloss|i)\|(.+?)}}\s*/.exec(inp)) {
				console.info('qualifier, gloss, sense : ', m);
				qual = '; ' + m;
				inp = inp.replace(m, '');
				if (m = /\s*\{\{(?:qualifier|qual|q|sense|gloss|i)\|(.+?)}}\s*/.exec(inp)) {
					console.info('qualifier, gloss, sense : ', m);
					qual += '|' + m;
					inp = inp.replace(m, '');
					if (m = /\s*\{\{(?:qualifier|qual|q|sense|gloss|i)\|(.+?)}}\s*/.exec(inp)) {
						console.info('qualifier, gloss, sense : ', m);
						qual += '|' + m;
						inp = inp.replace(m, '');
						if (m = /\s*\{\{(?:qualifier|qual|q|sense|gloss|i)\|(.+?)}}\s*/.exec(inp)) {
							console.info('qualifier, gloss, sense : ', m);
							qual += '|' + m;
							inp = inp.replace(m, '');
							console.info('inp after 4 matches: ', inp);
						}
					}
				}
			} else {
				// handle unknown parens
				inp = inp.replace(/\s*(?:\(''|''\()(+?)(?:''\)|\)'')/g, function(m, inside) {
					console.info('probably qualifier: ', arguments);
					qual += '; ' + inside;
					return '';
				});
			}
			var getWord = function (m) {
				var n;
				console.info('words: ', m);
				// remove garbage 
				m = m.replace(/&nbsp/, '');
				console.info('words after garbage removal: ', m);
				if (!/^\s*(\\|]*?]]|\{\}'<>]+)$/.test(m)) {
					var n = /^(*)\]*?)(?:#(]*?))?(?:\|(]*?))?]](*)$/.exec(m);
					if (n) {
						if (!(((n === n) || !n) && (n === name))) {
							if (xtepro) {
								// do not warn if one of "-?!"
								if (!//.test(m)) {
									// do not warn if one of prolangs
									if (prolangs.indexOf( code ) == -1) {
										addError('Warning: single piped or non-clean link in an item "' + m + '". Assuming an inflected form or vocalised spelling. See ].');
										suspc = 'was "' + m + '" - assumed inflected form or vocalised spelling; please verify if linking is acceptable. see ]';
										susp.push(code);
									}
								}
							} else {
								addError('Warning: single piped or non-clean link in an item "' + m + '". Assuming an inflected form or vocalised spelling. See ].');
								suspc = 'was "' + m + '" - assumed inflected form or vocalised spelling; please verify if linking is acceptable. see ]';
								susp.push(code);
							}
							alt = n + (n || n || wgPageName) + n;
							word = n || wgPageName;
							return '';
						}
					} else {
						// only add warnings if not one of the prolangs
						if (prolangs.indexOf( code ) == -1) {
							addError('Warning: multiple words in an item: "' + m + '". Assuming it is a ]. If it is not, remove the links to individual words.');
							suspc = 'was "' + m + '" - assumed sum-of-parts; if an idiom, remove the wikilinks to the individual words. see ]';
							susp.push(code);
						}
						word = m;
						if (!/\]/.test(word)) {
							word = word.replace(/(\(\) \t,]+)/g, function (wm) {
								return ']';
							});
						}
						return '';
					}
				}
				word = m.replace(/\]+?\|)?(.+?)]]/g, '$1').replace(/\s+/g, ' ');
				return '';
			}; // end getWord
			if (m = /^\{\{((?:-)?)\s*\|\s*(.+?)\s*}}/.exec(inp)) {
				sc = m;
				getWord(m);
				inp = inp.replace(m, '');
			} else if (/''+(.+?)''+/.test(inp)) {
				// whole line is a qualifier like "* Finnish: ''adessive of the means''"
				inp = inp.replace(/''+(.+?)''+/, function (m, t) {
					console.info('whole line is a qualifier in single quotes: ', arguments, '; script: ', sc);
					if (qual === '')
						qual = '; ' + t;
					else
						qual += '|' + t;
					word = ''; // no words on this line
					return '';
					//return m; // ???
				});
			} else
				inp = inp.replace(/^((\s*)(?!''|<!--)(?:\]+?\|)?(.+?)]]|(+)))+/, getWord);
			if (/^\s*$/.test(word)) {
				console.info('word: ' + word);
				addError('Failed to process item: "' + t9ns + '"');
				allok = false;
				continue;
			}
			if (!sc)
				sc = code2sc(code);
			if (sc !== 'Latn') {
				inp = inp.replace(/\{\{(IPAchar)\|\(?(.+?)\)?}}/, function (m, w, t) {
					console.info('most probably transcription: ', arguments, '; script: ', sc);
					tr = '{{' + w + '|' + t + '}}';
					return '';
				});
			}	
			inp = inp.replace(/\((.+?)\)/, function (m, t) {
				console.info('text in parens: ', arguments, '; script: ', sc);
				if (//.test(t)) // SOP Russian translation
					return m;
				if (!tr && (sc !== 'Latn') && (sc !== null)) { // probably a transcription
					console.info('probably a transcription:', t, 'script is: ', sc);
					tr = t;
					return '';
				} else if (/^]+$/.test(t)) { // probably qualifier
					console.info('probably a qualifier:', t);
					// discard "" like in {{t|mic|nseduwaqan}} ("my ear")
					t = t.replace(/"/g, '');
					t = t.replace(/'/g, '');
					if (qual === '')
						qual = '; ' + t;
					else
						qual += '|' + t;
					return '';
				}  else if (/\\]/.test(t)) { // probably qualifier
					// detect if qualifier, e.g. (])
					t = t.replace(/\[\[/, '')
					t = t.replace(/\]\]/, '')
					console.info('probably a qualifier in ]:', t);
					if (qual === '')
						qual = '; ' + t;
					else
						qual += '|' + t;
					return '';
				}
				return m; // ???
			});
			
			inp = inp.replace(/"(.+?)"/, function (m, t) {
				console.info('text in duoble quotes: ', arguments, '; script: ', sc);
				if (//.test(t)) // SOP Russian translation
					return m;
				if (!tr && (sc !== 'Latn') && (sc !== null)) { // probably a transcription
					console.info('probably a transcription:', t, 'script is: ', sc);
					tr = t;
					return '';
				} else if (/^]+$/.test(t)) { // probably qualifier
					console.info('probably a qualifier:', t);
					if (qual === '')
						qual = '; ' + t;
					else
						qual += '|' + t;
					return '';
				}
				return m; // ???
			});
			inp = inp.replace(/''+(.+?)''+/, function (m, t) {
				console.info('text in single quotes: ', arguments, '; script: ', sc);
				if (//.test(t)) // SOP Russian translation
					return m;
				if (!tr && (sc !== 'Latn') && (sc !== null)) { // probably a transcription
					console.info('probably a transcription:', t, 'script is: ', sc);
					tr = t;
					return '';
				} else if (/^]+$/.test(t)) { // probably qualifier
					console.info('probably a qualifier:', t);
					if (qual === '')
						qual = '; ' + t;
					else
						qual += '|' + t;
					return '';
				}
				
				return m; // ???
			});
			
			inp = inp.replace(/\{\{g(\|((?:|pf|impf)(?:-|impf|pf)*)*)}}/g, function (m, g) {
				gend = g;
				console.info('gender: ', arguments);
				return '';
			});
			
			if (qual.indexOf('(') !== -1) {
				addError('Opening parenthesis inside qualifier for item "' + t9ns + '". Not touching.');
				allok = false;
				continue;
			}
			if (qual.indexOf('{') !== -1) {
				addError('Opening bracket parens inside qualifier for item "' + t9ns + '". Not touching.');
				allok = false;
				continue;
			}
			if (tr.indexOf('(') !== -1) {
				addError('Opening parenthesis inside transliteration for item "' + t9ns + '". Not touching.');
				allok = false;
				continue;
			}

			var debris = '';
			if (!/^\s*$/.test(inp)) {
				debris = ' ' + inp.trim();
				addError('Warning: some markup with unclear purpose detected: "' + inp + '". Putting after {{t}} invocation.');
				suspc = true;
				susp.push(code);
			}
			
			t9ns = '';
			t9ns += '{{t' + ((suspc || (mode === 2)) ? '-check' : '')  + '|' + code + '|' + word;
			t9ns += gend;
			if (tr !== '')
				t9ns += '|tr=' + tr;
			if (alt !== '')
				t9ns += '|alt=' + alt;
			if (sc && (sc !== 'Latn') && (sc !== 'None'))
				t9ns += '|sc=' + sc;
			t9ns += '}}' 
			// qualifier comes after {{t}}
			if (qual !== '')
			t9ns += ' {{q|' + qual.substr(2) + '}} '
			t9ns += debris;
			if (typeof suspc === 'string')
				t9ns += ' {{attention|' + code + '|2=' + suspc + '}}';
			console.info('transformed into ', t9ns);
		}
		if (allok && (subbef === ('{{ttbc|' + code + '}}')))
			subbef = name;
		var newl = (issub ? '*: ' + subbef : ('* ' + subbef)) + ':' + (t9ns.length ? ' ' + t9ns.join(', ') : '');
		if (lines !== newl) {
			lines = newl;
			dirty = true;
		}
	} // end for loop
	if (!dirty)
		return null;
	return lines.join('\n');
}

function fmtts(ts) {
	function pad(wut) {
		return wut < 10 ? '0' + wut : wut.toString();
	}
	var d = new Date(ts);
	return d.getUTCFullYear().toString() + pad(d.getUTCMonth() + 1) + pad(d.getUTCDate()) + pad(d.getUTCHours()) + pad(d.getUTCMinutes()) + pad(d.getUTCSeconds());
}

function fixer(secnum) {
	// Begin querying languages found on the page
	var wgPageName = mw.config.get('wgPageName');
	jQuery.ajax({
		'url': mw.config.get('wgServer') + mw.config.get('wgScript') + '?action=raw&templates=expand&ctype=text/javascript&maxage=172800&title=User:Kephir/gadgets/xte/langdata.js',
		'cache': true,
		'dataType': 'json',
		'success': function (data) {
			try {
				code2nameLookup = {};
				code2scLookup = {};
				for (var key in data) {
					code2nameLookup = data.names;
					code2scLookup = data.scripts;
				}
				for (var key in code2nameLookup) {
					name2codeLookup] = key;
				}
			} catch (e) {
				mw.notify('xte: error while processing language data. See console for details.');
				throw e;
			}
		},
		'error': function (xhr, message) {
			if (message !== 'abort')
				mw.notify('xte: failed to grab language data. See console for details.');
			console.error(arguments);
		}
	});
	
	return function () {
		if (!code2nameLookup) {
			mw.notify('xte: Please wait a moment until language data is downloaded.');
		}
		var formcont, formstart, formtoken, formedit, formwatch, formsumm;
		var form = el('form', [
			formcont = ih('wpTextbox1'),
			formstart = ih('wpStarttime'),
			formedit = ih('wpEdittime'),
			formtoken = ih('wpEdittoken'),
			formwatch = ih('wpWatchthis', '1'),
			ih('oldid', '0'),
			secnum !== null ? ih('wpSection', secnum.toString()) : '',
			formsumm = ih('wpSummary', 'Fixing translation table using (])'),
			ih('wpDiff', 'wpDiff')
		], {
			'action': mw.config.get('wgScript') + '?xtewarn&action=submit' + (secnum !== null ? '&section=' + secnum : '') + '&title=' + encodeURIComponent(wgPageName),
			'method': 'post',
			'enctype': 'multipart/form-data'
		});

		var api = new mw.Api();
		api.get({
			action: 'query',
			prop: 'info|revisions',
			rvprop: 'timestamp|content',
			rvsection: secnum !== null ? secnum : void(0),
			rvlimit: 1,
			rvdir: 'older',
			intoken: 'edit',
			inprop: 'watched',
			titles: wgPageName
		}, {
			'success': function (result) {
				var pid = Object.keys(result.query.pages);
				var pg = result.query.pages;
				var susp = , errs = ;
				var fixd = fix(pg.revisions, susp, errs);
				if (errs.length) {
					try {
						var cnam = 'kephir-xte-errors-' + wgPageName;
						var cval = JSON.stringify(errs);
						window.sessionStorage.setItem(cnam, cval);
						if (window.sessionStorage.getItem(cnam) !== cval) {
							throw new Error("sessionStorage failed to work");
						}
					} catch (e) {
						alert('Errors while processing:\n\n' + errs.map(function (item) {
							return 'Line ' + item.line + (item.code === null ? '' : ' ') + ': ' + item.mesg;
						}).join('\n'));
					}
				}
				if (fixd === null) {
					if (confirm('Nothing fixed automatically (' + errs.length + ' messages). Edit manually?')) {
						location.href = mw.config.get('wgScript') + '?xtewarn&action=edit&title=' + encodeURIComponent(wgPageName) + (secnum !== null ? '&section=' + secnum.toString() : '');
					}
					//mw.notify('Nothing fixed automatically (' + errs.length + ' messages).');
					return;
				}
				if (susp.length) {
					susp.sort();
					var last;
					formsumm.value += ' — please review: ' + susp.filter(function(it) {
						if (it !== last) {
							last = it;
							return true;
						}
						return false;
					}).join(', ');
				}
				formedit.value = fmtts(pg.revisions.timestamp);
				formstart.value = fmtts(pg.starttimestamp);
				formtoken.value = pg.edittoken;
				formcont.value = fixd;
				if (!(('watched' in pg) || (mw.user.options.get('watchdefault') == '1'))) {
					formwatch.parentNode.removeChild(formwatch);
				}
				document.body.appendChild(form);
				//form.submit();
				// so9q do not submit automatically
				if (confirm('Fixed automatically (' + errs.length + ' messages). Submit?')) {
						form.submit();
				}
			},
			'error': function () {
				console.error(arguments);
				alert('Error while requesting page source. See console for details.');
			}
		});
	};
}



if (((mw.config.get('wgAction') === 'submit') || (mw.config.get('wgAction') === 'edit'))) {
	var genErrorList = function (errlist) {
		function lineSelector(ln) {
			return function () {
				var start = 0;
				for (var i = 1; i < ln; ++i)
					start = textbox.value.indexOf('\n', start) + 1;
				var end = textbox.value.indexOf('\n', start);

				textbox.focus();
				if (textbox.createTextRange) { // MSIE	
					var range = textbox.createTextRange();
					range.collapse(true);
					range.moveStart('character', start);
					range.moveEnd('character', end);
					range.select();
				} else if (textbox.setSelectionRange) { // browsers
					textbox.setSelectionRange(start, end);
					var phantom = document.createElement('div');
					var style = window.getComputedStyle(textbox, '');
					phantom.style.padding = '0';
					phantom.style.lineHeight = style.lineHeight;
					phantom.style.fontFamily = style.fontFamily;
					phantom.style.fontSize = style.fontSize;
					phantom.style.fontStyle = style.fontStyle;
					phantom.style.fontVariant = style.fontVariant;
					phantom.style.letterSpacing = style.letterSpacing;
					phantom.style.border = style.border;
					phantom.style.outline = style.outline;
					try { phantom.style.whiteSpace = "-moz-pre-wrap" } catch(e) {}
					try { phantom.style.whiteSpace = "-o-pre-wrap" } catch(e) {}
					try { phantom.style.whiteSpace = "-pre-wrap" } catch(e) {}
					try { phantom.style.whiteSpace = "pre-wrap" } catch(e) {}
					phantom.textContent = textbox.value.substr(0, start);
					document.body.appendChild(phantom); // XXX: do I need this?
					textbox.scrollTop = phantom.scrollHeight - (textbox.clientHeight / 2);
					document.body.removeChild(phantom);
				}
				textbox.scrollIntoViewIfNeeded();
			};
		}
		var errul = el('ul');
		var listdom = el('div', [
			el('p', ),
			errul
		]);
		if (!errlist.length)
			return null;
		for (var i = 0; i < errlist.length; ++i) {
			var linelink = el('a', .line], { 'href': 'javascript:void(0);' });
			linelink.addEventListener('click', lineSelector(errlist.line));
			var m, errmsg = , mesg = errlist.mesg;
			while (m = /(.*?)(\\])/.exec(mesg)) {
				errmsg.push(m);
				errmsg.push(el('a', ], { 'href': mw.util.getUrl(m) }));
				mesg = mesg.substr(m.length);
			}
			errmsg.push(mesg);
			errul.appendChild(el('li', [
				linelink, (errlist.code ? ' .code + ']' : ''), ': '
			].concat(errmsg)));
		}
		return listdom;
	};
	var diff = document.getElementById('wikiDiff');
	var xtebox = document.createElement('div');
	var fishy = false;
	var textbox = document.getElementById('wpTextbox1');
	if (diff) {
		diff.parentNode.insertBefore(xtebox, diff);
		if (/xtewarn/.test(location.search)) {
			xtebox.appendChild(el('p', [
				el('strong', ), ": the translation fixing mechanism is less than perfect and may generate erroneous markup in some unusual cases. Thoroughly review and correct the diff before saving the page. When unsure what to do, keep the old version of a line and leave a message in the edit summary, or not save at all. You take all responsibility for any changes you save."
			], { 'class': 'warning' }), diff);
			try {
				var errlist = JSON.parse(window.sessionStorage.getItem('kephir-xte-errors-' + wgPageName));
				var eldom = genErrorList(errlist);
				if (eldom)
					xtebox.appendChild(eldom);
				window.sessionStorage.removeItem('kephir-xte-errors-' + wgPageName);
			} catch (e) {
				console.error('failed to parse error list ', e.message, e);
			}
		}
		var restorer = function (linenum, linetext, linechk) {
			return function () {
				if (fishy)
					return;
				var oldline = textbox.value.split(/\n/g);
			};
		};

		var rows = diff.getElementsByTagName('tr');
		var curlin = null;
		for (var i = 0; i < rows.length; ++i) {
			var dln = rows.getElementsByClassName('diff-lineno');
			if (dln.length === 2) {
				var m = /(\d+):$/.exec(dln.textContent);
				curlin = parseInt(m, 10);
				continue;
			}
			if (curlin === null)
				continue;
			var dm = rows.getElementsByClassName('diff-marker');
			if (!dm.length) {
				fishy = true;
				alert('Something is fishy with the diff.');
				continue;
			}
			if (dm.nextElementSibling.className == 'diff-deletedline') {
				var text = dm.nextElementSibling.textContent;
				var link = el('a', , { 'href': 'javascript:void(0);' }, { 'click': restorer(curlin, text) });
				while (dm.hasChildNodes()) {
					link.appendChild(dm.firstChild);
				}
				dm.appendChild(link);
			}
			++curlin;
		}
	}
}

});

jQuery(document).ready(function xteload() {
	if (// Run only in mainspace
		mw.config.get('wgNamespaceNumber') === 0 && 
		// if view
		mw.config.get('wgAction') === 'view' &&
		// and if a translation section exist
		$('.translations').length !== 0) {
			console.info('xte loaded');
			// add section links
			$('#Translations.mw-editsection').each(function(){
				var $link = $(this);
				$link.parents.append(
					$('span').text("fix2").attr({
						'href': 'javascript:void(null);', 
						'click': 'fixer(secnum)',
						'class': 'mw-editsection'
					}))
			})
			mw.util.addPortletLink( mw.config.get('skin') === 'vector' ? 'p-views' : 'p-cactions', 'fixer(null)()', 'Fix translations', 'Make translations use {{t}}');
	}
});
// </nowiki>