diff --git a/dspace-api/src/main/java/org/dspace/app/util/DCInput.java b/dspace-api/src/main/java/org/dspace/app/util/DCInput.java index f9d43a9abc98..bc15392a3818 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/DCInput.java +++ b/dspace-api/src/main/java/org/dspace/app/util/DCInput.java @@ -164,6 +164,11 @@ public class DCInput { */ private ComplexDefinition complexDefinition = null; + /** + * give suggestions from this specific autocomplete solr index/file + */ + private String autocompleteCustom = null; + /** * the dropdown input type could have defined a default value */ @@ -235,6 +240,9 @@ public DCInput(Map fieldMap, Map> listMap, if ("complex".equals(inputType)) { complexDefinition = complexDefinitions.getByName((fieldMap.get(DCInputsReader.COMPLEX_DEFINITION_REF))); } + if ("autocomplete".equals(inputType)) { + autocompleteCustom = fieldMap.get(DCInputsReader.AUTOCOMPLETE_CUSTOM); + } hint = fieldMap.get("hint"); warning = fieldMap.get("required"); required = warning != null && warning.length() > 0; @@ -725,6 +733,14 @@ public boolean isMetadataField() { return isMetadataField; } + public String getAutocompleteCustom() { + return autocompleteCustom; + } + + public void setAutocompleteCustom(String autocompleteCustom) { + this.autocompleteCustom = autocompleteCustom; + } + /** * Class representing a Map of the ComplexDefinition object * Class is copied from UFAL/CLARIN-DSPACE (https://github.com/ufal/clarin-dspace) and modified by diff --git a/dspace-api/src/main/java/org/dspace/app/util/DCInputsReader.java b/dspace-api/src/main/java/org/dspace/app/util/DCInputsReader.java index f79de9bd8df7..c6e3701ef003 100644 --- a/dspace-api/src/main/java/org/dspace/app/util/DCInputsReader.java +++ b/dspace-api/src/main/java/org/dspace/app/util/DCInputsReader.java @@ -76,6 +76,11 @@ public class DCInputsReader { static final String COMPLEX_DEFINITION_REF = "complex-definition-ref"; public static final String TYPE_BIND_FIELD_ATTRIBUTE = "field"; + /** + * Keyname for storing the name of the custom autocomplete input type + */ + static final String AUTOCOMPLETE_CUSTOM = "autocomplete-custom"; + /** * Reference to the forms definitions map, computed from the forms @@ -552,6 +557,11 @@ private void handleInputTypeTagName(String formName, Map field, } else { field.put(COMPLEX_DEFINITION_REF, definitionName); } + } else if (value.equals("autocomplete")) { + String definitionName = getAttribute(nd, AUTOCOMPLETE_CUSTOM); + if (definitionName != null) { + field.put(AUTOCOMPLETE_CUSTOM, definitionName); + } } } diff --git a/dspace-api/src/main/java/org/dspace/discovery/indexobject/ItemIndexFactoryImpl.java b/dspace-api/src/main/java/org/dspace/discovery/indexobject/ItemIndexFactoryImpl.java index 5357e899702c..3a034cf71586 100644 --- a/dspace-api/src/main/java/org/dspace/discovery/indexobject/ItemIndexFactoryImpl.java +++ b/dspace-api/src/main/java/org/dspace/discovery/indexobject/ItemIndexFactoryImpl.java @@ -605,6 +605,28 @@ public void addDiscoveryFields(SolrInputDocument doc, Context context, Item item } + + // process item metadata + // just add _comp to local* + List mds = itemService.getMetadata(item, "local", Item.ANY, Item.ANY, Item.ANY); + for (MetadataValue meta : mds) { + String field = "local" + "." + meta.getMetadataField().getElement(); + String value = meta.getValue(); + if (value == null) { + continue; + } + String qualifier = meta.getMetadataField().getQualifier(); + if (qualifier != null && !qualifier.isEmpty()) { + field += "." + qualifier; + } + doc.addField(field + "_comp", value); + } + + // create handle_title_ac field + String title = item.getName(); + String handle = item.getHandle(); + doc.addField("handle_title_ac", handle + ":" + title); + log.debug(" Added Metadata"); try { diff --git a/dspace-api/src/main/resources/iso_langs.json b/dspace-api/src/main/resources/iso_langs.json new file mode 100644 index 000000000000..35f95c150136 --- /dev/null +++ b/dspace-api/src/main/resources/iso_langs.json @@ -0,0 +1,7895 @@ +{ +"Ghotuo": "aaa", +"Alumu-Tesu": "aab", +"Ari": "aac", +"Amal": "aad", +"Arbëreshë Albanian": "aae", +"Aranadan": "aaf", +"Ambrak": "aag", +"Abu'Arapesh": "aah", +"Arifama-Miniafia": "aai", +"Ankave": "aak", +"Afade": "aal", +"Anambé": "aan", +"AlgerianSaharan Arabic": "aao", +"ParáArára": "aap", +"EasternAbnaki": "aaq", +"Afar": "aar", +"Aasáx": "aas", +"Arvanitika Albanian": "aat", +"Abau": "aau", +"Solong": "aaw", +"MandoboAtas": "aax", +"Amarasi": "aaz", +"Abé": "aba", +"Bankon": "abb", +"Ambala Ayta": "abc", +"Manide": "abd", +"Western Abnaki": "abe", +"Abai Sungai": "abf", +"Abaga": "abg", +"Tajiki Arabic": "abh", +"Abidji": "abi", +"Aka-Bea": "abj", +"Abkhazian": "abk", +"LampungNyo": "abl", +"Abanyom": "abm", +"Abua": "abn", +"Abon": "abo", +"AbellenAyta": "abp", +"Abaza": "abq", +"Abron": "abr", +"AmboneseMalay": "abs", +"Ambulas": "abt", +"Abure": "abu", +"BaharnaArabic": "abv", +"Pal": "abw", +"Inabaknon": "abx", +"AnemeWake": "aby", +"Abui": "abz", +"Achagua": "aca", +"Áncá": "acb", +"Gikyode": "acd", +"Achinese": "ace", +"Saint Lucian Creole French": "acf", +"Acoli": "ach", +"Aka-Cari": "aci", +"Aka-Kora": "ack", +"Akar-Bale": "acl", +"Mesopotamian Arabic": "acm", +"Achang": "acn", +"EasternAcipa": "acp", +"Ta'izzi-AdeniArabic": "acq", +"Achi": "acr", +"Acroá": "acs", +"Achterhoeks": "act", +"Achuar-Shiwiar": "acu", +"Achumawi": "acv", +"HijaziArabic": "acw", +"OmaniArabic": "acx", +"CypriotArabic": "acy", +"Acheron": "acz", +"Adangme": "ada", +"Adabe": "adb", +"Dzodinka": "add", +"Adele": "ade", +"DhofariArabic": "adf", +"Andegerebinha": "adg", +"Adhola": "adh", +"Adi": "adi", +"Adioukrou": "adj", +"Galo": "adl", +"Adang": "adn", +"Abu": "ado", +"Adangbe": "adq", +"Adonara": "adr", +"AdamorobeSign Language": "ads", +"Adnyamathanha": "adt", +"Aduge": "adu", +"Amundava": "adw", +"AmdoTibetan": "adx", +"Adyghe": "ady", +"Adzera": "adz", +"Areba": "aea", +"TunisianArabic": "aeb", +"SaidiArabic": "aec", +"ArgentineSign Language": "aed", +"Northeast Pashayi": "aee", +"Haeke": "aek", +"Ambele": "ael", +"Arem": "aem", +"ArmenianSign Language": "aen", +"Aer": "aeq", +"EasternArrernte": "aer", +"Alsea": "aes", +"Akeu": "aeu", +"Ambakich": "aew", +"Amele": "aey", +"Aeka": "aez", +"GulfArabic": "afb", +"Andai": "afd", +"Putukwam": "afe", +"AfghanSign Language": "afg", +"Afrihili": "afh", +"Akrukay": "afi", +"Nanubae": "afk", +"Defaka": "afn", +"Eloyi": "afo", +"Tapei": "afp", +"Afrikaans": "afr", +"Afro-SeminoleCreole": "afs", +"Afitti": "aft", +"Awutu": "afu", +"Obokuitai": "afz", +"Aguano": "aga", +"Legbo": "agb", +"Agatu": "agc", +"Agarabi": "agd", +"Angal": "age", +"Arguni": "agf", +"Angor": "agg", +"Ngelima": "agh", +"Agariya": "agi", +"Argobba": "agj", +"IsarogAgta": "agk", +"Fembe": "agl", +"Angaataha": "agm", +"Agutaynen": "agn", +"Tainae": "ago", +"Aghem": "agq", +"Aguaruna": "agr", +"Esimbi": "ags", +"Central Cagayan Agta": "agt", +"Aguacateco": "agu", +"Remontado Dumagat": "agv", +"Kahua": "agw", +"Aghul": "agx", +"SouthernAlta": "agy", +"Mt. Iriga Agta": "agz", +"Ahanta": "aha", +"Axamb": "ahb", +"Qimant": "ahg", +"Aghu": "ahh", +"TiagbamrinAizi": "ahi", +"Akha": "ahk", +"Igo": "ahl", +"MobumrinAizi": "ahm", +"Àhàn": "ahn", +"Ahom": "aho", +"AproumuAizi": "ahp", +"Ahirani": "ahr", +"Ashe": "ahs", +"Ahtena": "aht", +"Arosi": "aia", +"Ainu(China)": "aib", +"Ainbai": "aic", +"Alngith": "aid", +"Amara": "aie", +"Agi": "aif", +"Antigua and Barbuda Creole English": "aig", +"Ai-Cham": "aih", +"AssyrianNeo-Aramaic": "aii", +"LishanidNoshan": "aij", +"Ake": "aik", +"Aimele": "ail", +"Aimol": "aim", +"Ainu(Japan)": "ain", +"Aiton": "aio", +"Burumakok": "aip", +"Aimaq": "aiq", +"Airoran": "air", +"Arikem": "ait", +"Aari": "aiw", +"Aighon": "aix", +"Ali": "aiy", +"Aja(Sudan)": "aja", +"Aja(Benin)": "ajg", +"Ajië": "aji", +"Andajin": "ajn", +"South Levantine Arabic": "ajp", +"Judeo-TunisianArabic": "ajt", +"Judeo-Moroccan Arabic": "aju", +"Ajawa": "ajw", +"AmriKarbi": "ajz", +"Akan": "aka", +"BatakAngkola": "akb", +"Mpur": "akc", +"Ukpet-Ehom": "akd", +"Akawaio": "ake", +"Akpa": "akf", +"Anakalangu": "akg", +"AngalHeneng": "akh", +"Aiome": "aki", +"Aka-Jeru": "akj", +"Akkadian": "akk", +"Aklanon": "akl", +"Aka-Bo": "akm", +"Akurio": "ako", +"Siwu": "akp", +"Ak": "akq", +"Araki": "akr", +"Akaselem": "aks", +"Akolet": "akt", +"Akum": "aku", +"Akhvakh": "akv", +"Akwa": "akw", +"Aka-Kede": "akx", +"Aka-Kol": "aky", +"Alabama": "akz", +"Alago": "ala", +"Qawasqar": "alc", +"Alladian": "ald", +"Aleut": "ale", +"Alege": "alf", +"Alawa": "alh", +"Amaimon": "ali", +"Alangan": "alj", +"Alak": "alk", +"Allar": "all", +"Amblong": "alm", +"GhegAlbanian": "aln", +"Larike-Wakasihu": "alo", +"Alune": "alp", +"Algonquin": "alq", +"Alutor": "alr", +"ToskAlbanian": "als", +"Southern Altai": "alt", +"'Are'are": "alu", +"Alaba-K’abeena": "alw", +"Amol": "alx", +"Alyawarr": "aly", +"Alur": "alz", +"Amanayé": "ama", +"Ambo": "amb", +"Amahuaca": "amc", +"Yanesha'": "ame", +"Hamer-Banna": "amf", +"Amarag": "amg", +"Amharic": "amh", +"Amis": "ami", +"Amdang": "amj", +"Ambai": "amk", +"War-Jaintia": "aml", +"Ama (Papua New Guinea)": "amm", +"Amanab": "amn", +"Amo": "amo", +"Alamblak": "amp", +"Amahai": "amq", +"Amarakaeri": "amr", +"SouthernAmami-Oshima": "ams", +"Amto": "amt", +"Guerrero Amuzgo": "amu", +"Ambelau": "amv", +"WesternNeo-Aramaic": "amw", +"Anmatyerre": "amx", +"Ami": "amy", +"Atampaya": "amz", +"Andaqui": "ana", +"Andoa": "anb", +"Ngas": "anc", +"Ansus": "and", +"Xârâcùù": "ane", +"Animere": "anf", +"Old English (ca. 450-1100)": "ang", +"Nend": "anh", +"Andi": "ani", +"Anor": "anj", +"Goemai": "ank", +"Anu": "anl", +"Anal": "anm", +"Obolo": "ann", +"Andoque": "ano", +"Angika": "anp", +"Jarawa (India)": "anq", +"Andh": "anr", +"Anserma": "ans", +"Antakarinya": "ant", +"Anuak": "anu", +"Denya": "anv", +"Anaang": "anw", +"Andra-Hus": "anx", +"Anyin": "any", +"Anem": "anz", +"Angolar": "aoa", +"Abom": "aob", +"Pemon": "aoc", +"Andarum": "aod", +"AngalEnen": "aoe", +"Bragat": "aof", +"Angoram": "aog", +"Anindilyakwa": "aoi", +"Mufian": "aoj", +"Arhö": "aok", +"Alor": "aol", +"Ömie": "aom", +"BumbitaArapesh": "aon", +"Aore": "aor", +"Taikat": "aos", +"A'tong": "aot", +"A'ou": "aou", +"Atorada": "aox", +"UabMeto": "aoz", +"Sa'a": "apb", +"North Levantine Arabic": "apc", +"SudaneseArabic": "apd", +"Bukiyip": "ape", +"PahananAgta": "apf", +"Ampanang": "apg", +"Athpariya": "aph", +"Apiaká": "api", +"Jicarilla Apache": "apj", +"KiowaApache": "apk", +"LipanApache": "apl", +"Mescalero-ChiricahuaApache": "apm", +"Apinayé": "apn", +"Apalik": "apo", +"Apma": "app", +"A-Pucikwar": "apq", +"Arop-Lokep": "apr", +"Arop-Sissano": "aps", +"Apatani": "apt", +"Apurinã": "apu", +"Alapmunte": "apv", +"WesternApache": "apw", +"Aputai": "apx", +"Apalaí": "apy", +"Safeyoka": "apz", +"Archi": "aqc", +"Ampari Dogon": "aqd", +"Arigidi": "aqg", +"Aninka": "aqk", +"Atohwaim": "aqm", +"Northern Alta": "aqn", +"Atakapa": "aqp", +"Arhâ": "aqr", +"Angaité": "aqt", +"Akuntsu": "aqz", +"Arabic": "ara", +"StandardArabic": "arb", +"Official Aramaic (700-300 BCE)": "arc", +"Arabana": "ard", +"WesternArrarnta": "are", +"Aragonese": "arg", +"Arhuaco": "arh", +"Arikara": "ari", +"Arapaso": "arj", +"Arikapú": "ark", +"Arabela": "arl", +"Mapudungun": "arn", +"Araona": "aro", +"Arapaho": "arp", +"AlgerianArabic": "arq", +"Karo(Brazil)": "arr", +"NajdiArabic": "ars", +"Aruá (Amazonas State)": "aru", +"Arbore": "arv", +"Arawak": "arw", +"Aruá(Rodonia State)": "arx", +"MoroccanArabic": "ary", +"Egyptian Arabic": "arz", +"Asu(Tanzania)": "asa", +"Assiniboine": "asb", +"Casuarina Coast Asmat": "asc", +"AmericanSign Language": "ase", +"Australian Sign Language": "asf", +"Cishingini": "asg", +"Abishira": "ash", +"Buruwai": "asi", +"Nsari": "asj", +"Ashkun": "ask", +"Asilulu": "asl", +"Assamese": "asm", +"Xingú Asuriní": "asn", +"Dano": "aso", +"Algerian Sign Language": "asp", +"AustrianSign Language": "asq", +"Asuri": "asr", +"Ipulo": "ass", +"Asturian": "ast", +"TocantinsAsurini": "asu", +"Asoa": "asv", +"Australian Aborigines Sign Language": "asw", +"Muratayak": "asx", +"YaosakorAsmat": "asy", +"As": "asz", +"Pele-Ata": "ata", +"Zaiwa": "atb", +"Atsahuaca": "atc", +"AtaManobo": "atd", +"Atemble": "ate", +"Ivbie North-Okpela-Arhe": "atg", +"Attié": "ati", +"Atikamekw": "atj", +"Ati": "atk", +"Mt.Iraya Agta": "atl", +"Ata": "atm", +"Ashtiani": "atn", +"Atong": "ato", +"PudtolAtta": "atp", +"Aralle-Tabulahan": "atq", +"Waimiri-Atroari": "atr", +"GrosVentre": "ats", +"PamplonaAtta": "att", +"Reel": "atu", +"NorthernAltai": "atv", +"Atsugewi": "atw", +"Arutani": "atx", +"Aneityum": "aty", +"Arta": "atz", +"Asumboa": "aua", +"Alugu": "aub", +"Waorani": "auc", +"Anuta": "aud", +"Aguna": "aug", +"Aushi": "auh", +"Anuki": "aui", +"Awjilah": "auj", +"Heyo": "auk", +"Aulua": "aul", +"Asu(Nigeria)": "aum", +"MolmoOne": "aun", +"Auyokawa": "auo", +"Makayam": "aup", +"Anus": "auq", +"Aruek": "aur", +"Austral": "aut", +"Auye": "auu", +"Awyi": "auw", +"Aurá": "aux", +"Awiyaana": "auy", +"UzbekiArabic": "auz", +"Avaric": "ava", +"Avau": "avb", +"Alviri-Vidari": "avd", +"Avestan": "ave", +"Avikam": "avi", +"Kotava": "avk", +"Eastern Egyptian Bedawi Arabic": "avl", +"Angkamuthi": "avm", +"Avatime": "avn", +"Agavotaguerra": "avo", +"Aushiri": "avs", +"Au": "avt", +"Avokaya": "avu", +"Avá-Canoeiro": "avv", +"Awadhi": "awa", +"Awa (Papua New Guinea)": "awb", +"Cicipu": "awc", +"Awetí": "awe", +"Anguthimri": "awg", +"Awbono": "awh", +"Aekyom": "awi", +"Awabakal": "awk", +"Arawum": "awm", +"Awngi": "awn", +"Awak": "awo", +"Awera": "awr", +"South Awyu": "aws", +"Araweté": "awt", +"CentralAwyu": "awu", +"JairAwyu": "awv", +"Awun": "aww", +"Awara": "awx", +"EderaAwyu": "awy", +"Abipon": "axb", +"Ayerrerenge": "axe", +"MatoGrosso Arára": "axg", +"Yaka(Central African Republic)": "axk", +"Lower Southern Aranda": "axl", +"MiddleArmenian": "axm", +"Xaragure": "axx", +"Awar": "aya", +"AyizoGbe": "ayb", +"Southern Aymara": "ayc", +"Ayabadhu": "ayd", +"Ayere": "aye", +"Ginyanga": "ayg", +"HadramiArabic": "ayh", +"Leyigha": "ayi", +"Akuku": "ayk", +"LibyanArabic": "ayl", +"Aymara": "aym", +"Sanaani Arabic": "ayn", +"Ayoreo": "ayo", +"North Mesopotamian Arabic": "ayp", +"Ayi(Papua New Guinea)": "ayq", +"Central Aymara": "ayr", +"SorsogonAyta": "ays", +"Magbukun Ayta": "ayt", +"Ayu": "ayu", +"MaiBrat": "ayz", +"Azha": "aza", +"SouthAzerbaijani": "azb", +"Eastern Durango Nahuatl": "azd", +"Azerbaijani": "aze", +"San Pedro Amuzgos Amuzgo": "azg", +"NorthAzerbaijani": "azj", +"Ipalapa Amuzgo": "azm", +"Western Durango Nahuatl": "azn", +"Awing": "azo", +"FaireAtta": "azt", +"HighlandPuebla Nahuatl": "azz", +"Babatana": "baa", +"Bainouk-Gunyuño": "bab", +"Badui": "bac", +"Baré": "bae", +"Nubaca": "baf", +"Tuki": "bag", +"BahamasCreole English": "bah", +"Barakai": "baj", +"Bashkir": "bak", +"Baluchi": "bal", +"Bambara": "bam", +"Balinese": "ban", +"Waimaha": "bao", +"Bantawa": "bap", +"Bavarian": "bar", +"Basa (Cameroon)": "bas", +"Bada (Nigeria)": "bau", +"Vengo": "bav", +"Bambili-Bambui": "baw", +"Bamun": "bax", +"Batuley": "bay", +"Baatonum": "bba", +"Barai": "bbb", +"Batak Toba": "bbc", +"Bau": "bbd", +"Bangba": "bbe", +"Baibai": "bbf", +"Barama": "bbg", +"Bugan": "bbh", +"Barombi": "bbi", +"Ghomálá'": "bbj", +"Babanki": "bbk", +"Bats": "bbl", +"Babango": "bbm", +"Uneapa": "bbn", +"Northern Bobo Madaré": "bbo", +"WestCentral Banda": "bbp", +"Bamali": "bbq", +"Girawa": "bbr", +"Bakpinka": "bbs", +"Mburku": "bbt", +"Kulung(Nigeria)": "bbu", +"Karnai": "bbv", +"Baba": "bbw", +"Bubia": "bbx", +"Befang": "bby", +"CentralBai": "bca", +"Bainouk-Samik": "bcb", +"SouthernBalochi": "bcc", +"North Babar": "bcd", +"Bamenyam": "bce", +"Bamu": "bcf", +"BagaBinari": "bcg", +"Bariai": "bch", +"Baoulé": "bci", +"Bardi": "bcj", +"Bunaba": "bck", +"Central Bicolano": "bcl", +"Bannoni": "bcm", +"Bali(Nigeria)": "bcn", +"Kaluli": "bco", +"Bali (Democratic Republic of Congo)": "bcp", +"Bench": "bcq", +"Babine": "bcr", +"Kohumono": "bcs", +"Bendi": "bct", +"Awad Bing": "bcu", +"Shoo-Minda-Nye": "bcv", +"Bana": "bcw", +"Bacama": "bcy", +"Bainouk-Gunyaamolo": "bcz", +"Bayot": "bda", +"Basap": "bdb", +"Emberá-Baudó": "bdc", +"Bunama": "bdd", +"Bade": "bde", +"Biage": "bdf", +"Bonggi": "bdg", +"Baka(Sudan)": "bdh", +"Burun": "bdi", +"Bai": "bdj", +"Budukh": "bdk", +"Indonesian Bajau": "bdl", +"Buduma": "bdm", +"Baldemu": "bdn", +"Morom": "bdo", +"Bende": "bdp", +"Bahnar": "bdq", +"WestCoast Bajau": "bdr", +"Burunge": "bds", +"Bokoto": "bdt", +"Oroko": "bdu", +"BodoParja": "bdv", +"Baham": "bdw", +"Budong-Budong": "bdx", +"Bandjalang": "bdy", +"Badeshi": "bdz", +"Beaver": "bea", +"Bebele": "beb", +"Iceve-Maci": "bec", +"Bedoanas": "bed", +"Byangsi": "bee", +"Benabena": "bef", +"Belait": "beg", +"Biali": "beh", +"Bekati'": "bei", +"Beja": "bej", +"Bebeli": "bek", +"Belarusian": "bel", +"Bemba(Zambia)": "bem", +"Bengali": "ben", +"Beami": "beo", +"Besoa": "bep", +"Beembe": "beq", +"Besme": "bes", +"GuiberouaBéte": "bet", +"Blagar": "beu", +"DaloaBété": "bev", +"Betawi": "bew", +"JurModo": "bex", +"Beli(Papua New Guinea)": "bey", +"Bena(Tanzania)": "bez", +"Bari": "bfa", +"PauriBareli": "bfb", +"NorthernBai": "bfc", +"Bafut": "bfd", +"Betaf": "bfe", +"Bofi": "bff", +"Busang Kayan": "bfg", +"Blafe": "bfh", +"British Sign Language": "bfi", +"Bafanji": "bfj", +"BanKhor Sign Language": "bfk", +"Banda-Ndélé": "bfl", +"Mmen": "bfm", +"Bunak": "bfn", +"MalbaBirifor": "bfo", +"Beba": "bfp", +"Badaga": "bfq", +"Bazigar": "bfr", +"SouthernBai": "bfs", +"Balti": "bft", +"Gahri": "bfu", +"Bondo": "bfw", +"Bantayanon": "bfx", +"Bagheli": "bfy", +"Mahasu Pahari": "bfz", +"Gwamhi-Wuri": "bga", +"Bobongko": "bgb", +"Haryanvi": "bgc", +"RathwiBareli": "bgd", +"Bauria": "bge", +"Bangandu": "bgf", +"Bugun": "bgg", +"Giangan": "bgi", +"Bangolan": "bgj", +"Bit": "bgk", +"Bo(Laos)": "bgl", +"Western Balochi": "bgn", +"Baga Koga": "bgo", +"Eastern Balochi": "bgp", +"Bagri": "bgq", +"Bawm Chin": "bgr", +"Tagabawa": "bgs", +"Bughotu": "bgt", +"Mbongno": "bgu", +"Warkay-Bipim": "bgv", +"Bhatri": "bgw", +"BalkanGagauz Turkish": "bgx", +"Benggoi": "bgy", +"Banggai": "bgz", +"Bharia": "bha", +"Bhili": "bhb", +"Biga": "bhc", +"Bhadrawahi": "bhd", +"Bhaya": "bhe", +"Odiai": "bhf", +"Binandere": "bhg", +"Bukharic": "bhh", +"Bhilali": "bhi", +"Bahing": "bhj", +"Bimin": "bhl", +"Bathari": "bhm", +"Bohtan Neo-Aramaic": "bhn", +"Bhojpuri": "bho", +"Bima": "bhp", +"TukangBesi South": "bhq", +"BaraMalagasy": "bhr", +"Buwal": "bhs", +"Bhattiyali": "bht", +"Bhunjia": "bhu", +"Bahau": "bhv", +"Biak": "bhw", +"Bhalay": "bhx", +"Bhele": "bhy", +"Bada(Indonesia)": "bhz", +"Badimaya": "bia", +"Bissa": "bib", +"Bidiyo": "bid", +"Bepour": "bie", +"Biafada": "bif", +"Biangai": "big", +"Bikol": "bik", +"Bile": "bil", +"Bimoba": "bim", +"Bini": "bin", +"Nai": "bio", +"Bila": "bip", +"Bipi": "biq", +"Bisorio": "bir", +"Bislama": "bis", +"Berinomo": "bit", +"Biete": "biu", +"Southern Birifor": "biv", +"Kol (Cameroon)": "biw", +"Bijori": "bix", +"Birhor": "biy", +"Baloi": "biz", +"Budza": "bja", +"Banggarla": "bjb", +"Bariji": "bjc", +"Biao-JiaoMien": "bje", +"Barzani Jewish Neo-Aramaic": "bjf", +"Bidyogo": "bjg", +"Bahinemo": "bjh", +"Burji": "bji", +"Kanauji": "bjj", +"Barok": "bjk", +"Bulu(Papua New Guinea)": "bjl", +"Bajelani": "bjm", +"Banjar": "bjn", +"Mid-Southern Banda": "bjo", +"Fanamaket": "bjp", +"Binumarien": "bjr", +"Bajan": "bjs", +"Balanta-Ganja": "bjt", +"Busuu": "bju", +"Bedjond": "bjv", +"Bakwé": "bjw", +"Banao Itneg": "bjx", +"Bayali": "bjy", +"Baruga": "bjz", +"Kyak": "bka", +"Baka (Cameroon)": "bkc", +"Binukid": "bkd", +"Beeke": "bkf", +"Buraka": "bkg", +"Bakoko": "bkh", +"Baki": "bki", +"Pande": "bkj", +"Brokskat": "bkk", +"Berik": "bkl", +"Kom(Cameroon)": "bkm", +"Bukitan": "bkn", +"Kwa'": "bko", +"Boko(Democratic Republic of Congo)": "bkp", +"Bakairí": "bkq", +"Bakumpai": "bkr", +"NorthernSorsoganon": "bks", +"Boloki": "bkt", +"Buhid": "bku", +"Bekwarra": "bkv", +"Bekwil": "bkw", +"Baikeno": "bkx", +"Bokyi": "bky", +"Bungku": "bkz", +"Siksika": "bla", +"Bilua": "blb", +"BellaCoola": "blc", +"Bolango": "bld", +"Balanta-Kentohe": "ble", +"Buol": "blf", +"Kuwaa": "blh", +"Bolia": "bli", +"Bolongan": "blj", +"Pa'o Karen": "blk", +"Biloxi": "bll", +"Beli(Sudan)": "blm", +"Southern Catanduanes Bicolano": "bln", +"Anii": "blo", +"Blablanga": "blp", +"Baluan-Pam": "blq", +"Blang": "blr", +"Balaesang": "bls", +"Tai Dam": "blt", +"Bolo": "blv", +"Balangao": "blw", +"Mag-Indi Ayta": "blx", +"Notre": "bly", +"Balantak": "blz", +"Lame": "bma", +"Bembe": "bmb", +"Biem": "bmc", +"BagaManduri": "bmd", +"Limassa": "bme", +"Bom": "bmf", +"Bamwe": "bmg", +"Kein": "bmh", +"Bagirmi": "bmi", +"Bote-Majhi": "bmj", +"Ghayavi": "bmk", +"Bomboli": "bml", +"Northern Betsimisaraka Malagasy": "bmm", +"Bina(Papua New Guinea)": "bmn", +"Bambalang": "bmo", +"Bulgebi": "bmp", +"Bomu": "bmq", +"Muinane": "bmr", +"BilmaKanuri": "bms", +"BiaoMon": "bmt", +"Burum-Mindik": "bmu", +"Bum": "bmv", +"Bomwali": "bmw", +"Baimak": "bmx", +"Baramu": "bmz", +"Bonerate": "bna", +"Bookan": "bnb", +"Bontok": "bnc", +"Banda(Indonesia)": "bnd", +"Bintauna": "bne", +"Masiwang": "bnf", +"Benga": "bng", +"Bangi": "bni", +"EasternTawbuid": "bnj", +"Bierebo": "bnk", +"Boon": "bnl", +"Batanga": "bnm", +"Bunun": "bnn", +"Bantoanon": "bno", +"Bola": "bnp", +"Bantik": "bnq", +"Butmas-Tur": "bnr", +"Bundeli": "bns", +"Bentong": "bnu", +"Bonerif": "bnv", +"Bisis": "bnw", +"Bangubangu": "bnx", +"Bintulu": "bny", +"Beezen": "bnz", +"Bora": "boa", +"Aweer": "bob", +"Tibetan": "bod", +"Mundabli": "boe", +"Bolon": "bof", +"Bamako Sign Language": "bog", +"Boma": "boh", +"Barbareño": "boi", +"Anjam": "boj", +"Bonjo": "bok", +"Bole": "bol", +"Berom": "bom", +"Bine": "bon", +"Tiemacèwè Bozo": "boo", +"Bonkiman": "bop", +"Bogaya": "boq", +"Borôro": "bor", +"Bosnian": "bos", +"Bongo": "bot", +"Bondei": "bou", +"Tuwuli": "bov", +"Rema": "bow", +"Buamu": "box", +"Bodo(Central African Republic)": "boy", +"Tiéyaxo Bozo": "boz", +"Dakaka": "bpa", +"Banda-Banda": "bpd", +"Bauni": "bpe", +"Bonggo": "bpg", +"Botlikh": "bph", +"Bagupi": "bpi", +"Binji": "bpj", +"Orowe": "bpk", +"Broome Pearling Lugger Pidgin": "bpl", +"Biyom": "bpm", +"DzaoMin": "bpn", +"Anasi": "bpo", +"Kaure": "bpp", +"Banda Malay": "bpq", +"KoronadalBlaan": "bpr", +"SaranganiBlaan": "bps", +"Barrow Point": "bpt", +"Bongu": "bpu", +"BianMarind": "bpv", +"Bo (Papua New Guinea)": "bpw", +"PalyaBareli": "bpx", +"Bishnupriya": "bpy", +"Bilba": "bpz", +"Tchumbuli": "bqa", +"Bagusa": "bqb", +"Boko (Benin)": "bqc", +"Bung": "bqd", +"BagaKaloum": "bqf", +"Bago-Kusuntu": "bqg", +"Baima": "bqh", +"Bakhtiari": "bqi", +"Bandial": "bqj", +"Banda-Mbrès": "bqk", +"Bilakura": "bql", +"Wumboko": "bqm", +"Bulgarian Sign Language": "bqn", +"Balo": "bqo", +"Busa": "bqp", +"Biritai": "bqq", +"Burusu": "bqr", +"Bosngun": "bqs", +"Bamukumbit": "bqt", +"Boguru": "bqu", +"Begbere-Ejar": "bqv", +"Buru (Nigeria)": "bqw", +"Baangi": "bqx", +"BengkalaSign Language": "bqy", +"Bakaka": "bqz", +"Braj": "bra", +"Lave": "brb", +"Berbice Creole Dutch": "brc", +"Baraamu": "brd", +"Breton": "bre", +"Bera": "brf", +"Baure": "brg", +"Brahui": "brh", +"Mokpwe": "bri", +"Bieria": "brj", +"Birked": "brk", +"Birwa": "brl", +"Barambu": "brm", +"Boruca": "brn", +"Brokkat": "bro", +"Barapasi": "brp", +"Breri": "brq", +"Birao": "brr", +"Baras": "brs", +"Bitare": "brt", +"EasternBru": "bru", +"Western Bru": "brv", +"Bellari": "brw", +"Bodo (India)": "brx", +"Burui": "bry", +"Bilbil": "brz", +"Abinomn": "bsa", +"Brunei Bisaya": "bsb", +"Bassari": "bsc", +"Wushi": "bse", +"Bauchi": "bsf", +"Bashkardi": "bsg", +"Kati": "bsh", +"Bassossi": "bsi", +"Bangwinji": "bsj", +"Burushaski": "bsk", +"Basa-Gumna": "bsl", +"Busami": "bsm", +"Barasana-Eduria": "bsn", +"Buso": "bso", +"Baga Sitemu": "bsp", +"Bassa": "bsq", +"Bassa-Kontagora": "bsr", +"Akoose": "bss", +"Basketo": "bst", +"Bahonsuai": "bsu", +"BagaSobané": "bsv", +"Baiso": "bsw", +"Yangkam": "bsx", +"Sabah Bisaya": "bsy", +"Bata": "bta", +"Bati(Cameroon)": "btc", +"BatakDairi": "btd", +"Gamo-Ningi": "bte", +"Birgit": "btf", +"GagnoaBété": "btg", +"Biatah Bidayuh": "bth", +"Burate": "bti", +"Bacanese Malay": "btj", +"BatakMandailing": "btm", +"Ratagnon": "btn", +"Rinconada Bikol": "bto", +"Budibud": "btp", +"Batek": "btq", +"Baetora": "btr", +"BatakSimalungun": "bts", +"Bete-Bendi": "btt", +"Batu": "btu", +"Bateri": "btv", +"Butuanon": "btw", +"Batak Karo": "btx", +"Bobot": "bty", +"Batak Alas-Kluet": "btz", +"Buriat": "bua", +"Bua": "bub", +"Bushi": "buc", +"Ntcham": "bud", +"Beothuk": "bue", +"Bushoong": "buf", +"Buginese": "bug", +"Younuo Bunu": "buh", +"Bongili": "bui", +"Basa-Gurmana": "buj", +"Bugawac": "buk", +"Bulgarian": "bul", +"Bulu (Cameroon)": "bum", +"Sherbro": "bun", +"Terei": "buo", +"Busoa": "bup", +"Brem": "buq", +"Bokobaru": "bus", +"Bungain": "but", +"Budu": "buu", +"Bun": "buv", +"Bubi": "buw", +"Boghom": "bux", +"BullomSo": "buy", +"Bukwen": "buz", +"Barein": "bva", +"Bube": "bvb", +"Baelelea": "bvc", +"Baeggu": "bvd", +"BerauMalay": "bve", +"Boor": "bvf", +"Bonkeng": "bvg", +"Bure": "bvh", +"BelandaViri": "bvi", +"Baan": "bvj", +"Bukat": "bvk", +"BolivianSign Language": "bvl", +"Bamunka": "bvm", +"Buna": "bvn", +"Bolgo": "bvo", +"Bumang": "bvp", +"Birri": "bvq", +"Burarra": "bvr", +"Bati(Indonesia)": "bvt", +"BukitMalay": "bvu", +"Baniva": "bvv", +"Boga": "bvw", +"Dibole": "bvx", +"Baybayanon": "bvy", +"Bauzi": "bvz", +"Bwatoo": "bwa", +"Namosi-Naitasiri-Serua": "bwb", +"Bwile": "bwc", +"Bwaidoka": "bwd", +"BweKaren": "bwe", +"Boselewa": "bwf", +"Barwe": "bwg", +"Bishuo": "bwh", +"Baniwa": "bwi", +"Láá Láá Bwamu": "bwj", +"Bauwaki": "bwk", +"Bwela": "bwl", +"Biwat": "bwm", +"WunaiBunu": "bwn", +"Boro(Ethiopia)": "bwo", +"MandoboBawah": "bwp", +"SouthernBobo Madaré": "bwq", +"Bura-Pabir": "bwr", +"Bomboma": "bws", +"Bafaw-Balong": "bwt", +"Buli(Ghana)": "bwu", +"Bwa": "bww", +"Bu-NaoBunu": "bwx", +"Cwi Bwamu": "bwy", +"Bwisi": "bwz", +"Bauro": "bxa", +"BelandaBor": "bxb", +"Molengue": "bxc", +"Pela": "bxd", +"Birale": "bxe", +"Bilur": "bxf", +"Bangala": "bxg", +"Buhutu": "bxh", +"Pirlatapa": "bxi", +"Bayungu": "bxj", +"Bukusu": "bxk", +"Jalkunan": "bxl", +"MongoliaBuriat": "bxm", +"Burduna": "bxn", +"Barikanchi": "bxo", +"Bebil": "bxp", +"Beele": "bxq", +"Russia Buriat": "bxr", +"Busam": "bxs", +"China Buriat": "bxu", +"Berakou": "bxv", +"Bankagooma": "bxw", +"Binahari": "bxz", +"Batak": "bya", +"Bikya": "byb", +"Ubaghara": "byc", +"Benyadu'": "byd", +"Pouye": "bye", +"Bete": "byf", +"Baygo": "byg", +"Bhujel": "byh", +"Buyu": "byi", +"Bina (Nigeria)": "byj", +"Biao": "byk", +"Bayono": "byl", +"Bidyara": "bym", +"Bilin": "byn", +"Biyo": "byo", +"Bumaji": "byp", +"Basay": "byq", +"Baruya": "byr", +"Burak": "bys", +"Berti": "byt", +"Medumba": "byv", +"Belhariya": "byw", +"Qaqet": "byx", +"Banaro": "byz", +"Bandi": "bza", +"Andio": "bzb", +"Southern Betsimisaraka Malagasy": "bzc", +"Bribri": "bzd", +"JenaamaBozo": "bze", +"Boikin": "bzf", +"Babuza": "bzg", +"MaposBuang": "bzh", +"Bisu": "bzi", +"Belize Kriol English": "bzj", +"Nicaragua Creole English": "bzk", +"Boano(Sulawesi)": "bzl", +"Bolondo": "bzm", +"Boano (Maluku)": "bzn", +"Bozaba": "bzo", +"Kemberano": "bzp", +"Buli (Indonesia)": "bzq", +"Biri": "bzr", +"Brazilian Sign Language": "bzs", +"Brithenig": "bzt", +"Burmeso": "bzu", +"Bebe": "bzv", +"Basa(Nigeria)": "bzw", +"HainyaxoBozo": "bzx", +"Obanliku": "bzy", +"Evant": "bzz", +"Chortí": "caa", +"Garifuna": "cab", +"Chuj": "cac", +"Caddo": "cad", +"Lehar": "cae", +"SouthernCarrier": "caf", +"Nivaclé": "cag", +"Cahuarano": "cah", +"Chané": "caj", +"Kaqchikel": "cak", +"Carolinian": "cal", +"Cemuhî": "cam", +"Chambri": "can", +"Chácobo": "cao", +"Chipaya": "cap", +"Car Nicobarese": "caq", +"Galibi Carib": "car", +"Tsimané": "cas", +"Catalan": "cat", +"Cavineña": "cav", +"Callawalla": "caw", +"Chiquitano": "cax", +"Cayuga": "cay", +"Canichana": "caz", +"Cabiyarí": "cbb", +"Carapana": "cbc", +"Carijona": "cbd", +"Chimila": "cbg", +"Chachi": "cbi", +"EdeCabe": "cbj", +"Chavacano": "cbk", +"Bualkhaw Chin": "cbl", +"Nyahkur": "cbn", +"Izora": "cbo", +"Tsucuba": "cbq", +"Cashibo-Cacataibo": "cbr", +"Cashinahua": "cbs", +"Chayahuita": "cbt", +"Candoshi-Shapra": "cbu", +"Cacua": "cbv", +"Kinabalian": "cbw", +"Carabayo": "cby", +"Chamicuro": "ccc", +"Cafundo Creole": "ccd", +"Chopi": "cce", +"SambaDaka": "ccg", +"Atsam": "cch", +"Kasanga": "ccj", +"Cutchi-Swahili": "ccl", +"Malaccan Creole Malay": "ccm", +"ComaltepecChinantec": "cco", +"Chakma": "ccp", +"Cacaopera": "ccr", +"Choni": "cda", +"Chenchu": "cde", +"Chiru": "cdf", +"Chambeali": "cdh", +"Chodri": "cdi", +"Churahi": "cdj", +"Chepang": "cdm", +"Chaudangsi": "cdn", +"Min Dong Chinese": "cdo", +"Cinda-Regi-Tiyal": "cdr", +"ChadianSign Language": "cds", +"Chadong": "cdy", +"Koda": "cdz", +"Lower Chehalis": "cea", +"Cebuano": "ceb", +"Chamacoco": "ceg", +"Eastern Khumi Chin": "cek", +"Cen": "cen", +"Czech": "ces", +"Centúúm": "cet", +"Ekai Chin": "cey", +"Dijim-Bwilim": "cfa", +"Cara": "cfd", +"ComoKarim": "cfg", +"FalamChin": "cfm", +"Changriwa": "cga", +"Kagayanen": "cgc", +"Chiga": "cgg", +"Chocangacakha": "cgk", +"Chamorro": "cha", +"Chibcha": "chb", +"Catawba": "chc", +"HighlandOaxaca Chontal": "chd", +"Chechen": "che", +"TabascoChontal": "chf", +"Chagatai": "chg", +"Chinook": "chh", +"OjitlánChinantec": "chj", +"Chuukese": "chk", +"Cahuilla": "chl", +"Mari (Russia)": "chm", +"Chinookjargon": "chn", +"Choctaw": "cho", +"Chipewyan": "chp", +"Quiotepec Chinantec": "chq", +"Cherokee": "chr", +"Cholón": "cht", +"ChurchSlavic": "chu", +"Chuvash": "chv", +"Chuwabu": "chw", +"Chantyal": "chx", +"Cheyenne": "chy", +"Ozumacín Chinantec": "chz", +"Cia-Cia": "cia", +"CiGbe": "cib", +"Chickasaw": "cic", +"Chimariko": "cid", +"Cineni": "cie", +"Chinali": "cih", +"ChitkuliKinnauri": "cik", +"Cimbrian": "cim", +"CintaLarga": "cin", +"Chiapanec": "cip", +"Tiri": "cir", +"Chippewa": "ciw", +"Chaima": "ciy", +"WesternCham": "cja", +"Chru": "cje", +"UpperChehalis": "cjh", +"Chamalal": "cji", +"Chokwe": "cjk", +"EasternCham": "cjm", +"Chenapian": "cjn", +"AshéninkaPajonal": "cjo", +"Cabécar": "cjp", +"Shor": "cjs", +"Chuave": "cjv", +"Jinyu Chinese": "cjy", +"CentralKurdish": "ckb", +"Chak": "ckh", +"Cibak": "ckl", +"Chakavian": "ckm", +"Kaang Chin": "ckn", +"Anufo": "cko", +"Kajakse": "ckq", +"Kairak": "ckr", +"Tayo": "cks", +"Chukot": "ckt", +"Koasati": "cku", +"Kavalan": "ckv", +"Caka": "ckx", +"Cakfem-Mushere": "cky", +"Cakchiquel-Quiché Mixed Language": "ckz", +"Ron": "cla", +"Chilcotin": "clc", +"Chaldean Neo-Aramaic": "cld", +"LealaoChinantec": "cle", +"Chilisso": "clh", +"Chakali": "cli", +"Laitu Chin": "clj", +"Idu-Mishmi": "clk", +"Chala": "cll", +"Clallam": "clm", +"Lowland Oaxaca Chontal": "clo", +"Lautu Chin": "clt", +"Caluyanun": "clu", +"Chulym": "clw", +"Eastern Highland Chatino": "cly", +"Maa": "cma", +"Cerma": "cme", +"ClassicalMongolian": "cmg", +"Emberá-Chamí": "cmi", +"Campalagian": "cml", +"Michigamea": "cmm", +"MandarinChinese": "cmn", +"CentralMnong": "cmo", +"Mro Chin": "cmr", +"Messapic": "cms", +"Camtho": "cmt", +"Changthang": "cna", +"ChinbonChin": "cnb", +"Côông": "cnc", +"NorthernQiang": "cng", +"HakaChin": "cnh", +"Asháninka": "cni", +"KhumiChin": "cnk", +"Lalana Chinantec": "cnl", +"Con": "cno", +"Northern Ping Chinese": "cnp", +"Montenegrin": "cnr", +"CentralAsmat": "cns", +"Tepetotutla Chinantec": "cnt", +"Chenoua": "cnu", +"NgawnChin": "cnw", +"MiddleCornish": "cnx", +"Cocos Islands Malay": "coa", +"Chicomuceltec": "cob", +"Cocopa": "coc", +"Cocama-Cocamilla": "cod", +"Koreguaje": "coe", +"Colorado": "cof", +"Chong": "cog", +"Chonyi-Dzihana-Kauma": "coh", +"Cochimi": "coj", +"SantaTeresa Cora": "cok", +"Columbia-Wenatchi": "col", +"Comanche": "com", +"Cofán": "con", +"Comox": "coo", +"Coptic": "cop", +"Coquille": "coq", +"Cornish": "cor", +"Corsican": "cos", +"Caquinte": "cot", +"Wamey": "cou", +"CaoMiao": "cov", +"Cowlitz": "cow", +"Nanti": "cox", +"Chochotec": "coz", +"Palantla Chinantec": "cpa", +"Ucayali-YurúaAshéninka": "cpb", +"AjyíninkaApurucayali": "cpc", +"CappadocianGreek": "cpg", +"ChinesePidgin English": "cpi", +"Cherepon": "cpn", +"Kpeego": "cpo", +"Capiznon": "cps", +"PichisAshéninka": "cpu", +"Pu-XianChinese": "cpx", +"South Ucayali Ashéninka": "cpy", +"Chuanqiandian Cluster Miao": "cqd", +"Chara": "cra", +"IslandCarib": "crb", +"Lonwolwol": "crc", +"Coeurd'Alene": "crd", +"Cree": "cre", +"Caramanta": "crf", +"Michif": "crg", +"CrimeanTatar": "crh", +"Sãotomense": "cri", +"SouthernEast Cree": "crj", +"PlainsCree": "crk", +"NorthernEast Cree": "crl", +"MooseCree": "crm", +"ElNayar Cora": "crn", +"Crow": "cro", +"Iyo'wujwaChorote": "crq", +"Carolina Algonquian": "crr", +"Seselwa Creole French": "crs", +"Iyojwa'ja Chorote": "crt", +"Chaura": "crv", +"Chrau": "crw", +"Carrier": "crx", +"Cori": "cry", +"Cruzeño": "crz", +"Chiltepec Chinantec": "csa", +"Kashubian": "csb", +"CatalanSign Language": "csc", +"ChiangmaiSign Language": "csd", +"CzechSign Language": "cse", +"Cuba Sign Language": "csf", +"Chilean Sign Language": "csg", +"AshoChin": "csh", +"CoastMiwok": "csi", +"Songlai Chin": "csj", +"Jola-Kasa": "csk", +"Chinese Sign Language": "csl", +"CentralSierra Miwok": "csm", +"ColombianSign Language": "csn", +"SochiapamChinantec": "cso", +"Southern Ping Chinese": "csp", +"CroatiaSign Language": "csq", +"CostaRican Sign Language": "csr", +"SouthernOhlone": "css", +"Northern Ohlone": "cst", +"Sumtu Chin": "csv", +"Swampy Cree": "csw", +"Cambodian Sign Language": "csx", +"Siyin Chin": "csy", +"Coos": "csz", +"TataltepecChatino": "cta", +"Chetco": "ctc", +"Tedim Chin": "ctd", +"Tepinapa Chinantec": "cte", +"Chittagonian": "ctg", +"Thaiphum Chin": "cth", +"TlacoatzintepecChinantec": "ctl", +"Chitimacha": "ctm", +"Chhintange": "ctn", +"Emberá-Catío": "cto", +"Western Highland Chatino": "ctp", +"Northern Catanduanes Bicolano": "cts", +"WayanadChetti": "ctt", +"Chol": "ctu", +"Moundadan Chetty": "cty", +"ZacatepecChatino": "ctz", +"Cua": "cua", +"Cubeo": "cub", +"UsilaChinantec": "cuc", +"Cung": "cug", +"Chuka": "cuh", +"Cuiba": "cui", +"MashcoPiro": "cuj", +"SanBlas Kuna": "cuk", +"Culina": "cul", +"Cumanagoto": "cuo", +"Cupeño": "cup", +"Cun": "cuq", +"Chhulung": "cur", +"TeutilaCuicatec": "cut", +"TaiYa": "cuu", +"Cuvok": "cuv", +"Chukwa": "cuw", +"TepeuxilaCuicatec": "cux", +"Cuitlatec": "cuy", +"Chug": "cvg", +"Valle Nacional Chinantec": "cvn", +"Kabwa": "cwa", +"Maindo": "cwb", +"Woods Cree": "cwd", +"Kwere": "cwe", +"Chewong": "cwg", +"Kuwaataay": "cwt", +"Nopala Chatino": "cya", +"Cayubaba": "cyb", +"Welsh": "cym", +"Cuyonon": "cyo", +"Huizhou Chinese": "czh", +"Knaanic": "czk", +"ZenzontepecChatino": "czn", +"Min Zhong Chinese": "czo", +"ZotungChin": "czt", +"Dangaléat": "daa", +"Dambi": "dac", +"Marik": "dad", +"Duupa": "dae", +"Dagbani": "dag", +"Gwahatike": "dah", +"Day": "dai", +"DarFur Daju": "daj", +"Dakota": "dak", +"Dahalo": "dal", +"Damakawa": "dam", +"Danish": "dan", +"DaaiChin": "dao", +"Dandami Maria": "daq", +"Dargwa": "dar", +"Daho-Doo": "das", +"DarSila Daju": "dau", +"Taita": "dav", +"Davawenyo": "daw", +"Dayi": "dax", +"Dao": "daz", +"BangiMe": "dba", +"Deno": "dbb", +"Dadiya": "dbd", +"Dabe": "dbe", +"Edopi": "dbf", +"DogulDom Dogon": "dbg", +"Doka": "dbi", +"Ida'an": "dbj", +"Dyirbal": "dbl", +"Duguri": "dbm", +"Duriankere": "dbn", +"Dulbu": "dbo", +"Duwai": "dbp", +"Daba": "dbq", +"Dabarre": "dbr", +"Ben Tey Dogon": "dbt", +"BondumDom Dogon": "dbu", +"Dungu": "dbv", +"Bankan Tey Dogon": "dbw", +"Dibiyaso": "dby", +"Deccan": "dcc", +"Negerhollands": "dcr", +"Dadi Dadi": "dda", +"Dongotono": "ddd", +"Doondo": "dde", +"Fataluku": "ddg", +"West Goodenough": "ddi", +"Jaru": "ddj", +"Dendi (Benin)": "ddn", +"Dido": "ddo", +"Dhudhuroa": "ddr", +"Donno So Dogon": "dds", +"Dawera-Daweloor": "ddw", +"Dagik": "dec", +"Dedua": "ded", +"Dewoin": "dee", +"Dezfuli": "def", +"Degema": "deg", +"Dehwari": "deh", +"Demisa": "dei", +"Dek": "dek", +"Delaware": "del", +"Dem": "dem", +"Slave (Athapascan)": "den", +"PidginDelaware": "dep", +"Dendi(Central African Republic)": "deq", +"Deori": "der", +"Desano": "des", +"German": "deu", +"Domung": "dev", +"Dengese": "dez", +"SouthernDagaare": "dga", +"Bunoge Dogon": "dgb", +"CasiguranDumagat Agta": "dgc", +"Dagaari Dioula": "dgd", +"Degenan": "dge", +"Doga": "dgg", +"Dghwede": "dgh", +"NorthernDagara": "dgi", +"Dagba": "dgk", +"Andaandi": "dgl", +"Dagoman": "dgn", +"Dogri(individual language)": "dgo", +"Dogrib": "dgr", +"Dogoso": "dgs", +"Ndra'ngith": "dgt", +"Daungwurrung": "dgw", +"Doghoro": "dgx", +"Daga": "dgz", +"Dhundari": "dhd", +"Dhangu": "dhg", +"Dhimal": "dhi", +"Dhalandji": "dhl", +"Zemba": "dhm", +"Dhanki": "dhn", +"Dhodia": "dho", +"Dhargari": "dhr", +"Dhaiso": "dhs", +"Dhurga": "dhu", +"Dehu": "dhv", +"Dhanwar(Nepal)": "dhw", +"Dhungaloo": "dhx", +"Dia": "dia", +"South Central Dinka": "dib", +"Lakota Dida": "dic", +"Didinga": "did", +"Dieri": "dif", +"Digo": "dig", +"Kumiai": "dih", +"Dimbong": "dii", +"Dai": "dij", +"Southwestern Dinka": "dik", +"Dilling": "dil", +"Dime": "dim", +"Dinka": "din", +"Dibo": "dio", +"NortheasternDinka": "dip", +"Dimli (individual language)": "diq", +"Dirim": "dir", +"Dimasa": "dis", +"Diriku": "diu", +"Dhivehi": "div", +"NorthwesternDinka": "diw", +"DixonReef": "dix", +"Diuwe": "diy", +"Ding": "diz", +"Djadjawurrung": "dja", +"Djinba": "djb", +"Dar Daju Daju": "djc", +"Djamindjung": "djd", +"Zarma": "dje", +"Djangun": "djf", +"Djinang": "dji", +"Djeebbana": "djj", +"Eastern Maroon Creole": "djk", +"Jamsay Dogon": "djm", +"Djauan": "djn", +"Jangkang": "djo", +"Djambarrpuyngu": "djr", +"Kapriman": "dju", +"Djawi": "djw", +"Dakpakha": "dka", +"Kadung": "dkg", +"Dakka": "dkk", +"Kuijau": "dkr", +"SoutheasternDinka": "dks", +"Mazagway": "dkx", +"Dolgan": "dlg", +"Dahalik": "dlk", +"Dalmatian": "dlm", +"Darlong": "dln", +"Duma": "dma", +"Mombo Dogon": "dmb", +"Dimir": "dmc", +"Madhi Madhi": "dmd", +"Dugwor": "dme", +"Medefaidrin": "dmf", +"UpperKinabatangan": "dmg", +"Domaaki": "dmk", +"Dameli": "dml", +"Dama": "dmm", +"Kemezung": "dmo", +"EastDamar": "dmr", +"Dampelas": "dms", +"Dubu": "dmu", +"Dumpas": "dmv", +"Mudburra": "dmw", +"Dema": "dmx", +"Demta": "dmy", +"UpperGrand Valley Dani": "dna", +"Daonda": "dnd", +"Ndendeule": "dne", +"Dungan": "dng", +"LowerGrand Valley Dani": "dni", +"Dan": "dnj", +"Dengka": "dnk", +"Dzùùngoo": "dnn", +"Ndrulo": "dno", +"Danaru": "dnr", +"MidGrand Valley Dani": "dnt", +"Danau": "dnu", +"Danu": "dnv", +"Western Dani": "dnw", +"Dení": "dny", +"Dom": "doa", +"Dobu": "dob", +"Northern Dong": "doc", +"Doe": "doe", +"Domu": "dof", +"Dong": "doh", +"Dogri (macrolanguage)": "doi", +"Dondo": "dok", +"Doso": "dol", +"Toura(Papua New Guinea)": "don", +"Dongo": "doo", +"Lukpa": "dop", +"Dominican Sign Language": "doq", +"Dori'o": "dor", +"Dogosé": "dos", +"Dass": "dot", +"Dombe": "dov", +"Doyayo": "dow", +"Bussa": "dox", +"Dompo": "doy", +"Dorze": "doz", +"Papar": "dpp", +"Dair": "drb", +"Minderico": "drc", +"Darmiya": "drd", +"Dolpo": "dre", +"Rungus": "drg", +"C'lela": "dri", +"Darling": "drl", +"WestDamar": "drn", +"Daro-MatuMelanau": "dro", +"Dura": "drq", +"Gedeo": "drs", +"Drents": "drt", +"Rukai": "dru", +"Darai": "dry", +"LowerSorbian": "dsb", +"DutchSign Language": "dse", +"Daasanach": "dsh", +"Disa": "dsi", +"Danish Sign Language": "dsl", +"Dusner": "dsn", +"Desiya": "dso", +"Tadaksahak": "dsq", +"Daur": "dta", +"Labuk-Kinabatangan Kadazan": "dtb", +"Ditidaht": "dtd", +"Adithinngithigh": "dth", +"AnaTinga Dogon": "dti", +"Tene Kan Dogon": "dtk", +"TomoKan Dogon": "dtm", +"Daatsʼíin": "dtn", +"Tommo So Dogon": "dto", +"CentralDusun": "dtp", +"Lotud": "dtr", +"Toro So Dogon": "dts", +"ToroTegu Dogon": "dtt", +"Tebul Ure Dogon": "dtu", +"Dotyali": "dty", +"Duala": "dua", +"Dubli": "dub", +"Duna": "duc", +"UmirayDumaget Agta": "due", +"Dumbea": "duf", +"Duruma": "dug", +"DungraBhil": "duh", +"Dumun": "dui", +"Duduela": "duk", +"AlabatIsland Agta": "dul", +"Middle Dutch (ca. 1050-1350)": "dum", +"DusunDeyah": "dun", +"Dupaninan Agta": "duo", +"Duano": "dup", +"DusunMalang": "duq", +"Dii": "dur", +"Dumi": "dus", +"Drung": "duu", +"Duvle": "duv", +"Dusun Witu": "duw", +"Duungooma": "dux", +"DicamayAgta": "duy", +"Duli": "duz", +"Duau": "dva", +"Diri": "dwa", +"Dawik Kui": "dwk", +"Dawro": "dwr", +"Dutton World Speedwords": "dws", +"Dhuwal": "dwu", +"Dawawa": "dww", +"Dhuwaya": "dwy", +"Dewas Rai": "dwz", +"Dyan": "dya", +"Dyaberdyaber": "dyb", +"Dyugun": "dyd", +"VillaViciosa Agta": "dyg", +"DjiminiSenoufo": "dyi", +"YandaDom Dogon": "dym", +"Dyangadi": "dyn", +"Jola-Fonyi": "dyo", +"Dyula": "dyu", +"Dyaabugay": "dyy", +"Tunzu": "dza", +"Djiwarli": "dze", +"Dazaga": "dzg", +"Dzalakha": "dzl", +"Dzando": "dzn", +"Dzongkha": "dzo", +"Karenggapa": "eaa", +"Beginci": "ebc", +"Ebughu": "ebg", +"Eastern Bontok": "ebk", +"Teke-Ebo": "ebo", +"Ebrié": "ebr", +"Embu": "ebu", +"Eteocretan": "ecr", +"EcuadorianSign Language": "ecs", +"Eteocypriot": "ecy", +"E": "eee", +"Efai": "efa", +"Efe": "efe", +"Efik": "efi", +"Ega": "ega", +"Emilian": "egl", +"Eggon": "ego", +"Egyptian(Ancient)": "egy", +"Miyakubo Sign Language": "ehs", +"Ehueun": "ehu", +"Eipomek": "eip", +"Eitiep": "eit", +"Askopan": "eiv", +"Ejamat": "eja", +"Ekajuk": "eka", +"Ekit": "eke", +"Ekari": "ekg", +"Eki": "eki", +"Standard Estonian": "ekk", +"Kol": "ekl", +"Elip": "ekm", +"Koti": "eko", +"Ekpeye": "ekp", +"Yace": "ekr", +"EasternKayah": "eky", +"Elepi": "ele", +"ElHugeirat": "elh", +"Nding": "eli", +"Elkei": "elk", +"Modern Greek (1453-)": "ell", +"Eleme": "elm", +"El Molo": "elo", +"Elu": "elu", +"Elamite": "elx", +"Emai-Iuleha-Ora": "ema", +"Embaloh": "emb", +"Emerillon": "eme", +"EasternMeohang": "emg", +"Mussau-Emira": "emi", +"EasternManinkakan": "emk", +"Mamulique": "emm", +"Eman": "emn", +"Northern Emberá": "emp", +"Eastern Minyag": "emq", +"PacificGulf Yupik": "ems", +"EasternMuria": "emu", +"Emplawas": "emw", +"Erromintxela": "emx", +"EpigraphicMayan": "emy", +"Mbessa": "emz", +"Apali": "ena", +"Markweeta": "enb", +"En": "enc", +"Ende": "end", +"ForestEnets": "enf", +"English": "eng", +"TundraEnets": "enh", +"Enlhet": "enl", +"Middle English (1100-1500)": "enm", +"Engenni": "enn", +"Enggano": "eno", +"Enga": "enq", +"Emumu": "enr", +"Enu": "enu", +"Enwan(Edu State)": "env", +"Enwan (Akwa Ibom State)": "enw", +"Enxet": "enx", +"Beti(Côte d'Ivoire)": "eot", +"Epie": "epi", +"Esperanto": "epo", +"Eravallan": "era", +"Sie": "erg", +"Eruwa": "erh", +"Ogea": "eri", +"SouthEfate": "erk", +"Horpa": "ero", +"Erre": "err", +"Ersu": "ers", +"Eritai": "ert", +"Erokwanas": "erw", +"EseEjja": "ese", +"Aheri Gondi": "esg", +"Eshtehardi": "esh", +"North Alaskan Inupiatun": "esi", +"Northwest Alaska Inupiatun": "esk", +"Egypt Sign Language": "esl", +"Esuma": "esm", +"Salvadoran Sign Language": "esn", +"EstonianSign Language": "eso", +"Esselen": "esq", +"Central Siberian Yupik": "ess", +"Estonian": "est", +"Central Yupik": "esu", +"Eskayan": "esy", +"Etebi": "etb", +"Etchemin": "etc", +"EthiopianSign Language": "eth", +"Eton(Vanuatu)": "etn", +"Eton(Cameroon)": "eto", +"Edolo": "etr", +"Yekhee": "ets", +"Etruscan": "ett", +"Ejagham": "etu", +"Eten": "etx", +"Semimi": "etz", +"Basque": "eus", +"Even": "eve", +"Uvbie": "evh", +"Evenki": "evn", +"Ewe": "ewe", +"Ewondo": "ewo", +"Extremaduran": "ext", +"Eyak": "eya", +"Keiyo": "eyo", +"Ezaa": "eza", +"Uzekwe": "eze", +"Fasu": "faa", +"Fa D'ambu": "fab", +"Wagi": "fad", +"Fagani": "faf", +"Finongan": "fag", +"Baissa Fali": "fah", +"Faiwol": "fai", +"Faita": "faj", +"Fang(Cameroon)": "fak", +"SouthFali": "fal", +"Fam": "fam", +"Fang (Equatorial Guinea)": "fan", +"Faroese": "fao", +"Palor": "fap", +"Fataleka": "far", +"Persian": "fas", +"Fanti": "fat", +"Fayu": "fau", +"Fala": "fax", +"SouthwesternFars": "fay", +"Northwestern Fars": "faz", +"WestAlbay Bikol": "fbl", +"Quebec Sign Language": "fcs", +"Feroge": "fer", +"FoiaFoia": "ffi", +"MaasinaFulfulde": "ffm", +"Fongoro": "fgr", +"Nobiin": "fia", +"Fyer": "fie", +"Faifi": "fif", +"Fijian": "fij", +"Filipino": "fil", +"Finnish": "fin", +"Fipa": "fip", +"Firan": "fir", +"TornedalenFinnish": "fit", +"Fiwaga": "fiw", +"Kirya-Konzəl": "fkk", +"KvenFinnish": "fkv", +"Kalispel-Pendd'Oreille": "fla", +"Foau": "flh", +"Fali": "fli", +"NorthFali": "fll", +"Flinders Island": "fln", +"Fuliiru": "flr", +"Tsotsitaal": "fly", +"Fe'fe'": "fmp", +"Far Western Muria": "fmu", +"Fanbak": "fnb", +"Fanagalo": "fng", +"Fania": "fni", +"Foodo": "fod", +"Foi": "foi", +"Foma": "fom", +"Fon": "fon", +"Fore": "for", +"Siraya": "fos", +"FernandoPo Creole English": "fpe", +"Fas": "fqs", +"French": "fra", +"CajunFrench": "frc", +"Fordata": "frd", +"Frankish": "frk", +"Middle French (ca. 1400-1600)": "frm", +"OldFrench (842-ca. 1400)": "fro", +"Arpitan": "frp", +"Forak": "frq", +"NorthernFrisian": "frr", +"EasternFrisian": "frs", +"Fortsenal": "frt", +"WesternFrisian": "fry", +"FinnishSign Language": "fse", +"FrenchSign Language": "fsl", +"Finland-Swedish Sign Language": "fss", +"AdamawaFulfulde": "fub", +"Pulaar": "fuc", +"EastFutuna": "fud", +"BorguFulfulde": "fue", +"Pular": "fuf", +"Western Niger Fulfulde": "fuh", +"Bagirmi Fulfulde": "fui", +"Ko": "fuj", +"Fulah": "ful", +"Fum": "fum", +"Fulniô": "fun", +"Central-EasternNiger Fulfulde": "fuq", +"Friulian": "fur", +"Futuna-Aniwa": "fut", +"Furu": "fuu", +"NigerianFulfulde": "fuv", +"Fuyug": "fuy", +"Fur": "fvr", +"Fwâi": "fwa", +"Fwe": "fwe", +"Ga": "gaa", +"Gabri": "gab", +"MixedGreat Andamanese": "gac", +"Gaddang": "gad", +"Guarequena": "gae", +"Gende": "gaf", +"Gagauz": "gag", +"Alekano": "gah", +"Borei": "gai", +"Gadsup": "gaj", +"Gamkonora": "gak", +"Galoli": "gal", +"Kandawo": "gam", +"GanChinese": "gan", +"Gants": "gao", +"Gal": "gap", +"Gata'": "gaq", +"Galeya": "gar", +"AdiwasiGarasia": "gas", +"Kenati": "gat", +"MudhiliGadaba": "gau", +"Nobonob": "gaw", +"Borana-Arsi-GujiOromo": "gax", +"Gayo": "gay", +"West Central Oromo": "gaz", +"Gbaya(Central African Republic)": "gba", +"Kaytetye": "gbb", +"Karadjeri": "gbd", +"Niksek": "gbe", +"Gaikundi": "gbf", +"Gbanziri": "gbg", +"Defi Gbe": "gbh", +"Galela": "gbi", +"BodoGadaba": "gbj", +"Gaddi": "gbk", +"Gamit": "gbl", +"Garhwali": "gbm", +"Mo'da": "gbn", +"NorthernGrebo": "gbo", +"Gbaya-Bossangoa": "gbp", +"Gbaya-Bozoum": "gbq", +"Gbagyi": "gbr", +"GbesiGbe": "gbs", +"Gagadu": "gbu", +"Gbanu": "gbv", +"Gabi-Gabi": "gbw", +"EasternXwla Gbe": "gbx", +"Gbari": "gby", +"ZoroastrianDari": "gbz", +"Mali": "gcc", +"Ganggalida": "gcd", +"Galice": "gce", +"Guadeloupean Creole French": "gcf", +"Grenadian Creole English": "gcl", +"Gaina": "gcn", +"GuianeseCreole French": "gcr", +"Colonia Tovar German": "gct", +"Gade Lohar": "gda", +"Pottangi Ollar Gadaba": "gdb", +"GuguBadhun": "gdc", +"Gedaged": "gdd", +"Gude": "gde", +"Guduf-Gava": "gdf", +"Ga'dang": "gdg", +"Gadjerawang": "gdh", +"Gundi": "gdi", +"Gurdjar": "gdj", +"Gadang": "gdk", +"Dirasha": "gdl", +"Laal": "gdm", +"Umanakaina": "gdn", +"Ghodoberi": "gdo", +"Mehri": "gdq", +"Wipi": "gdr", +"Ghandruk Sign Language": "gds", +"Kungardutyi": "gdt", +"Gudu": "gdu", +"Godwari": "gdx", +"Geruma": "gea", +"Kire": "geb", +"GbolooGrebo": "gec", +"Gade": "ged", +"Gerai": "gef", +"Gengle": "geg", +"HutteriteGerman": "geh", +"Gebe": "gei", +"Gen": "gej", +"Yiwom": "gek", +"Kag-Fer-Jiir-Koor-Ror-Us-Zuksun": "gel", +"Geme": "geq", +"Geser-Gorom": "ges", +"Eviya": "gev", +"Gera": "gew", +"Garre": "gex", +"Enya": "gey", +"Geez": "gez", +"Patpatar": "gfk", +"Gafat": "gft", +"Gao": "gga", +"Gbii": "ggb", +"Gugadj": "ggd", +"Guragone": "gge", +"Gurgula": "ggg", +"Kungarakany": "ggk", +"Ganglau": "ggl", +"Gitua": "ggt", +"Gagu": "ggu", +"Gogodala": "ggw", +"Ghadamès": "gha", +"Hiberno-ScottishGaelic": "ghc", +"Southern Ghale": "ghe", +"Northern Ghale": "ghh", +"Geko Karen": "ghk", +"Ghulfan": "ghl", +"Ghanongga": "ghn", +"Ghomara": "gho", +"Ghera": "ghr", +"Guhu-Samane": "ghs", +"KutangGhale": "ght", +"Kitja": "gia", +"Gibanawa": "gib", +"Gail": "gic", +"Gidar": "gid", +"Gaɓogbo": "gie", +"Goaria": "gig", +"Githabul": "gih", +"Girirra": "gii", +"Gilbertese": "gil", +"Gimi (Eastern Highlands)": "gim", +"Hinukh": "gin", +"Gimi(West New Britain)": "gip", +"GreenGelao": "giq", +"RedGelao": "gir", +"North Giziga": "gis", +"Gitxsan": "git", +"Mulao": "giu", +"WhiteGelao": "giw", +"Gilima": "gix", +"Giyug": "giy", +"South Giziga": "giz", +"Kachi Koli": "gjk", +"Gunditjmara": "gjm", +"Gonja": "gjn", +"Gurindji Kriol": "gjr", +"Gujari": "gju", +"Guya": "gka", +"Magɨ (Madang Province)": "gkd", +"Ndai": "gke", +"Gokana": "gkn", +"Kok-Nar": "gko", +"Guinea Kpelle": "gkp", +"ǂUngkue": "gku", +"ScottishGaelic": "gla", +"Belning": "glb", +"Bon Gula": "glc", +"Nanai": "gld", +"Irish": "gle", +"Galician": "glg", +"Northwest Pashayi": "glh", +"GulaIro": "glj", +"Gilaki": "glk", +"Garlali": "gll", +"Galambu": "glo", +"Glaro-Twabo": "glr", +"Gula (Chad)": "glu", +"Manx": "glv", +"Glavda": "glw", +"Gule": "gly", +"Gambera": "gma", +"Gula'alaa": "gmb", +"Mághdì": "gmd", +"Magɨyi": "gmg", +"Middle High German (ca. 1050-1500)": "gmh", +"MiddleLow German": "gml", +"Gbaya-Mbodomo": "gmm", +"Gimnime": "gmn", +"Mirning": "gmr", +"Gumalu": "gmu", +"Gamo": "gmv", +"Magoma": "gmx", +"MycenaeanGreek": "gmy", +"Mgbolizhia": "gmz", +"Kaansa": "gna", +"Gangte": "gnb", +"Guanche": "gnc", +"Zulgo-Gemzek": "gnd", +"Ganang": "gne", +"Ngangam": "gng", +"Lere": "gnh", +"Gooniyandi": "gni", +"Ngen": "gnj", +"//Gana": "gnk", +"Gangulu": "gnl", +"Ginuman": "gnm", +"Gumatj": "gnn", +"NorthernGondi": "gno", +"Gana": "gnq", +"GurengGureng": "gnr", +"Guntai": "gnt", +"Gnau": "gnu", +"WesternBolivian Guaraní": "gnw", +"Ganzi": "gnz", +"Guro": "goa", +"Playero": "gob", +"Gorakor": "goc", +"Godié": "god", +"Gongduk": "goe", +"Gofa": "gof", +"Gogo": "gog", +"Old High German (ca. 750-1050)": "goh", +"Gobasi": "goi", +"Gowlan": "goj", +"Gowli": "gok", +"Gola": "gol", +"GoanKonkani": "gom", +"Gondi": "gon", +"GoneDau": "goo", +"Yeretuar": "gop", +"Gorap": "goq", +"Gorontalo": "gor", +"Gronings": "gos", +"Gothic": "got", +"Gavar": "gou", +"Gorowa": "gow", +"Gobu": "gox", +"Goundo": "goy", +"Gozarkhani": "goz", +"Gupa-Abawa": "gpa", +"Ghanaian Pidgin English": "gpe", +"Taiap": "gpn", +"Ga'anda": "gqa", +"Guiqiong": "gqi", +"Guana(Brazil)": "gqn", +"Gor": "gqr", +"Qau": "gqu", +"Rajput Garasia": "gra", +"Grebo": "grb", +"AncientGreek (to 1453)": "grc", +"Guruntum-Mbaaru": "grd", +"Madi": "grg", +"Gbiri-Niragu": "grh", +"Ghari": "gri", +"SouthernGrebo": "grj", +"KotaMarudu Talantang": "grm", +"Guarani": "grn", +"Groma": "gro", +"Gorovu": "grq", +"Taznatit": "grr", +"Gresi": "grs", +"Garo": "grt", +"Kistane": "gru", +"Central Grebo": "grv", +"Gweda": "grw", +"Guriaso": "grx", +"Barclayville Grebo": "gry", +"Guramalum": "grz", +"GhanaianSign Language": "gse", +"German Sign Language": "gsg", +"Gusilay": "gsl", +"Guatemalan Sign Language": "gsm", +"Gusan": "gsn", +"SouthwestGbaya": "gso", +"Wasembo": "gsp", +"Greek Sign Language": "gss", +"SwissGerman": "gsw", +"Guató": "gta", +"Aghu-Tharnggala": "gtu", +"Shiki": "gua", +"Guajajára": "gub", +"Wayuu": "guc", +"YocobouéDida": "gud", +"Gurinji": "gue", +"Gupapuyngu": "guf", +"ParaguayanGuaraní": "gug", +"Guahibo": "guh", +"EasternBolivian Guaraní": "gui", +"Gujarati": "guj", +"Gumuz": "guk", +"Sea Island Creole English": "gul", +"Guambiano": "gum", +"MbyáGuaraní": "gun", +"Guayabero": "guo", +"Gunwinggu": "gup", +"Aché": "guq", +"Farefare": "gur", +"GuineanSign Language": "gus", +"Maléku Jaíka": "gut", +"Yanomamö": "guu", +"Gun": "guw", +"Gourmanchéma": "gux", +"Gusii": "guz", +"Guana (Paraguay)": "gva", +"Guanano": "gvc", +"Duwet": "gve", +"Golin": "gvf", +"Guajá": "gvj", +"Gulay": "gvl", +"Gurmana": "gvm", +"Kuku-Yalanji": "gvn", +"GaviãoDo Jiparaná": "gvo", +"Pará Gavião": "gvp", +"WesternGurung": "gvr", +"Gumawana": "gvs", +"Guyani": "gvy", +"Mbato": "gwa", +"Gwa": "gwb", +"Kalami": "gwc", +"Gawwada": "gwd", +"Gweno": "gwe", +"Gowro": "gwf", +"Moo": "gwg", +"Gwichʼin": "gwi", +"/Gwi": "gwj", +"Awngthim": "gwm", +"Gwandara": "gwn", +"Gwere": "gwr", +"Gawar-Bati": "gwt", +"Guwamu": "gwu", +"Kwini": "gww", +"Gua": "gwx", +"WèSouthern": "gxx", +"NorthwestGbaya": "gya", +"Garus": "gyb", +"Kayardild": "gyd", +"Gyem": "gye", +"Gungabula": "gyf", +"Gbayi": "gyg", +"Gyele": "gyi", +"Gayil": "gyl", +"Ngäbere": "gym", +"Guyanese Creole English": "gyn", +"Gyalsumdo": "gyo", +"Guarayu": "gyr", +"Gunya": "gyy", +"Geji": "gyz", +"Ganza": "gza", +"Gazi": "gzi", +"Gane": "gzn", +"Han": "haa", +"Hanoi Sign Language": "hab", +"Gurani": "hac", +"Hatam": "had", +"EasternOromo": "hae", +"HaiphongSign Language": "haf", +"Hanga": "hag", +"Hahon": "hah", +"Haida": "hai", +"Hajong": "haj", +"HakkaChinese": "hak", +"Halang": "hal", +"Hewa": "ham", +"Hangaza": "han", +"Hakö": "hao", +"Hupla": "hap", +"Ha": "haq", +"Harari": "har", +"Haisla": "has", +"Haitian": "hat", +"Hausa": "hau", +"Havu": "hav", +"Hawaiian": "haw", +"SouthernHaida": "hax", +"Haya": "hay", +"Hazaragi": "haz", +"Hamba": "hba", +"Huba": "hbb", +"Heiban": "hbn", +"Ancient Hebrew": "hbo", +"Serbo-Croatian": "hbs", +"Habu": "hbu", +"AndamanCreole Hindi": "hca", +"Huichol": "hch", +"NorthernHaida": "hdn", +"Honduras Sign Language": "hds", +"Hadiyya": "hdy", +"Northern Qiandong Miao": "hea", +"Hebrew": "heb", +"Herdé": "hed", +"Helong": "heg", +"Hehe": "heh", +"Heiltsuk": "hei", +"Hemba": "hem", +"Herero": "her", +"Hai//om": "hgm", +"Haigwai": "hgw", +"HoiaHoia": "hhi", +"Kerak": "hhr", +"Hoyahoya": "hhy", +"Lamang": "hia", +"Hibito": "hib", +"Hidatsa": "hid", +"Fiji Hindi": "hif", +"Kamwe": "hig", +"Pamosu": "hih", +"Hinduri": "hii", +"Hijuk": "hij", +"Seit-Kaitetu": "hik", +"Hiligaynon": "hil", +"Hindi": "hin", +"Tsoa": "hio", +"Himarimã": "hir", +"Hittite": "hit", +"Hiw": "hiw", +"Hixkaryána": "hix", +"Haji": "hji", +"Kahe": "hka", +"Hunde": "hke", +"Khah": "hkh", +"Hunjara-KainaKe": "hkk", +"Mel-Khaonh": "hkn", +"HongKong Sign Language": "hks", +"Halia": "hla", +"Halbi": "hlb", +"HalangDoan": "hld", +"Hlersu": "hle", +"NgaLa": "hlt", +"HieroglyphicLuwian": "hlu", +"Southern Mashan Hmong": "hma", +"HumburiSenni Songhay": "hmb", +"CentralHuishui Hmong": "hmc", +"Large Flowery Miao": "hmd", +"Eastern Huishui Hmong": "hme", +"HmongDon": "hmf", +"Southwestern Guiyang Hmong": "hmg", +"SouthwesternHuishui Hmong": "hmh", +"NorthernHuishui Hmong": "hmi", +"Ge": "hmj", +"Maek": "hmk", +"Luopohe Hmong": "hml", +"Central Mashan Hmong": "hmm", +"Hmong": "hmn", +"HiriMotu": "hmo", +"Northern Mashan Hmong": "hmp", +"EasternQiandong Miao": "hmq", +"Hmar": "hmr", +"SouthernQiandong Miao": "hms", +"Hamtai": "hmt", +"Hamap": "hmu", +"HmongDô": "hmv", +"Western Mashan Hmong": "hmw", +"Southern Guiyang Hmong": "hmy", +"Hmong Shua": "hmz", +"Mina(Cameroon)": "hna", +"Southern Hindko": "hnd", +"Chhattisgarhi": "hne", +"Hungu": "hng", +"//Ani": "hnh", +"Hani": "hni", +"HmongNjua": "hnj", +"Hanunoo": "hnn", +"Northern Hindko": "hno", +"CaribbeanHindustani": "hns", +"Hung": "hnu", +"Hoava": "hoa", +"Mari(Madang Province)": "hob", +"Ho": "hoc", +"Holma": "hod", +"Horom": "hoe", +"Hobyót": "hoh", +"Holikachuk": "hoi", +"Hadothi": "hoj", +"Holu": "hol", +"Homa": "hom", +"Holoholo": "hoo", +"Hopi": "hop", +"Horo": "hor", +"Ho Chi Minh City Sign Language": "hos", +"Hote": "hot", +"Hovongan": "hov", +"Honi": "how", +"Holiya": "hoy", +"Hozo": "hoz", +"Hpon": "hpo", +"Hawai'i Pidgin Sign Language": "hps", +"Hrangkhol": "hra", +"Niwer Mil": "hrc", +"Hre": "hre", +"Haruku": "hrk", +"HornedMiao": "hrm", +"Haroi": "hro", +"Nhirrpi": "hrp", +"Hértevin": "hrt", +"Hruso": "hru", +"Croatian": "hrv", +"Warwar Feni": "hrw", +"Hunsrik": "hrx", +"Harzani": "hrz", +"UpperSorbian": "hsb", +"HungarianSign Language": "hsh", +"Hausa Sign Language": "hsl", +"XiangChinese": "hsn", +"Harsusi": "hss", +"Hoti": "hti", +"Minica Huitoto": "hto", +"Hadza": "hts", +"Hitu": "htu", +"MiddleHittite": "htx", +"Huambisa": "hub", +"=/Hua": "huc", +"Huaulu": "hud", +"San Francisco Del Mar Huave": "hue", +"Humene": "huf", +"Huachipaeri": "hug", +"Huilliche": "huh", +"Huli": "hui", +"Northern Guiyang Hmong": "huj", +"Hulung": "huk", +"Hula": "hul", +"Hungana": "hum", +"Hungarian": "hun", +"Hu": "huo", +"Hupa": "hup", +"Tsat": "huq", +"Halkomelem": "hur", +"Huastec": "hus", +"Humla": "hut", +"MuruiHuitoto": "huu", +"San Mateo Del Mar Huave": "huv", +"Hukumina": "huw", +"NüpodeHuitoto": "hux", +"Hulaulá": "huy", +"Hunzib": "huz", +"HaitianVodoun Culture Language": "hvc", +"San Dionisio Del Mar Huave": "hve", +"Haveke": "hvk", +"Sabu": "hvn", +"Santa María Del Mar Huave": "hvv", +"Wané": "hwa", +"Hawai'iCreole English": "hwc", +"Hwana": "hwo", +"Hya": "hya", +"Armenian": "hye", +"Western Armenian": "hyw", +"Iaai": "iai", +"Iatmul": "ian", +"Purari": "iar", +"Iban": "iba", +"Ibibio": "ibb", +"Iwaidja": "ibd", +"Akpes": "ibe", +"Ibanag": "ibg", +"Bih": "ibh", +"Ibaloi": "ibl", +"Agoi": "ibm", +"Ibino": "ibn", +"Igbo": "ibo", +"Ibuoro": "ibr", +"Ibu": "ibu", +"Ibani": "iby", +"Ede Ica": "ica", +"Etkywan": "ich", +"Icelandic Sign Language": "icl", +"Islander Creole English": "icr", +"Idakho-Isukha-Tiriki": "ida", +"Indo-Portuguese": "idb", +"Idon": "idc", +"EdeIdaca": "idd", +"Idere": "ide", +"Idi": "idi", +"Ido": "ido", +"Indri": "idr", +"Idesa": "ids", +"Idaté": "idt", +"Idoma": "idu", +"AmganadIfugao": "ifa", +"BatadIfugao": "ifb", +"Ifè": "ife", +"Ifo": "iff", +"TuwaliIfugao": "ifk", +"Teke-Fuumu": "ifm", +"Mayoyao Ifugao": "ifu", +"Keley-IKallahan": "ify", +"Ebira": "igb", +"Igede": "ige", +"Igana": "igg", +"Igala": "igl", +"Kanggape": "igm", +"Ignaciano": "ign", +"Isebe": "igo", +"Interglossa": "igs", +"Igwe": "igw", +"IhaBased Pidgin": "ihb", +"Ihievbe": "ihi", +"Iha": "ihp", +"Bidhawal": "ihw", +"SichuanYi": "iii", +"Thiin": "iin", +"Izon": "ijc", +"Biseni": "ije", +"EdeIje": "ijj", +"Kalabari": "ijn", +"SoutheastIjo": "ijs", +"Eastern Canadian Inuktitut": "ike", +"Iko": "iki", +"Ika": "ikk", +"Ikulu": "ikl", +"Olulumo-Ikom": "iko", +"Ikpeshi": "ikp", +"Ikaranggal": "ikr", +"Inuit Sign Language": "iks", +"Western Canadian Inuktitut": "ikt", +"Inuktitut": "iku", +"Iku-Gora-Ankwa": "ikv", +"Ikwere": "ikw", +"Ik": "ikx", +"Ikizu": "ikz", +"Ile Ape": "ila", +"Ila": "ilb", +"Interlingue": "ile", +"Garig-Ilgar": "ilg", +"IliTurki": "ili", +"Ilongot": "ilk", +"Iranun (Malaysia)": "ilm", +"Iloko": "ilo", +"Iranun (Philippines)": "ilp", +"International Sign": "ils", +"Ili'uun": "ilu", +"Ilue": "ilv", +"MalaMalasar": "ima", +"Anamgura": "imi", +"Miluk": "iml", +"Imonda": "imn", +"Imbongu": "imo", +"Imroing": "imr", +"Marsian": "ims", +"Milyan": "imy", +"Interlingua (International Auxiliary Language Association)": "ina", +"Inga": "inb", +"Indonesian": "ind", +"Degexit'an": "ing", +"Ingush": "inh", +"JungleInga": "inj", +"IndonesianSign Language": "inl", +"Minaean": "inm", +"Isinai": "inn", +"Inoke-Yate": "ino", +"Iñapari": "inp", +"Indian Sign Language": "ins", +"Intha": "int", +"Ineseño": "inz", +"Inor": "ior", +"Tuma-Irumu": "iou", +"Iowa-Oto": "iow", +"Ipili": "ipi", +"Inupiaq": "ipk", +"Ipiko": "ipo", +"Iquito": "iqu", +"Ikwo": "iqw", +"Iresim": "ire", +"Irarutu": "irh", +"Irigwe": "iri", +"Iraqw": "irk", +"Irántxe": "irn", +"Ir": "irr", +"Irula": "iru", +"Kamberau": "irx", +"Iraya": "iry", +"Isabi": "isa", +"Isconahua": "isc", +"Isnag": "isd", +"ItalianSign Language": "ise", +"IrishSign Language": "isg", +"Esan": "ish", +"Nkem-Nkum": "isi", +"Ishkashimi": "isk", +"Icelandic": "isl", +"Masimasi": "ism", +"Isanzu": "isn", +"Isoko": "iso", +"Israeli Sign Language": "isr", +"Istriot": "ist", +"Isu (Menchum Division)": "isu", +"Italian": "ita", +"BinonganItneg": "itb", +"Southern Tidung": "itd", +"Itene": "ite", +"InlaodItneg": "iti", +"Judeo-Italian": "itk", +"Itelmen": "itl", +"ItuMbon Uzo": "itm", +"Itonama": "ito", +"Iteri": "itr", +"Isekiri": "its", +"MaengItneg": "itt", +"Itawit": "itv", +"Ito": "itw", +"Itik": "itx", +"MoyadanItneg": "ity", +"Itzá": "itz", +"IuMien": "ium", +"Ibatan": "ivb", +"Ivatan": "ivv", +"I-Wak": "iwk", +"Iwam": "iwm", +"Iwur": "iwo", +"Sepik Iwam": "iws", +"Ixcatec": "ixc", +"Ixil": "ixl", +"Iyayu": "iya", +"Mesaka": "iyo", +"Yaka (Congo)": "iyx", +"Ingrian": "izh", +"Izere": "izr", +"Izii": "izz", +"Jamamadí": "jaa", +"Hyam": "jab", +"Popti'": "jac", +"Jahanka": "jad", +"Yabem": "jae", +"Jara": "jaf", +"JahHut": "jah", +"Zazao": "jaj", +"Jakun": "jak", +"Yalahatan": "jal", +"Jamaican Creole English": "jam", +"Jandai": "jan", +"Yanyuwa": "jao", +"Yaqay": "jaq", +"NewCaledonian Javanese": "jas", +"Jakati": "jat", +"Yaur": "jau", +"Javanese": "jav", +"JambiMalay": "jax", +"Yan-nhangu": "jay", +"Jawe": "jaz", +"Judeo-Berber": "jbe", +"Badjiri": "jbi", +"Arandai": "jbj", +"Barikewa": "jbk", +"Bijim": "jbm", +"Nafusi": "jbn", +"Lojban": "jbo", +"Jofotek-Bromnya": "jbr", +"Jabutí": "jbt", +"JukunTakum": "jbu", +"Yawijibaya": "jbw", +"JamaicanCountry Sign Language": "jcs", +"Krymchak": "jct", +"Jad": "jda", +"Jadgali": "jdg", +"Judeo-Tat": "jdt", +"Jebero": "jeb", +"Jerung": "jee", +"Jeh": "jeh", +"Yei": "jei", +"JeriKuo": "jek", +"Yelmek": "jel", +"Dza": "jen", +"Jere": "jer", +"Manem": "jet", +"JonkorBourmataguil": "jeu", +"Ngbee": "jgb", +"Judeo-Georgian": "jge", +"Gwak": "jgk", +"Ngomba": "jgo", +"Jehai": "jhi", +"JhankotSign Language": "jhs", +"Jina": "jia", +"Jibu": "jib", +"Tol": "jic", +"Bu": "jid", +"Jilbe": "jie", +"Djingili": "jig", +"Shangzhai": "jih", +"Jiiddu": "jii", +"Jilim": "jil", +"Jimi (Cameroon)": "jim", +"Jiamao": "jio", +"Guanyinqiao": "jiq", +"Jita": "jit", +"YouleJinuo": "jiu", +"Shuar": "jiv", +"BuyuanJinuo": "jiy", +"Jejueo": "jje", +"Bankal": "jjr", +"Kaera": "jka", +"Mobwa Karen": "jkm", +"Kubo": "jko", +"Paku Karen": "jkp", +"Koro (India)": "jkr", +"Amami Koniya Sign Language": "jks", +"Labir": "jku", +"Ngile": "jle", +"JamaicanSign Language": "jls", +"Dima": "jma", +"Zumbun": "jmb", +"Machame": "jmc", +"Yamdena": "jmd", +"Jimi(Nigeria)": "jmi", +"Jumli": "jml", +"Makuri Naga": "jmn", +"Kamara": "jmr", +"Mashi (Nigeria)": "jms", +"Mouwase": "jmw", +"WesternJuxtlahuaca Mixtec": "jmx", +"Jangshung": "jna", +"Jandavra": "jnd", +"Yangman": "jng", +"Janji": "jni", +"Yemsa": "jnj", +"Rawat": "jnl", +"Jaunsari": "jns", +"Joba": "job", +"Wojenaka": "jod", +"Jogi": "jog", +"Jorá": "jor", +"Jordanian Sign Language": "jos", +"Jowulu": "jow", +"Jewish Palestinian Aramaic": "jpa", +"Japanese": "jpn", +"Judeo-Persian": "jpr", +"Jaqaru": "jqr", +"Jarai": "jra", +"Judeo-Arabic": "jrb", +"Jiru": "jrr", +"Jorto": "jrt", +"Japrería": "jru", +"JapaneseSign Language": "jsl", +"Júma": "jua", +"Wannu": "jub", +"Jurchen": "juc", +"Worodougou": "jud", +"Hõne": "juh", +"Ngadjuri": "jui", +"Wapan": "juk", +"Jirel": "jul", +"Jumjum": "jum", +"Juang": "jun", +"Jiba": "juo", +"Hupdë": "jup", +"Jurúna": "jur", +"Jumla Sign Language": "jus", +"Jutish": "jut", +"Ju": "juu", +"Wãpha": "juw", +"Juray": "juy", +"Javindo": "jvd", +"Caribbean Javanese": "jvn", +"Jwira-Pepesa": "jwi", +"Jiarong": "jya", +"Judeo-Yemeni Arabic": "jye", +"Jaya": "jyy", +"Kara-Kalpak": "kaa", +"Kabyle": "kab", +"Kachin": "kac", +"Kadara": "kad", +"Ketangalan": "kae", +"Katso": "kaf", +"Kajaman": "kag", +"Kara (Central African Republic)": "kah", +"Karekare": "kai", +"Jju": "kaj", +"Kayapa Kallahan": "kak", +"Kalaallisut": "kal", +"Kamba(Kenya)": "kam", +"Kannada": "kan", +"Xaasongaxango": "kao", +"Bezhta": "kap", +"Capanahua": "kaq", +"Kashmiri": "kas", +"Georgian": "kat", +"Kanuri": "kau", +"Katukína": "kav", +"Kawi": "kaw", +"Kao": "kax", +"Kamayurá": "kay", +"Kazakh": "kaz", +"Kalarko": "kba", +"Kaxuiâna": "kbb", +"Kadiwéu": "kbc", +"Kabardian": "kbd", +"Kanju": "kbe", +"Khamba": "kbg", +"Camsá": "kbh", +"Kaptiau": "kbi", +"Kari": "kbj", +"GrassKoiari": "kbk", +"Kanembu": "kbl", +"Iwal": "kbm", +"Kare (Central African Republic)": "kbn", +"Keliko": "kbo", +"Kabiyè": "kbp", +"Kamano": "kbq", +"Kafa": "kbr", +"Kande": "kbs", +"Abadi": "kbt", +"Kabutra": "kbu", +"Dera(Indonesia)": "kbv", +"Kaiep": "kbw", +"Ap Ma": "kbx", +"MangaKanuri": "kby", +"Duhwa": "kbz", +"Khanty": "kca", +"Kawacha": "kcb", +"Lubila": "kcc", +"NgkâlmpwKanum": "kcd", +"Kaivi": "kce", +"Ukaan": "kcf", +"Tyap": "kcg", +"Vono": "kch", +"Kamantan": "kci", +"Kobiana": "kcj", +"Kalanga": "kck", +"Kela (Papua New Guinea)": "kcl", +"Gula(Central African Republic)": "kcm", +"Nubi": "kcn", +"Kinalakna": "kco", +"Kanga": "kcp", +"Kamo": "kcq", +"Katla": "kcr", +"Koenoem": "kcs", +"Kaian": "kct", +"Kami(Tanzania)": "kcu", +"Kete": "kcv", +"Kabwari": "kcw", +"Kachama-Ganjule": "kcx", +"Korandje": "kcy", +"Konongo": "kcz", +"Worimi": "kda", +"Kutu": "kdc", +"Yankunytjatjara": "kdd", +"Makonde": "kde", +"Mamusi": "kdf", +"Seba": "kdg", +"Tem": "kdh", +"Kumam": "kdi", +"Karamojong": "kdj", +"Numee": "kdk", +"Tsikimba": "kdl", +"Kagoma": "kdm", +"Kunda": "kdn", +"Kaningdon-Nindem": "kdp", +"Koch": "kdq", +"Karaim": "kdr", +"Kuy": "kdt", +"Kadaru": "kdu", +"Koneraw": "kdw", +"Kam": "kdx", +"Keder": "kdy", +"Kwaja": "kdz", +"Kabuverdianu": "kea", +"Kélé": "keb", +"Keiga": "kec", +"Kerewe": "ked", +"EasternKeres": "kee", +"Kpessi": "kef", +"Tese": "keg", +"Keak": "keh", +"Kei": "kei", +"Kadar": "kej", +"Kekchí": "kek", +"Kela (Democratic Republic of Congo)": "kel", +"Kemak": "kem", +"Kenyang": "ken", +"Kakwa": "keo", +"Kaikadi": "kep", +"Kamar": "keq", +"Kera": "ker", +"Kugbo": "kes", +"Ket": "ket", +"Akebu": "keu", +"Kanikkaran": "kev", +"WestKewa": "kew", +"Kukna": "kex", +"Kupia": "key", +"Kukele": "kez", +"Kodava": "kfa", +"NorthwesternKolami": "kfb", +"Konda-Dora": "kfc", +"KorraKoraga": "kfd", +"Kota(India)": "kfe", +"Koya": "kff", +"Kudiya": "kfg", +"Kurichiya": "kfh", +"KannadaKurumba": "kfi", +"Kemiehua": "kfj", +"Kinnauri": "kfk", +"Kung": "kfl", +"Khunsari": "kfm", +"Kuk": "kfn", +"Koro(Côte d'Ivoire)": "kfo", +"Korwa": "kfp", +"Korku": "kfq", +"Kachchi": "kfr", +"Bilaspuri": "kfs", +"Kanjari": "kft", +"Katkari": "kfu", +"Kurmukar": "kfv", +"Kharam Naga": "kfw", +"KulluPahari": "kfx", +"Kumaoni": "kfy", +"Koromfé": "kfz", +"Koyaga": "kga", +"Kawe": "kgb", +"Komering": "kge", +"Kube": "kgf", +"Kusunda": "kgg", +"SelangorSign Language": "kgi", +"Gamale Kham": "kgj", +"Kaiwá": "kgk", +"Kunggari": "kgl", +"Karipúna": "kgm", +"Karingani": "kgn", +"Krongo": "kgo", +"Kaingang": "kgp", +"Kamoro": "kgq", +"Abun": "kgr", +"Kumbainggar": "kgs", +"Somyev": "kgt", +"Kobol": "kgu", +"Karas": "kgv", +"KaronDori": "kgw", +"Kamaru": "kgx", +"Kyerung": "kgy", +"Khasi": "kha", +"Lü": "khb", +"Tukang Besi North": "khc", +"Bädi Kanum": "khd", +"Korowai": "khe", +"Khuen": "khf", +"KhamsTibetan": "khg", +"Kehu": "khh", +"Kuturmi": "khj", +"HalhMongolian": "khk", +"Lusi": "khl", +"CentralKhmer": "khm", +"Khandesi": "khn", +"Khotanese": "kho", +"Kapori": "khp", +"KoyraChiini Songhay": "khq", +"Kharia": "khr", +"Kasua": "khs", +"Khamti": "kht", +"Nkhumbi": "khu", +"Khvarshi": "khv", +"Khowar": "khw", +"Kanu": "khx", +"Kele (Democratic Republic of Congo)": "khy", +"Keapara": "khz", +"Kim": "kia", +"Koalib": "kib", +"Kickapoo": "kic", +"Koshin": "kid", +"Kibet": "kie", +"Eastern Parbate Kham": "kif", +"Kimaama": "kig", +"Kilmeri": "kih", +"Kitsai": "kii", +"Kilivila": "kij", +"Kikuyu": "kik", +"Kariya": "kil", +"Karagas": "kim", +"Kinyarwanda": "kin", +"Kiowa": "kio", +"Sheshi Kham": "kip", +"Kosadle": "kiq", +"Kirghiz": "kir", +"Kis": "kis", +"Agob": "kit", +"Kirmanjki (individual language)": "kiu", +"Kimbu": "kiv", +"NortheastKiwai": "kiw", +"KhiamniunganNaga": "kix", +"Kirikiri": "kiy", +"Kisi": "kiz", +"Mlap": "kja", +"Q'anjob'al": "kjb", +"CoastalKonjo": "kjc", +"SouthernKiwai": "kjd", +"Kisar": "kje", +"Khmu": "kjg", +"Khakas": "kjh", +"Zabana": "kji", +"Khinalugh": "kjj", +"Highland Konjo": "kjk", +"WesternParbate Kham": "kjl", +"Kháng": "kjm", +"Kunjen": "kjn", +"HarijanKinnauri": "kjo", +"PwoEastern Karen": "kjp", +"WesternKeres": "kjq", +"Kurudu": "kjr", +"East Kewa": "kjs", +"PhraePwo Karen": "kjt", +"Kashaya": "kju", +"Kaikavian Literary Language": "kjv", +"Ramopa": "kjx", +"Erave": "kjy", +"Bumthangkha": "kjz", +"Kakanda": "kka", +"Kwerisa": "kkb", +"Odoodee": "kkc", +"Kinuku": "kkd", +"Kakabe": "kke", +"KalaktangMonpa": "kkf", +"MabakaValley Kalinga": "kkg", +"Khün": "kkh", +"Kagulu": "kki", +"Kako": "kkj", +"Kokota": "kkk", +"KosarekYale": "kkl", +"Kiong": "kkm", +"Kon Keu": "kkn", +"Karko": "kko", +"Gugubera": "kkp", +"Kaiku": "kkq", +"Kir-Balar": "kkr", +"Giiwo": "kks", +"Koi": "kkt", +"Tumi": "kku", +"Kangean": "kkv", +"Teke-Kukuya": "kkw", +"Kohin": "kkx", +"Guguyimidjir": "kky", +"Kaska": "kkz", +"Klamath-Modoc": "kla", +"Kiliwa": "klb", +"Kolbila": "klc", +"Gamilaraay": "kld", +"Kulung (Nepal)": "kle", +"Kendeje": "klf", +"Tagakaulo": "klg", +"Weliki": "klh", +"Kalumpang": "kli", +"TurkicKhalaj": "klj", +"Kono(Nigeria)": "klk", +"KaganKalagan": "kll", +"Migum": "klm", +"Kalenjin": "kln", +"Kapya": "klo", +"Kamasa": "klp", +"Rumu": "klq", +"Khaling": "klr", +"Kalasha": "kls", +"Nukna": "klt", +"Klao": "klu", +"Maskelynes": "klv", +"Lindu": "klw", +"Koluwawa": "klx", +"Kalao": "kly", +"Kabola": "klz", +"Konni": "kma", +"Kimbundu": "kmb", +"Southern Dong": "kmc", +"MajukayangKalinga": "kmd", +"Bakole": "kme", +"Kare (Papua New Guinea)": "kmf", +"Kâte": "kmg", +"Kalam": "kmh", +"Kami(Nigeria)": "kmi", +"KumarbhagPaharia": "kmj", +"LimosKalinga": "kmk", +"LowerTanudan Kalinga": "kml", +"Kom(India)": "kmm", +"Awtuw": "kmn", +"Kwoma": "kmo", +"Gimme": "kmp", +"Kwama": "kmq", +"NorthernKurdish": "kmr", +"Kamasau": "kms", +"Kemtuik": "kmt", +"Kanite": "kmu", +"KaripúnaCreole French": "kmv", +"Komo(Democratic Republic of Congo)": "kmw", +"Waboda": "kmx", +"Koma": "kmy", +"KhorasaniTurkish": "kmz", +"Dera(Nigeria)": "kna", +"LubuaganKalinga": "knb", +"Central Kanuri": "knc", +"Konda": "knd", +"Kankanaey": "kne", +"Mankanya": "knf", +"Koongo": "kng", +"Kanufi": "kni", +"Western Kanjobal": "knj", +"Kuranko": "knk", +"Keninjal": "knl", +"Kanamarí": "knm", +"Konkani(individual language)": "knn", +"Kono (Sierra Leone)": "kno", +"Kwanja": "knp", +"Kintaq": "knq", +"Kaningra": "knr", +"Kensiu": "kns", +"Panoan Katukína": "knt", +"Kono (Guinea)": "knu", +"Tabo": "knv", +"Kung-Ekoka": "knw", +"Kendayan": "knx", +"Kanyok": "kny", +"Kalamsé": "knz", +"Konomala": "koa", +"Kpati": "koc", +"Kodi": "kod", +"Kacipo-Balesi": "koe", +"Kubi": "kof", +"Cogui": "kog", +"Koyo": "koh", +"Komi-Permyak": "koi", +"Konkani (macrolanguage)": "kok", +"Kol(Papua New Guinea)": "kol", +"Komi": "kom", +"Kongo": "kon", +"Konzo": "koo", +"Kwato": "kop", +"Kota(Gabon)": "koq", +"Korean": "kor", +"Kosraean": "kos", +"Lagwan": "kot", +"Koke": "kou", +"Kudu-Camo": "kov", +"Kugama": "kow", +"Koyukon": "koy", +"Korak": "koz", +"Kutto": "kpa", +"MulluKurumba": "kpb", +"Curripaco": "kpc", +"Koba": "kpd", +"Kpelle": "kpe", +"Komba": "kpf", +"Kapingamarangi": "kpg", +"Kplang": "kph", +"Kofei": "kpi", +"Karajá": "kpj", +"Kpan": "kpk", +"Kpala": "kpl", +"Koho": "kpm", +"Kepkiriwát": "kpn", +"Ikposo": "kpo", +"Korupun-Sela": "kpq", +"Korafe-Yegha": "kpr", +"Tehit": "kps", +"Karata": "kpt", +"Kafoa": "kpu", +"Komi-Zyrian": "kpv", +"Kobon": "kpw", +"Mountain Koiali": "kpx", +"Koryak": "kpy", +"Kupsabiny": "kpz", +"Mum": "kqa", +"Kovai": "kqb", +"Doromu-Koki": "kqc", +"KoySanjaq Surat": "kqd", +"Kalagan": "kqe", +"Kakabai": "kqf", +"Khe": "kqg", +"Kisankasa": "kqh", +"Koitabu": "kqi", +"Koromira": "kqj", +"KotafonGbe": "kqk", +"Kyenele": "kql", +"Khisa": "kqm", +"Kaonde": "kqn", +"Eastern Krahn": "kqo", +"Kimré": "kqp", +"Krenak": "kqq", +"Kimaragang": "kqr", +"NorthernKissi": "kqs", +"KliasRiver Kadazan": "kqt", +"Seroa": "kqu", +"Okolod": "kqv", +"Kandas": "kqw", +"Mser": "kqx", +"Koorete": "kqy", +"Korana": "kqz", +"Kumhali": "kra", +"Karkin": "krb", +"Karachay-Balkar": "krc", +"Kairui-Midiki": "krd", +"Panará": "kre", +"Koro(Vanuatu)": "krf", +"Kurama": "krh", +"Krio": "kri", +"Kinaray-A": "krj", +"Kerek": "krk", +"Karelian": "krl", +"Sapo": "krn", +"Korop": "krp", +"Kru'ng 2": "krr", +"Gbaya (Sudan)": "krs", +"TumariKanuri": "krt", +"Kurukh": "kru", +"Kavet": "krv", +"WesternKrahn": "krw", +"Karon": "krx", +"Kryts": "kry", +"Sota Kanum": "krz", +"Shuwa-Zamani": "ksa", +"Shambala": "ksb", +"Southern Kalinga": "ksc", +"Kuanua": "ksd", +"Kuni": "kse", +"Bafia": "ksf", +"Kusaghe": "ksg", +"Kölsch": "ksh", +"Krisa": "ksi", +"Uare": "ksj", +"Kansa": "ksk", +"Kumalu": "ksl", +"Kumba": "ksm", +"Kasiguranin": "ksn", +"Kofa": "kso", +"Kaba": "ksp", +"Kwaami": "ksq", +"Borong": "ksr", +"SouthernKisi": "kss", +"Winyé": "kst", +"Khamyang": "ksu", +"Kusu": "ksv", +"S'gawKaren": "ksw", +"Kedang": "ksx", +"KhariaThar": "ksy", +"Kodaku": "ksz", +"Katua": "kta", +"Kambaata": "ktb", +"Kholok": "ktc", +"Kokata": "ktd", +"Nubri": "kte", +"Kwami": "ktf", +"Kalkutung": "ktg", +"Karanga": "kth", +"NorthMuyu": "kti", +"Plapo Krumen": "ktj", +"Kaniet": "ktk", +"Koroshi": "ktl", +"Kurti": "ktm", +"Karitiâna": "ktn", +"Kuot": "kto", +"Kaduo": "ktp", +"Katabaga": "ktq", +"South Muyu": "kts", +"Ketum": "ktt", +"Kituba(Democratic Republic of Congo)": "ktu", +"Eastern Katu": "ktv", +"Kato": "ktw", +"Kaxararí": "ktx", +"Kango(Bas-Uélé District)": "kty", +"Ju/'hoan": "ktz", +"Kuanyama": "kua", +"Kutep": "kub", +"Kwinsu": "kuc", +"'Auhelawa": "kud", +"Kuman": "kue", +"WesternKatu": "kuf", +"Kupa": "kug", +"Kushi": "kuh", +"Kuikúro-Kalapálo": "kui", +"Kuria": "kuj", +"Kepo'": "kuk", +"Kulere": "kul", +"Kumyk": "kum", +"Kunama": "kun", +"Kumukio": "kuo", +"Kunimaipa": "kup", +"Karipuna": "kuq", +"Kurdish": "kur", +"Kusaal": "kus", +"Kutenai": "kut", +"Upper Kuskokwim": "kuu", +"Kur": "kuv", +"Kpagua": "kuw", +"Kukatja": "kux", +"Kuuku-Ya'u": "kuy", +"Kunza": "kuz", +"Bagvalal": "kva", +"Kubu": "kvb", +"Kove": "kvc", +"Kui (Indonesia)": "kvd", +"Kalabakan": "kve", +"Kabalai": "kvf", +"Kuni-Boazi": "kvg", +"Komodo": "kvh", +"Kwang": "kvi", +"Psikye": "kvj", +"KoreanSign Language": "kvk", +"BrekKaren": "kvl", +"Kendem": "kvm", +"BorderKuna": "kvn", +"Dobel": "kvo", +"Kompane": "kvp", +"GebaKaren": "kvq", +"Kerinci": "kvr", +"Lahta Karen": "kvt", +"Yinbaw Karen": "kvu", +"Kola": "kvv", +"Wersing": "kvw", +"ParkariKoli": "kvx", +"Yintale Karen": "kvy", +"Tsakwambo": "kvz", +"Dâw": "kwa", +"Kwa": "kwb", +"Likwala": "kwc", +"Kwaio": "kwd", +"Kwerba": "kwe", +"Kwara'ae": "kwf", +"SaraKaba Deme": "kwg", +"Kowiai": "kwh", +"Awa-Cuaiquer": "kwi", +"Kwanga": "kwj", +"Kwakiutl": "kwk", +"Kofyar": "kwl", +"Kwambi": "kwm", +"Kwangali": "kwn", +"Kwomtari": "kwo", +"Kodia": "kwp", +"Kwer": "kwr", +"Kwese": "kws", +"Kwesten": "kwt", +"Kwakum": "kwu", +"SaraKaba Náà": "kwv", +"Kwinti": "kww", +"Khirwar": "kwx", +"San Salvador Kongo": "kwy", +"Kwadi": "kwz", +"Kairiru": "kxa", +"Krobu": "kxb", +"Konso": "kxc", +"Brunei": "kxd", +"ManumanawKaren": "kxf", +"Karo (Ethiopia)": "kxh", +"Keningau Murut": "kxi", +"Kulfa": "kxj", +"ZayeinKaren": "kxk", +"Northern Khmer": "kxm", +"Kanowit-Tanjong Melanau": "kxn", +"Kanoé": "kxo", +"Wadiyara Koli": "kxp", +"SmärkyKanum": "kxq", +"Koro (Papua New Guinea)": "kxr", +"Kangjia": "kxs", +"Koiwat": "kxt", +"Kuvi": "kxv", +"Konai": "kxw", +"Likuba": "kxx", +"Kayong": "kxy", +"Kerewo": "kxz", +"Kwaya": "kya", +"ButbutKalinga": "kyb", +"Kyaka": "kyc", +"Karey": "kyd", +"Krache": "kye", +"Kouya": "kyf", +"Keyagana": "kyg", +"Karok": "kyh", +"Kiput": "kyi", +"Karao": "kyj", +"Kamayo": "kyk", +"Kalapuya": "kyl", +"Kpatili": "kym", +"NorthernBinukidnon": "kyn", +"Kelon": "kyo", +"Kang": "kyp", +"Kenga": "kyq", +"Kuruáya": "kyr", +"BaramKayan": "kys", +"Kayagar": "kyt", +"Western Kayah": "kyu", +"Kayort": "kyv", +"Kudmali": "kyw", +"Rapoisi": "kyx", +"Kambaira": "kyy", +"Kayabí": "kyz", +"WesternKaraboro": "kza", +"Kaibobo": "kzb", +"Bondoukou Kulango": "kzc", +"Kadai": "kzd", +"Kosena": "kze", +"Da'aKaili": "kzf", +"Kikai": "kzg", +"Kelabit": "kzi", +"Kazukuru": "kzk", +"Kayeli": "kzl", +"Kais": "kzm", +"Kokola": "kzn", +"Kaningi": "kzo", +"Kaidipang": "kzp", +"Kaike": "kzq", +"Karang": "kzr", +"SugutDusun": "kzs", +"Kayupulau": "kzu", +"Komyandaret": "kzv", +"Karirí-Xocó": "kzw", +"Kamarian": "kzx", +"Kango (Tshopo District)": "kzy", +"Kalabra": "kzz", +"Southern Subanen": "laa", +"LinearA": "lab", +"Lacandon": "lac", +"Ladino": "lad", +"Pattani": "lae", +"Lafofa": "laf", +"Langi": "lag", +"Lahnda": "lah", +"Lambya": "lai", +"Lango(Uganda)": "laj", +"Laka (Nigeria)": "lak", +"Lalia": "lal", +"Lamba": "lam", +"Laru": "lan", +"Lao": "lao", +"Laka(Chad)": "lap", +"Qabiao": "laq", +"Larteh": "lar", +"Lama (Togo)": "las", +"Latin": "lat", +"Laba": "lau", +"Latvian": "lav", +"Lauje": "law", +"Tiwa": "lax", +"Lama(Myanmar)": "lay", +"Aribwatsa": "laz", +"Label": "lbb", +"Lakkia": "lbc", +"Lak": "lbe", +"Tinani": "lbf", +"Laopang": "lbg", +"La'bi": "lbi", +"Ladakhi": "lbj", +"CentralBontok": "lbk", +"Libon Bikol": "lbl", +"Lodhi": "lbm", +"Lamet": "lbn", +"Laven": "lbo", +"Wampar": "lbq", +"Northern Lorung": "lbr", +"Libyan Sign Language": "lbs", +"Lachi": "lbt", +"Labu": "lbu", +"Lavatbura-Lamusong": "lbv", +"Tolaki": "lbw", +"Lawangan": "lbx", +"Lamu-Lamu": "lby", +"Lardil": "lbz", +"Legenyem": "lcc", +"Lola": "lcd", +"Loncong": "lce", +"Lubu": "lcf", +"Luchazi": "lch", +"Lisela": "lcl", +"Tungag": "lcm", +"WesternLawa": "lcp", +"Luhu": "lcq", +"Lisabata-Nuniali": "lcs", +"Kla-Dan": "lda", +"Idun": "ldb", +"Luri": "ldd", +"Lenyima": "ldg", +"Lamja-Dengsa-Tola": "ldh", +"Laari": "ldi", +"Lemoro": "ldj", +"Leelau": "ldk", +"Kaan": "ldl", +"Landoma": "ldm", +"Láadan": "ldn", +"Loo": "ldo", +"Tso": "ldp", +"Lufu": "ldq", +"Lega-Shabunda": "lea", +"Lala-Bisa": "leb", +"Leco": "lec", +"Lendu": "led", +"Lyélé": "lee", +"Lelemi": "lef", +"Lenje": "leh", +"Lemio": "lei", +"Lengola": "lej", +"Leipon": "lek", +"Lele(Democratic Republic of Congo)": "lel", +"Nomaande": "lem", +"Lenca": "len", +"Leti(Cameroon)": "leo", +"Lepcha": "lep", +"Lembena": "leq", +"Lenkau": "ler", +"Lese": "les", +"Lesing-Gelimi": "let", +"Kara (Papua New Guinea)": "leu", +"Lamma": "lev", +"LedoKaili": "lew", +"Luang": "lex", +"Lemolang": "ley", +"Lezghian": "lez", +"Lefa": "lfa", +"Lingua Franca Nova": "lfn", +"Lungga": "lga", +"Laghu": "lgb", +"Lugbara": "lgg", +"Laghuu": "lgh", +"Lengilu": "lgi", +"Lingarak": "lgk", +"Wala": "lgl", +"Lega-Mwenga": "lgm", +"Opuuo": "lgn", +"Logba": "lgq", +"Lengo": "lgr", +"Pahi": "lgt", +"Longgu": "lgu", +"Ligenza": "lgz", +"Laha (Viet Nam)": "lha", +"Laha(Indonesia)": "lhh", +"LahuShi": "lhi", +"LahulLohar": "lhl", +"Lhomi": "lhm", +"Lahanan": "lhn", +"Lhokpu": "lhp", +"Mlahsö": "lhs", +"Lo-Toga": "lht", +"Lahu": "lhu", +"West-CentralLimba": "lia", +"Likum": "lib", +"Hlai": "lic", +"Nyindrou": "lid", +"Likila": "lie", +"Limbu": "lif", +"Ligbi": "lig", +"Lihir": "lih", +"Ligurian": "lij", +"Lika": "lik", +"Lillooet": "lil", +"Limburgan": "lim", +"Lingala": "lin", +"Liki": "lio", +"Sekpele": "lip", +"Libido": "liq", +"Liberian English": "lir", +"Lisu": "lis", +"Lithuanian": "lit", +"Logorik": "liu", +"Liv": "liv", +"Col": "liw", +"Liabuku": "lix", +"Banda-Bambari": "liy", +"Libinza": "liz", +"Golpa": "lja", +"Rampi": "lje", +"Laiyolo": "lji", +"Li'o": "ljl", +"LampungApi": "ljp", +"Yirandali": "ljw", +"Yuru": "ljx", +"Lakalei": "lka", +"Kabras": "lkb", +"Kucong": "lkc", +"Lakondê": "lkd", +"Kenyi": "lke", +"Lakha": "lkh", +"Laki": "lki", +"Remun": "lkj", +"Laeko-Libuat": "lkl", +"Kalaamaya": "lkm", +"Lakon": "lkn", +"Khayo": "lko", +"Päri": "lkr", +"Kisa": "lks", +"Lakota": "lkt", +"Kungkari": "lku", +"Lokoya": "lky", +"Lala-Roba": "lla", +"Lolo": "llb", +"Lele (Guinea)": "llc", +"Ladin": "lld", +"Lele(Papua New Guinea)": "lle", +"Hermit": "llf", +"Lole": "llg", +"Lamu": "llh", +"Teke-Laali": "lli", +"Ladji Ladji": "llj", +"Lelak": "llk", +"Lilau": "lll", +"Lasalimu": "llm", +"Lele (Chad)": "lln", +"NorthEfate": "llp", +"Lolak": "llq", +"LithuanianSign Language": "lls", +"Lau": "llu", +"Lauan": "llx", +"EastLimba": "lma", +"Merei": "lmb", +"Limilngan": "lmc", +"Lumun": "lmd", +"Pévé": "lme", +"SouthLembata": "lmf", +"Lamogai": "lmg", +"Lambichhong": "lmh", +"Lombi": "lmi", +"WestLembata": "lmj", +"Lamkang": "lmk", +"Hano": "lml", +"Lambadi": "lmn", +"Lombard": "lmo", +"Limbum": "lmp", +"Lamatuka": "lmq", +"Lamalera": "lmr", +"Lamenu": "lmu", +"Lomaiviti": "lmv", +"LakeMiwok": "lmw", +"Laimbue": "lmx", +"Lamboya": "lmy", +"Langbashe": "lna", +"Mbalanhu": "lnb", +"Lundayeh": "lnd", +"Langobardic": "lng", +"Lanoh": "lnh", +"Daantanai'": "lni", +"Leningitij": "lnj", +"SouthCentral Banda": "lnl", +"Langam": "lnm", +"Lorediakarkar": "lnn", +"Lango (Sudan)": "lno", +"Lamnso'": "lns", +"Longuda": "lnu", +"Lanima": "lnw", +"Lonzo": "lnz", +"Loloda": "loa", +"Lobi": "lob", +"Inonhan": "loc", +"Saluan": "loe", +"Logol": "lof", +"Logo": "log", +"Narim": "loh", +"Loma(Côte d'Ivoire)": "loi", +"Lou": "loj", +"Loko": "lok", +"Mongo": "lol", +"Loma (Liberia)": "lom", +"MalawiLomwe": "lon", +"Lombo": "loo", +"Lopa": "lop", +"Lobala": "loq", +"Téén": "lor", +"Loniu": "los", +"Otuho": "lot", +"Louisiana Creole French": "lou", +"Lopi": "lov", +"TampiasLobu": "low", +"Loun": "lox", +"Lowa": "loy", +"Lozi": "loz", +"Lelepa": "lpa", +"Lepki": "lpe", +"LongPhuri Naga": "lpn", +"Lipo": "lpo", +"Lopit": "lpx", +"RaraBakati'": "lra", +"NorthernLuri": "lrc", +"Laurentian": "lre", +"Laragia": "lrg", +"Marachi": "lri", +"Loarki": "lrk", +"Lari": "lrl", +"Marama": "lrm", +"Lorang": "lrn", +"Laro": "lro", +"Southern Lorung": "lrr", +"Larantuka Malay": "lrt", +"Larevat": "lrv", +"Lemerig": "lrz", +"Lasgerdi": "lsa", +"Burundian Sign Language": "lsb", +"Lishana Deni": "lsd", +"Lusengo": "lse", +"Lish": "lsh", +"Lashi": "lsi", +"Latvian Sign Language": "lsl", +"Saamia": "lsm", +"Tibetan Sign Language": "lsn", +"LaosSign Language": "lso", +"Panamanian Sign Language": "lsp", +"Aruop": "lsr", +"Lasi": "lss", +"Trinidad and Tobago Sign Language": "lst", +"Sivia Sign Language": "lsv", +"MauritianSign Language": "lsy", +"LateMiddle Chinese": "ltc", +"Latgalian": "ltg", +"Thur": "lth", +"Leti(Indonesia)": "lti", +"Latundê": "ltn", +"Tsotso": "lto", +"Tachoni": "lts", +"Latu": "ltu", +"Luxembourgish": "ltz", +"Luba-Lulua": "lua", +"Luba-Katanga": "lub", +"Aringa": "luc", +"Ludian": "lud", +"Luvale": "lue", +"Laua": "luf", +"Ganda": "lug", +"Luiseno": "lui", +"Luna": "luj", +"Lunanakha": "luk", +"Olu'bo": "lul", +"Luimbi": "lum", +"Lunda": "lun", +"Luo(Kenya and Tanzania)": "luo", +"Lumbu": "lup", +"Lucumi": "luq", +"Laura": "lur", +"Lushai": "lus", +"Lushootseed": "lut", +"Lumba-Yakkha": "luu", +"Luwati": "luv", +"Luo (Cameroon)": "luw", +"Luyia": "luy", +"SouthernLuri": "luz", +"Maku'a": "lva", +"Lavi": "lvi", +"Lavukaleve": "lvk", +"StandardLatvian": "lvs", +"Levuka": "lvu", +"Lwalu": "lwa", +"LewoEleng": "lwe", +"Wanga": "lwg", +"White Lachi": "lwh", +"EasternLawa": "lwl", +"Laomian": "lwm", +"Luwo": "lwo", +"Malawian Sign Language": "lws", +"Lewotobi": "lwt", +"Lawu": "lwu", +"Lewo": "lww", +"Lakurumau": "lxm", +"Layakha": "lya", +"Lyngngam": "lyg", +"Luyana": "lyn", +"LiteraryChinese": "lzh", +"Litzlitz": "lzl", +"LeinongNaga": "lzn", +"Laz": "lzz", +"San Jerónimo Tecóatl Mazatec": "maa", +"Yutanduchi Mixtec": "mab", +"Madurese": "mad", +"Bo-Rukul": "mae", +"Mafa": "maf", +"Magahi": "mag", +"Marshallese": "mah", +"Maithili": "mai", +"JalapaDe Díaz Mazatec": "maj", +"Makasar": "mak", +"Malayalam": "mal", +"Mam": "mam", +"Mandingo": "man", +"Chiquihuitlán Mazatec": "maq", +"Marathi": "mar", +"Masai": "mas", +"SanFrancisco Matlatzinca": "mat", +"HuautlaMazatec": "mau", +"Sateré-Mawé": "mav", +"Mampruli": "maw", +"North Moluccan Malay": "max", +"CentralMazahua": "maz", +"Higaonon": "mba", +"WesternBukidnon Manobo": "mbb", +"Macushi": "mbc", +"DibabawonManobo": "mbd", +"Molale": "mbe", +"BabaMalay": "mbf", +"Mangseng": "mbh", +"Ilianen Manobo": "mbi", +"Nadëb": "mbj", +"Malol": "mbk", +"Maxakalí": "mbl", +"Ombamba": "mbm", +"Macaguán": "mbn", +"Mbo(Cameroon)": "mbo", +"Malayo": "mbp", +"Maisin": "mbq", +"Nukak Makú": "mbr", +"SaranganiManobo": "mbs", +"MatigsalugManobo": "mbt", +"Mbula-Bwazza": "mbu", +"Mbulungish": "mbv", +"Maring": "mbw", +"Mari (East Sepik Province)": "mbx", +"Memoni": "mby", +"Amoltepec Mixtec": "mbz", +"Maca": "mca", +"Machiguenga": "mcb", +"Bitur": "mcc", +"Sharanahua": "mcd", +"Itundujia Mixtec": "mce", +"Matsés": "mcf", +"Mapoyo": "mcg", +"Maquiritari": "mch", +"Mese": "mci", +"Mvanip": "mcj", +"Mbunda": "mck", +"Macaguaje": "mcl", +"MalaccanCreole Portuguese": "mcm", +"Masana": "mcn", +"Coatlán Mixe": "mco", +"Makaa": "mcp", +"Ese": "mcq", +"Menya": "mcr", +"Mambai": "mcs", +"Mengisa": "mct", +"Cameroon Mambila": "mcu", +"Minanibai": "mcv", +"Mawa (Chad)": "mcw", +"Mpiemo": "mcx", +"SouthWatut": "mcy", +"Mawan": "mcz", +"Mada (Nigeria)": "mda", +"Morigi": "mdb", +"Male(Papua New Guinea)": "mdc", +"Mbum": "mdd", +"Maba(Chad)": "mde", +"Moksha": "mdf", +"Massalat": "mdg", +"Maguindanaon": "mdh", +"Mamvu": "mdi", +"Mangbetu": "mdj", +"Mangbutu": "mdk", +"Maltese Sign Language": "mdl", +"Mayogo": "mdm", +"Mbati": "mdn", +"Mbala": "mdp", +"Mbole": "mdq", +"Mandar": "mdr", +"Maria (Papua New Guinea)": "mds", +"Mbere": "mdt", +"Mboko": "mdu", +"Santa Lucía Monteverde Mixtec": "mdv", +"Mbosi": "mdw", +"Dizin": "mdx", +"Male (Ethiopia)": "mdy", +"Suruí Do Pará": "mdz", +"Menka": "mea", +"Ikobi-Mena": "meb", +"Mara": "mec", +"Melpa": "med", +"Mengen": "mee", +"Megam": "mef", +"Southwestern Tlaxiaco Mixtec": "meh", +"Midob": "mei", +"Meyah": "mej", +"Mekeo": "mek", +"Central Melanau": "mel", +"Mangala": "mem", +"Mende(Sierra Leone)": "men", +"Kedah Malay": "meo", +"Miriwung": "mep", +"Merey": "meq", +"Meru": "mer", +"Masmaje": "mes", +"Mato": "met", +"Motu": "meu", +"Mann": "mev", +"Maaka": "mew", +"Hassaniyya": "mey", +"Menominee": "mez", +"PattaniMalay": "mfa", +"Bangka": "mfb", +"Mba": "mfc", +"Mendankwe-Nkwen": "mfd", +"Morisyen": "mfe", +"Naki": "mff", +"Mixifore": "mfg", +"Matal": "mfh", +"Wandala": "mfi", +"Mefele": "mfj", +"NorthMofu": "mfk", +"Putai": "mfl", +"MarghiSouth": "mfm", +"Cross River Mbembe": "mfn", +"Mbe": "mfo", +"MakassarMalay": "mfp", +"Moba": "mfq", +"Marithiel": "mfr", +"Mexican Sign Language": "mfs", +"Mokerang": "mft", +"Mbwela": "mfu", +"Mandjak": "mfv", +"Mulaha": "mfw", +"Melo": "mfx", +"Mayo": "mfy", +"Mabaan": "mfz", +"Middle Irish (900-1200)": "mga", +"Mararit": "mgb", +"Morokodo": "mgc", +"Moru": "mgd", +"Mango": "mge", +"Maklew": "mgf", +"Mpongmpong": "mgg", +"Makhuwa-Meetto": "mgh", +"Lijili": "mgi", +"Abureni": "mgj", +"Mawes": "mgk", +"Maleu-Kilenge": "mgl", +"Mambae": "mgm", +"Mbangi": "mgn", +"Meta'": "mgo", +"Eastern Magar": "mgp", +"Malila": "mgq", +"Mambwe-Lungu": "mgr", +"Manda (Tanzania)": "mgs", +"Mongol": "mgt", +"Mailu": "mgu", +"Matengo": "mgv", +"Matumbi": "mgw", +"Mbunga": "mgy", +"Mbugwe": "mgz", +"Manda(India)": "mha", +"Mahongwe": "mhb", +"Mocho": "mhc", +"Mbugu": "mhd", +"Besisi": "mhe", +"Mamaa": "mhf", +"Margu": "mhg", +"Ma'di": "mhi", +"Mogholi": "mhj", +"Mungaka": "mhk", +"Mauwake": "mhl", +"Makhuwa-Moniga": "mhm", +"Mócheno": "mhn", +"Mashi(Zambia)": "mho", +"BalineseMalay": "mhp", +"Mandan": "mhq", +"EasternMari": "mhr", +"Buru(Indonesia)": "mhs", +"Mandahuaca": "mht", +"Digaro-Mishmi": "mhu", +"Mbukushu": "mhw", +"Maru": "mhx", +"Ma'anyan": "mhy", +"Mor(Mor Islands)": "mhz", +"Miami": "mia", +"AtatláhucaMixtec": "mib", +"Mi'kmaq": "mic", +"Mandaic": "mid", +"OcotepecMixtec": "mie", +"Mofu-Gudur": "mif", +"San Miguel El Grande Mixtec": "mig", +"ChayucoMixtec": "mih", +"ChigmecatitlánMixtec": "mii", +"Abar": "mij", +"Mikasuki": "mik", +"Peñoles Mixtec": "mil", +"Alacatlatzala Mixtec": "mim", +"Minangkabau": "min", +"Pinotepa Nacional Mixtec": "mio", +"Apasco-ApoalaMixtec": "mip", +"Mískito": "miq", +"IsthmusMixe": "mir", +"Uncoded languages": "mis", +"Southern Puebla Mixtec": "mit", +"CacaloxtepecMixtec": "miu", +"Akoye": "miw", +"MixtepecMixtec": "mix", +"AyutlaMixtec": "miy", +"CoatzospanMixtec": "miz", +"Makalero": "mjb", +"SanJuan Colorado Mixtec": "mjc", +"Northwest Maidu": "mjd", +"Muskum": "mje", +"Tu": "mjg", +"Mwera(Nyasa)": "mjh", +"KimMun": "mji", +"Mawak": "mjj", +"Matukar": "mjk", +"Mandeali": "mjl", +"Medebur": "mjm", +"Ma (Papua New Guinea)": "mjn", +"Malankuravan": "mjo", +"Malapandaram": "mjp", +"Malaryan": "mjq", +"Malavedan": "mjr", +"Miship": "mjs", +"Sauria Paharia": "mjt", +"Manna-Dora": "mju", +"Mannan": "mjv", +"Karbi": "mjw", +"Mahali": "mjx", +"Mahican": "mjy", +"Majhi": "mjz", +"Mbre": "mka", +"MalPaharia": "mkb", +"Siliput": "mkc", +"Macedonian": "mkd", +"Mawchi": "mke", +"Miya": "mkf", +"Mak (China)": "mkg", +"Dhatki": "mki", +"Mokilese": "mkj", +"Byep": "mkk", +"Mokole": "mkl", +"Moklen": "mkm", +"Kupang Malay": "mkn", +"MingangDoso": "mko", +"Moikodi": "mkp", +"BayMiwok": "mkq", +"Malas": "mkr", +"SilacayoapanMixtec": "mks", +"Vamale": "mkt", +"KonyankaManinka": "mku", +"Mafea": "mkv", +"Kituba (Congo)": "mkw", +"Kinamiging Manobo": "mkx", +"EastMakian": "mky", +"Makasae": "mkz", +"Malo": "mla", +"Mbule": "mlb", +"CaoLan": "mlc", +"Manambu": "mle", +"Mal": "mlf", +"Malagasy": "mlg", +"Mape": "mlh", +"Malimpung": "mli", +"Miltu": "mlj", +"Ilwana": "mlk", +"MaluaBay": "mll", +"Mulam": "mlm", +"Malango": "mln", +"Mlomp": "mlo", +"Bargam": "mlp", +"Western Maninkakan": "mlq", +"Vame": "mlr", +"Masalit": "mls", +"Maltese": "mlt", +"To'abaita": "mlu", +"Motlav": "mlv", +"Moloko": "mlw", +"Malfaxal": "mlx", +"Malaynon": "mlz", +"Mama": "mma", +"Momina": "mmb", +"MichoacánMazahua": "mmc", +"Maonan": "mmd", +"Mae": "mme", +"Mundat": "mmf", +"NorthAmbrym": "mmg", +"Mehináku": "mmh", +"Musar": "mmi", +"Majhwar": "mmj", +"Mukha-Dora": "mmk", +"ManMet": "mml", +"Maii": "mmm", +"Mamanwa": "mmn", +"ManggaBuang": "mmo", +"Siawi": "mmp", +"Musak": "mmq", +"WesternXiangxi Miao": "mmr", +"Malalamai": "mmt", +"Mmaala": "mmu", +"Miriti": "mmv", +"Emae": "mmw", +"Madak": "mmx", +"Migaama": "mmy", +"Mabaale": "mmz", +"Mbula": "mna", +"Muna": "mnb", +"Manchu": "mnc", +"Mondé": "mnd", +"Naba": "mne", +"Mundani": "mnf", +"Eastern Mnong": "mng", +"Mono(Democratic Republic of Congo)": "mnh", +"Manipuri": "mni", +"Munji": "mnj", +"Mandinka": "mnk", +"Tiale": "mnl", +"Mapena": "mnm", +"SouthernMnong": "mnn", +"MinBei Chinese": "mnp", +"Minriq": "mnq", +"Mono(USA)": "mnr", +"Mansi": "mns", +"Mer": "mnu", +"Rennell-Bellona": "mnv", +"Mon": "mnw", +"Manikion": "mnx", +"Manyawa": "mny", +"Moni": "mnz", +"Mwan": "moa", +"Mocoví": "moc", +"Mobilian": "mod", +"Montagnais": "moe", +"Mongondow": "mog", +"Mohawk": "moh", +"Mboi": "moi", +"Monzombo": "moj", +"Morori": "mok", +"Mangue": "mom", +"Mongolian": "mon", +"Monom": "moo", +"MopánMaya": "mop", +"Mor (Bomberai Peninsula)": "moq", +"Moro": "mor", +"Mossi": "mos", +"Barí": "mot", +"Mogum": "mou", +"Mohave": "mov", +"Moi(Congo)": "mow", +"Molima": "mox", +"Shekkacho": "moy", +"Mukulu": "moz", +"Mpoto": "mpa", +"Mullukmulluk": "mpb", +"Mangarayi": "mpc", +"Machinere": "mpd", +"Majang": "mpe", +"Marba": "mpg", +"Maung": "mph", +"Mpade": "mpi", +"MartuWangka": "mpj", +"Mbara(Chad)": "mpk", +"MiddleWatut": "mpl", +"Yosondúa Mixtec": "mpm", +"Mindiri": "mpn", +"Miu": "mpo", +"Migabac": "mpp", +"Matís": "mpq", +"Vangunu": "mpr", +"Dadibi": "mps", +"Mian": "mpt", +"Makuráp": "mpu", +"Mungkip": "mpv", +"Mapidian": "mpw", +"Misima-Paneati": "mpx", +"Mapia": "mpy", +"Mpi": "mpz", +"Maba(Indonesia)": "mqa", +"Mbuko": "mqb", +"Mangole": "mqc", +"Matepi": "mqe", +"Momuna": "mqf", +"Kota Bangun Kutai Malay": "mqg", +"TlazoyaltepecMixtec": "mqh", +"Mariri": "mqi", +"Mamasa": "mqj", +"RajahKabunsuwan Manobo": "mqk", +"Mbelime": "mql", +"SouthMarquesan": "mqm", +"Moronene": "mqn", +"Modole": "mqo", +"Manipa": "mqp", +"Minokok": "mqq", +"Mander": "mqr", +"West Makian": "mqs", +"Mok": "mqt", +"Mandari": "mqu", +"Mosimo": "mqv", +"Murupi": "mqw", +"Mamuju": "mqx", +"Manggarai": "mqy", +"Malasanga": "mqz", +"Mlabri": "mra", +"Marino": "mrb", +"Maricopa": "mrc", +"WesternMagar": "mrd", +"Martha'sVineyard Sign Language": "mre", +"Elseng": "mrf", +"Miri": "mrg", +"Mara Chin": "mrh", +"Maori": "mri", +"WesternMari": "mrj", +"Hmwaveke": "mrk", +"Mortlockese": "mrl", +"Merlav": "mrm", +"ChekeHolo": "mrn", +"Mru": "mro", +"Morouas": "mrp", +"NorthMarquesan": "mrq", +"Maria(India)": "mrr", +"Maragus": "mrs", +"Marghi Central": "mrt", +"Mono (Cameroon)": "mru", +"Mangareva": "mrv", +"Maranao": "mrw", +"Maremgi": "mrx", +"Mandaya": "mry", +"Marind": "mrz", +"Malay (macrolanguage)": "msa", +"Masbatenyo": "msb", +"SankaranManinka": "msc", +"Yucatec Maya Sign Language": "msd", +"Musey": "mse", +"Mekwei": "msf", +"Moraid": "msg", +"Masikoro Malagasy": "msh", +"SabahMalay": "msi", +"Ma (Democratic Republic of Congo)": "msj", +"Mansaka": "msk", +"Molof": "msl", +"AgusanManobo": "msm", +"Vurës": "msn", +"Mombum": "mso", +"Maritsauá": "msp", +"Caac": "msq", +"Mongolian Sign Language": "msr", +"WestMasela": "mss", +"Musom": "msu", +"Maslam": "msv", +"Mansoanka": "msw", +"Moresada": "msx", +"Aruamu": "msy", +"Momare": "msz", +"Cotabato Manobo": "mta", +"Anyin Morofo": "mtb", +"Munit": "mtc", +"Mualang": "mtd", +"Mono (Solomon Islands)": "mte", +"Murik (Papua New Guinea)": "mtf", +"Una": "mtg", +"Munggui": "mth", +"Maiwa (Papua New Guinea)": "mti", +"Moskona": "mtj", +"Mbe'": "mtk", +"Montol": "mtl", +"Mator": "mtm", +"Matagalpa": "mtn", +"Totontepec Mixe": "mto", +"WichíLhamtés Nocten": "mtp", +"Muong": "mtq", +"Mewari": "mtr", +"Yora": "mts", +"Mota": "mtt", +"TututepecMixtec": "mtu", +"Asaro'o": "mtv", +"SouthernBinukidnon": "mtw", +"TidaáMixtec": "mtx", +"Nabi": "mty", +"Mundang": "mua", +"Mubi": "mub", +"Mbu'": "muc", +"MednyjAleut": "mud", +"MediaLengua": "mue", +"Musgu": "mug", +"Mündü": "muh", +"Musi": "mui", +"Mabire": "muj", +"Mugom": "muk", +"Multiple languages": "mul", +"Maiwala": "mum", +"Nyong": "muo", +"Malvi": "mup", +"Eastern Xiangxi Miao": "muq", +"Murle": "mur", +"Creek": "mus", +"Western Muria": "mut", +"Yaaku": "muu", +"Muthuvan": "muv", +"Bo-Ung": "mux", +"Muyang": "muy", +"Mursi": "muz", +"Manam": "mva", +"Mattole": "mvb", +"Mamboru": "mvd", +"Marwari(Pakistan)": "mve", +"PeripheralMongolian": "mvf", +"Yucuañe Mixtec": "mvg", +"Mire": "mvh", +"Miyako": "mvi", +"Mekmek": "mvk", +"Mbara (Australia)": "mvl", +"Minaveha": "mvn", +"Marovo": "mvo", +"Duri": "mvp", +"Moere": "mvq", +"Marau": "mvr", +"Massep": "mvs", +"Mpotovoro": "mvt", +"Marfa": "mvu", +"TagalMurut": "mvv", +"Machinga": "mvw", +"Meoswar": "mvx", +"IndusKohistani": "mvy", +"Mesqan": "mvz", +"Mwatebu": "mwa", +"Juwal": "mwb", +"Are": "mwc", +"Mwera(Chimwera)": "mwe", +"Murrinh-Patha": "mwf", +"Aiklep": "mwg", +"Mouk-Aria": "mwh", +"Labo": "mwi", +"Kita Maninkakan": "mwk", +"Mirandese": "mwl", +"Sar": "mwm", +"Nyamwanga": "mwn", +"CentralMaewo": "mwo", +"KalaLagaw Ya": "mwp", +"MünChin": "mwq", +"Marwari": "mwr", +"Mwimbi-Muthambi": "mws", +"Moken": "mwt", +"Mittu": "mwu", +"Mentawai": "mwv", +"Hmong Daw": "mww", +"Moingi": "mwz", +"NorthwestOaxaca Mixtec": "mxa", +"TezoatlánMixtec": "mxb", +"Manyika": "mxc", +"Modang": "mxd", +"Mele-Fila": "mxe", +"Malgbe": "mxf", +"Mbangala": "mxg", +"Mvuba": "mxh", +"Mozarabic": "mxi", +"Miju-Mishmi": "mxj", +"Monumbo": "mxk", +"Maxi Gbe": "mxl", +"Meramera": "mxm", +"Moi(Indonesia)": "mxn", +"Mbowe": "mxo", +"TlahuitoltepecMixe": "mxp", +"Juquila Mixe": "mxq", +"Murik(Malaysia)": "mxr", +"HuitepecMixtec": "mxs", +"JamiltepecMixtec": "mxt", +"Mada(Cameroon)": "mxu", +"MetlatónocMixtec": "mxv", +"Namo": "mxw", +"Mahou": "mxx", +"Southeastern Nochixtlán Mixtec": "mxy", +"CentralMasela": "mxz", +"Burmese": "mya", +"Mbay": "myb", +"Mayeka": "myc", +"Myene": "mye", +"Bambassi": "myf", +"Manta": "myg", +"Makah": "myh", +"Mangayat": "myj", +"MamaraSenoufo": "myk", +"Moma": "myl", +"Me'en": "mym", +"Anfillo": "myo", +"Pirahã": "myp", +"Muniche": "myr", +"Mesmes": "mys", +"Mundurukú": "myu", +"Erzya": "myv", +"Muyuw": "myw", +"Masaaba": "myx", +"Macuna": "myy", +"Classical Mandaic": "myz", +"Santa María Zacatepec Mixtec": "mza", +"Tumzabt": "mzb", +"MadagascarSign Language": "mzc", +"Malimba": "mzd", +"Morawa": "mze", +"Monastic Sign Language": "mzg", +"Wichí Lhamtés Güisnay": "mzh", +"IxcatlánMazatec": "mzi", +"Manya": "mzj", +"NigeriaMambila": "mzk", +"MazatlánMixe": "mzl", +"Mumuye": "mzm", +"Mazanderani": "mzn", +"Matipuhy": "mzo", +"Movima": "mzp", +"MoriAtas": "mzq", +"Marúbo": "mzr", +"Macanese": "mzs", +"Mintil": "mzt", +"Inapang": "mzu", +"Manza": "mzv", +"Deg": "mzw", +"Mawayana": "mzx", +"MozambicanSign Language": "mzy", +"Maiadomu": "mzz", +"Namla": "naa", +"Southern Nambikuára": "nab", +"Narak": "nac", +"Naka'ela": "nae", +"Nabak": "naf", +"NagaPidgin": "nag", +"Nalu": "naj", +"Nakanai": "nak", +"Nalik": "nal", +"Nangikurrunggurr": "nam", +"MinNan Chinese": "nan", +"Naaba": "nao", +"Neapolitan": "nap", +"Nama(Namibia)": "naq", +"Iguta": "nar", +"Naasioi": "nas", +"Hungworo": "nat", +"Nauru": "nau", +"Navajo": "nav", +"Nawuri": "naw", +"Nakwi": "nax", +"Narrinyeri": "nay", +"CoatepecNahuatl": "naz", +"Nyemba": "nba", +"Ndoe": "nbb", +"ChangNaga": "nbc", +"Ngbinda": "nbd", +"KonyakNaga": "nbe", +"Nagarchal": "nbg", +"Ngamo": "nbh", +"MaoNaga": "nbi", +"Ngarinman": "nbj", +"Nake": "nbk", +"SouthNdebele": "nbl", +"NgbakaMa'bo": "nbm", +"Kuri": "nbn", +"Nkukoli": "nbo", +"Nnam": "nbp", +"Nggem": "nbq", +"Numana-Nunku-Gbantu-Numbu": "nbr", +"Namibian Sign Language": "nbs", +"Na": "nbt", +"RongmeiNaga": "nbu", +"Ngamambo": "nbv", +"SouthernNgbandi": "nbw", +"Ningera": "nby", +"Iyo": "nca", +"Central Nicobarese": "ncb", +"Ponam": "ncc", +"Nachering": "ncd", +"Yale": "nce", +"Notsi": "ncf", +"Nisga'a": "ncg", +"Central Huasteca Nahuatl": "nch", +"Classical Nahuatl": "nci", +"Northern Puebla Nahuatl": "ncj", +"Nakara": "nck", +"Michoacán Nahuatl": "ncl", +"Nambo": "ncm", +"Nauna": "ncn", +"Sibe": "nco", +"Northern Katang": "ncq", +"Ncane": "ncr", +"NicaraguanSign Language": "ncs", +"ChotheNaga": "nct", +"Chumburung": "ncu", +"Central Puebla Nahuatl": "ncx", +"Natchez": "ncz", +"Ndasa": "nda", +"Kenswei Nsei": "ndb", +"Ndau": "ndc", +"Nde-Nsele-Nta": "ndd", +"NorthNdebele": "nde", +"Nadruvian": "ndf", +"Ndengereko": "ndg", +"Ndali": "ndh", +"SambaLeko": "ndi", +"Ndamba": "ndj", +"Ndaka": "ndk", +"Ndolo": "ndl", +"Ndam": "ndm", +"Ngundi": "ndn", +"Ndonga": "ndo", +"Ndo": "ndp", +"Ndombe": "ndq", +"Ndoola": "ndr", +"LowGerman": "nds", +"Ndunga": "ndt", +"Dugun": "ndu", +"Ndut": "ndv", +"Ndobo": "ndw", +"Nduga": "ndx", +"Lutos": "ndy", +"Ndogo": "ndz", +"EasternNgad'a": "nea", +"Toura (Côte d'Ivoire)": "neb", +"Nedebang": "nec", +"Nde-Gbite": "ned", +"Kumak": "nee", +"Nefamese": "nef", +"Negidal": "neg", +"Nyenkha": "neh", +"Neo-Hittite": "nei", +"Neko": "nej", +"Neku": "nek", +"Nemi": "nem", +"Nengone": "nen", +"Ná-Meo": "neo", +"Nepali": "nep", +"North Central Mixe": "neq", +"Yahadian": "ner", +"Bhoti Kinnauri": "nes", +"Nete": "net", +"Neo": "neu", +"Nyaheun": "nev", +"Newari": "new", +"Neme": "nex", +"Neyo": "ney", +"Nez Perce": "nez", +"Dhao": "nfa", +"Ahwai": "nfd", +"Ayiwo": "nfl", +"Nafaanra": "nfr", +"Mfumte": "nfu", +"Ngbaka": "nga", +"NorthernNgbandi": "ngb", +"Ngombe (Democratic Republic of Congo)": "ngc", +"Ngando (Central African Republic)": "ngd", +"Ngemba": "nge", +"Ngbaka Manza": "ngg", +"N/u": "ngh", +"Ngizim": "ngi", +"Ngie": "ngj", +"Ngalkbun": "ngk", +"Lomwe": "ngl", +"Ngatik Men's Creole": "ngm", +"Ngwo": "ngn", +"Ngulu": "ngp", +"Ngurimi": "ngq", +"Nanggu": "ngr", +"Gvoko": "ngs", +"Ngeq": "ngt", +"GuerreroNahuatl": "ngu", +"Nagumi": "ngv", +"Ngwaba": "ngw", +"Nggwahyi": "ngx", +"Tibea": "ngy", +"Ngungwel": "ngz", +"Nhanda": "nha", +"Beng": "nhb", +"Tabasco Nahuatl": "nhc", +"Chiripá": "nhd", +"EasternHuasteca Nahuatl": "nhe", +"Nhuwala": "nhf", +"TetelcingoNahuatl": "nhg", +"Nahari": "nhh", +"Zacatlán-Ahuacatlán-Tepetzintla Nahuatl": "nhi", +"Isthmus-CosoleacaqueNahuatl": "nhk", +"MorelosNahuatl": "nhm", +"CentralNahuatl": "nhn", +"Takuu": "nho", +"Isthmus-PajapanNahuatl": "nhp", +"Huaxcaleca Nahuatl": "nhq", +"Naro": "nhr", +"OmetepecNahuatl": "nht", +"Noone": "nhu", +"TemascaltepecNahuatl": "nhv", +"Western Huasteca Nahuatl": "nhw", +"Isthmus-Mecayapan Nahuatl": "nhx", +"NorthernOaxaca Nahuatl": "nhy", +"SantaMaría La Alta Nahuatl": "nhz", +"Nias": "nia", +"Nakama": "nib", +"Ngandi": "nid", +"Niellim": "nie", +"Nek": "nif", +"Ngalakan": "nig", +"Nyiha(Tanzania)": "nih", +"Nii": "nii", +"Ngaju": "nij", +"Southern Nicobarese": "nik", +"Nila": "nil", +"Nilamba": "nim", +"Ninzo": "nin", +"Nganasan": "nio", +"Nandi": "niq", +"Nimboran": "nir", +"Nimi": "nis", +"SoutheasternKolami": "nit", +"Niuean": "niu", +"Gilyak": "niv", +"Nimo": "niw", +"Hema": "nix", +"Ngiti": "niy", +"Ningil": "niz", +"Nzanyi": "nja", +"NocteNaga": "njb", +"NdondeHamba": "njd", +"LothaNaga": "njh", +"Gudanji": "nji", +"Njen": "njj", +"Njalgulgule": "njl", +"Angami Naga": "njm", +"LiangmaiNaga": "njn", +"AoNaga": "njo", +"Njerep": "njr", +"Nisa": "njs", +"Ndyuka-Trio Pidgin": "njt", +"Ngadjunmaya": "nju", +"Kunyi": "njx", +"Njyem": "njy", +"Nyishi": "njz", +"Nkoya": "nka", +"KhoibuNaga": "nkb", +"Nkongho": "nkc", +"Koireng": "nkd", +"Duke": "nke", +"InpuiNaga": "nkf", +"Nekgini": "nkg", +"KhezhaNaga": "nkh", +"ThangalNaga": "nki", +"Nakai": "nkj", +"Nokuku": "nkk", +"Namat": "nkm", +"Nkangala": "nkn", +"Nkonya": "nko", +"Niuatoputapu": "nkp", +"Nkami": "nkq", +"Nukuoro": "nkr", +"North Asmat": "nks", +"Nyika(Tanzania)": "nkt", +"BounaKulango": "nku", +"Nyika (Malawi and Zambia)": "nkv", +"Nkutu": "nkw", +"Nkoroo": "nkx", +"Nkari": "nkz", +"Ngombale": "nla", +"Nalca": "nlc", +"Dutch": "nld", +"EastNyala": "nle", +"Gela": "nlg", +"Grangali": "nli", +"Nyali": "nlj", +"Ninia Yali": "nlk", +"Nihali": "nll", +"Mankiyali": "nlm", +"Ngul": "nlo", +"Lao Naga": "nlq", +"Nchumbulu": "nlu", +"Orizaba Nahuatl": "nlv", +"Walangama": "nlw", +"Nahali": "nlx", +"Nyamal": "nly", +"Nalögo": "nlz", +"Maram Naga": "nma", +"Big Nambas": "nmb", +"Ngam": "nmc", +"Ndumu": "nmd", +"MziemeNaga": "nme", +"TangkhulNaga": "nmf", +"Kwasio": "nmg", +"Monsang Naga": "nmh", +"Nyam": "nmi", +"Ngombe (Central African Republic)": "nmj", +"Namakura": "nmk", +"Ndemli": "nml", +"Manangba": "nmm", +"!Xóõ": "nmn", +"Moyon Naga": "nmo", +"Nimanbur": "nmp", +"Nambya": "nmq", +"Nimbari": "nmr", +"Letemboi": "nms", +"Namonuito": "nmt", +"NortheastMaidu": "nmu", +"Ngamini": "nmv", +"Nimoa": "nmw", +"Nama (Papua New Guinea)": "nmx", +"Namuyi": "nmy", +"Nawdm": "nmz", +"Nyangumarta": "nna", +"Nande": "nnb", +"Nancere": "nnc", +"West Ambae": "nnd", +"Ngandyera": "nne", +"Ngaing": "nnf", +"MaringNaga": "nng", +"Ngiemboon": "nnh", +"NorthNuaulu": "nni", +"Nyangatom": "nnj", +"Nankina": "nnk", +"Northern Rengma Naga": "nnl", +"Namia": "nnm", +"Ngete": "nnn", +"Norwegian Nynorsk": "nno", +"WanchoNaga": "nnp", +"Ngindo": "nnq", +"Narungga": "nnr", +"Nanticoke": "nnt", +"Dwang": "nnu", +"Nugunu (Australia)": "nnv", +"Southern Nuni": "nnw", +"Nyangga": "nny", +"Nda'nda'": "nnz", +"Woun Meu": "noa", +"NorwegianBokmål": "nob", +"Nuk": "noc", +"NorthernThai": "nod", +"Nimadi": "noe", +"Nomane": "nof", +"Nogai": "nog", +"Nomu": "noh", +"Noiri": "noi", +"Nonuya": "noj", +"Nooksack": "nok", +"Nomlaki": "nol", +"Nocamán": "nom", +"Old Norse": "non", +"Numanggang": "nop", +"Ngongo": "noq", +"Norwegian": "nor", +"Eastern Nisu": "nos", +"Nomatsiguenga": "not", +"Ewage-Notu": "nou", +"Novial": "nov", +"Nyambo": "now", +"Noy": "noy", +"Nayi": "noz", +"NarPhu": "npa", +"Nupbikha": "npb", +"Ponyo-Gongwang Naga": "npg", +"PhomNaga": "nph", +"Nepali (individual language)": "npi", +"Southeastern Puebla Nahuatl": "npl", +"Mondropolon": "npn", +"PochuriNaga": "npo", +"Nipsan": "nps", +"PuimeiNaga": "npu", +"Noipx": "npx", +"Napu": "npy", +"SouthernNago": "nqg", +"Kura Ede Nago": "nqk", +"Ngendelengo": "nql", +"Ndom": "nqm", +"Nen": "nqn", +"N'Ko": "nqo", +"Kyan-Karyaw Naga": "nqq", +"Nteng": "nqt", +"Akyaung Ari Naga": "nqy", +"Ngom": "nra", +"Nara": "nrb", +"Noric": "nrc", +"SouthernRengma Naga": "nre", +"Jèrriais": "nrf", +"Narango": "nrg", +"ChokriNaga": "nri", +"Ngarla": "nrk", +"Ngarluma": "nrl", +"Narom": "nrm", +"Norn": "nrn", +"North Picene": "nrp", +"Norra": "nrr", +"Northern Kalapuya": "nrt", +"Narua": "nru", +"Ngurmbur": "nrx", +"Lala": "nrz", +"SangtamNaga": "nsa", +"Lower Nossob": "nsb", +"Nshi": "nsc", +"SouthernNisu": "nsd", +"Nsenga": "nse", +"Northwestern Nisu": "nsf", +"Ngasa": "nsg", +"Ngoshie": "nsh", +"NigerianSign Language": "nsi", +"Naskapi": "nsk", +"Norwegian Sign Language": "nsl", +"SumiNaga": "nsm", +"Nehan": "nsn", +"Pedi": "nso", +"NepaleseSign Language": "nsp", +"Northern Sierra Miwok": "nsq", +"MaritimeSign Language": "nsr", +"Nali": "nss", +"TaseNaga": "nst", +"Sierra Negra Nahuatl": "nsu", +"Southwestern Nisu": "nsv", +"Navut": "nsw", +"Nsongo": "nsx", +"Nasal": "nsy", +"Nisenan": "nsz", +"Northern Tidung": "ntd", +"Nathembo": "nte", +"Ngantangarra": "ntg", +"Natioro": "nti", +"Ngaanyatjarra": "ntj", +"Ikoma-Nata-Isenye": "ntk", +"Nateni": "ntm", +"Ntomba": "nto", +"Northern Tepehuan": "ntp", +"Delo": "ntr", +"Natügu": "ntu", +"Nottoway": "ntw", +"Tangkhul Naga (Myanmar)": "ntx", +"Mantsi": "nty", +"Natanzi": "ntz", +"Yuaga": "nua", +"Nukuini": "nuc", +"Ngala": "nud", +"Ngundu": "nue", +"Nusu": "nuf", +"Nungali": "nug", +"Ndunda": "nuh", +"Ngumbi": "nui", +"Nyole": "nuj", +"Nuu-chah-nulth": "nuk", +"NusaLaut": "nul", +"Niuafo'ou": "num", +"Nung(Myanmar)": "nun", +"Nguôn": "nuo", +"Nupe-Nupe-Tako": "nup", +"Nukumanu": "nuq", +"Nukuria": "nur", +"Nuer": "nus", +"Nung(Viet Nam)": "nut", +"Ngbundu": "nuu", +"Northern Nuni": "nuv", +"Nguluwan": "nuw", +"Mehek": "nux", +"Nunggubuyu": "nuy", +"Tlamacazapa Nahuatl": "nuz", +"Nasarian": "nvh", +"Namiae": "nvm", +"Nyokon": "nvo", +"Nawathinehena": "nwa", +"Nyabwa": "nwb", +"ClassicalNewari": "nwc", +"Ngwe": "nwe", +"Ngayawung": "nwg", +"Southwest Tanna": "nwi", +"Nyamusa-Molo": "nwm", +"Nauo": "nwo", +"Nawaru": "nwr", +"MiddleNewar": "nwx", +"Nottoway-Meherrin": "nwy", +"Nauete": "nxa", +"Ngando (Democratic Republic of Congo)": "nxd", +"Nage": "nxe", +"Ngad'a": "nxg", +"Nindi": "nxi", +"Koki Naga": "nxk", +"SouthNuaulu": "nxl", +"Numidian": "nxm", +"Ngawun": "nxn", +"Ndambomo": "nxo", +"Naxi": "nxq", +"Ninggerum": "nxr", +"Nafri": "nxx", +"Nyanja": "nya", +"Nyangbo": "nyb", +"Nyanga-li": "nyc", +"Nyore": "nyd", +"Nyengo": "nye", +"Giryama": "nyf", +"Nyindu": "nyg", +"Nyigina": "nyh", +"Ama(Sudan)": "nyi", +"Nyanga": "nyj", +"Nyaneka": "nyk", +"Nyeu": "nyl", +"Nyamwezi": "nym", +"Nyankole": "nyn", +"Nyoro": "nyo", +"Nyang'i": "nyp", +"Nayini": "nyq", +"Nyiha(Malawi)": "nyr", +"Nyunga": "nys", +"Nyawaygi": "nyt", +"Nyungwe": "nyu", +"Nyulnyul": "nyv", +"Nyaw": "nyw", +"Nganyaywana": "nyx", +"Nyakyusa-Ngonde": "nyy", +"Tigon Mbembe": "nza", +"Njebi": "nzb", +"Nzadi": "nzd", +"Nzima": "nzi", +"Nzakara": "nzk", +"ZemeNaga": "nzm", +"New Zealand Sign Language": "nzs", +"Teke-Nzikou": "nzu", +"Nzakambay": "nzy", +"NangaDama Dogon": "nzz", +"Orok": "oaa", +"Oroch": "oac", +"Old Aramaic (up to 700 BCE)": "oar", +"OldAvar": "oav", +"Obispeño": "obi", +"Southern Bontok": "obk", +"Oblo": "obl", +"Moabite": "obm", +"OboManobo": "obo", +"OldBurmese": "obr", +"Old Breton": "obt", +"Obulom": "obu", +"Ocaina": "oca", +"OldChinese": "och", +"Occitan(post 1500)": "oci", +"Old Cham": "ocm", +"Old Cornish": "oco", +"Atzingo Matlatzinca": "ocu", +"Odut": "oda", +"Od": "odk", +"OldDutch": "odt", +"Odual": "odu", +"Ofo": "ofo", +"Old Frisian": "ofs", +"Efutop": "ofu", +"Ogbia": "ogb", +"Ogbah": "ogc", +"OldGeorgian": "oge", +"Ogbogolo": "ogg", +"Khana": "ogo", +"Ogbronuagum": "ogu", +"OldHittite": "oht", +"Old Hungarian": "ohu", +"Oirata": "oia", +"Inebu One": "oin", +"Northwestern Ojibwa": "ojb", +"CentralOjibwa": "ojc", +"EasternOjibwa": "ojg", +"Ojibwa": "oji", +"OldJapanese": "ojp", +"SevernOjibwa": "ojs", +"Ontong Java": "ojv", +"WesternOjibwa": "ojw", +"Okanagan": "oka", +"Okobo": "okb", +"Kobo": "okc", +"Okodia": "okd", +"Okpe (Southwestern Edo)": "oke", +"Koko Babangk": "okg", +"Koresh-eRostam": "okh", +"Okiek": "oki", +"Oko-Juwoi": "okj", +"KwamtimOne": "okk", +"Old Kentish Sign Language": "okl", +"Middle Korean (10th-16th cent.)": "okm", +"Oki-No-Erabu": "okn", +"OldKorean (3rd-9th cent.)": "oko", +"Kirike": "okr", +"Oko-Eni-Osayen": "oks", +"Oku": "oku", +"Orokaiva": "okv", +"Okpe(Northwestern Edo)": "okx", +"Old Khmer": "okz", +"Walungge": "ola", +"Mochi": "old", +"Olekha": "ole", +"Olkol": "olk", +"Oloma": "olm", +"Livvi": "olo", +"Olrat": "olr", +"Old Lithuanian": "olt", +"Kuvale": "olu", +"Omaha-Ponca": "oma", +"EastAmbae": "omb", +"Mochica": "omc", +"Omagua": "omg", +"Omi": "omi", +"Omok": "omk", +"Ombo": "oml", +"Minoan": "omn", +"Utarmbung": "omo", +"Old Manipuri": "omp", +"OldMarathi": "omr", +"Omotik": "omt", +"Omurano": "omu", +"SouthTairora": "omw", +"OldMon": "omx", +"Old Malay": "omy", +"Ona": "ona", +"Lingao": "onb", +"Oneida": "one", +"Olo": "ong", +"Onin": "oni", +"Onjob": "onj", +"KaboreOne": "onk", +"Onobasulu": "onn", +"Onondaga": "ono", +"Sartang": "onp", +"NorthernOne": "onr", +"Ono": "ons", +"Ontenu": "ont", +"Unua": "onu", +"OldNubian": "onw", +"OninBased Pidgin": "onx", +"TohonoO'odham": "ood", +"Ong": "oog", +"Önge": "oon", +"Oorlams": "oor", +"OldOssetic": "oos", +"Okpamheri": "opa", +"Kopkaka": "opk", +"Oksapmin": "opm", +"Opao": "opo", +"Opata": "opt", +"Ofayé": "opy", +"Oroha": "ora", +"Orma": "orc", +"Orejón": "ore", +"Oring": "org", +"Oroqen": "orh", +"Oriya": "ori", +"Oromo": "orm", +"OrangKanaq": "orn", +"Orokolo": "oro", +"Oruma": "orr", +"OrangSeletar": "ors", +"AdivasiOriya": "ort", +"Ormuri": "oru", +"OldRussian": "orv", +"OroWin": "orw", +"Oro": "orx", +"Odia": "ory", +"Ormu": "orz", +"Osage": "osa", +"Oscan": "osc", +"Osing": "osi", +"Old Sundanese": "osn", +"Ososo": "oso", +"Old Spanish": "osp", +"Ossetian": "oss", +"Osatu": "ost", +"SouthernOne": "osu", +"OldSaxon": "osx", +"Ottoman Turkish (1500-1928)": "ota", +"OldTibetan": "otb", +"OtDanum": "otd", +"Mezquital Otomi": "ote", +"Oti": "oti", +"Old Turkish": "otk", +"Tilapa Otomi": "otl", +"EasternHighland Otomi": "otm", +"TenangoOtomi": "otn", +"Querétaro Otomi": "otq", +"Otoro": "otr", +"Estado de México Otomi": "ots", +"Temoaya Otomi": "ott", +"Otuke": "otu", +"Ottawa": "otw", +"Texcatepec Otomi": "otx", +"OldTamil": "oty", +"IxtencoOtomi": "otz", +"Tagargrent": "oua", +"Glio-Oubi": "oub", +"Ounge": "oue", +"OldUighur": "oui", +"Ouma": "oum", +"Elfdalian": "ovd", +"Owiniga": "owi", +"OldWelsh": "owl", +"Oy": "oyb", +"Oyda": "oyd", +"Wayampi": "oym", +"Oya'oya": "oyy", +"Koonzime": "ozm", +"Parecís": "pab", +"Pacoh": "pac", +"Paumarí": "pad", +"Pagibete": "pae", +"Paranawát": "paf", +"Pangasinan": "pag", +"Tenharim": "pah", +"Pe": "pai", +"Parakanã": "pak", +"Pahlavi": "pal", +"Pampanga": "pam", +"Panjabi": "pan", +"NorthernPaiute": "pao", +"Papiamento": "pap", +"Parya": "paq", +"Panamint": "par", +"Papasena": "pas", +"Palauan": "pau", +"Pakaásnovos": "pav", +"Pawnee": "paw", +"Pankararé": "pax", +"Pech": "pay", +"Pankararú": "paz", +"Páez": "pbb", +"Patamona": "pbc", +"MezontlaPopoloca": "pbe", +"CoyotepecPopoloca": "pbf", +"Paraujano": "pbg", +"E'ñapa Woromaipu": "pbh", +"Parkwa": "pbi", +"Mak(Nigeria)": "pbl", +"Puebla Mazatec": "pbm", +"Kpasam": "pbn", +"Papel": "pbo", +"Badyara": "pbp", +"Pangwa": "pbr", +"CentralPame": "pbs", +"SouthernPashto": "pbt", +"NorthernPashto": "pbu", +"Pnar": "pbv", +"Pyu": "pby", +"Santa Inés Ahuatempan Popoloca": "pca", +"Pear": "pcb", +"Bouyei": "pcc", +"Picard": "pcd", +"RuchingPalaung": "pce", +"Paliyan": "pcf", +"Paniya": "pcg", +"Pardhan": "pch", +"Duruwa": "pci", +"Parenga": "pcj", +"PaiteChin": "pck", +"Pardhi": "pcl", +"Nigerian Pidgin": "pcm", +"Piti": "pcn", +"Pacahuara": "pcp", +"Pyapun": "pcw", +"Anam": "pda", +"PennsylvaniaGerman": "pdc", +"PaDi": "pdi", +"Podena": "pdn", +"Padoe": "pdo", +"Plautdietsch": "pdt", +"Kayan": "pdu", +"Peranakan Indonesian": "pea", +"Eastern Pomo": "peb", +"Mala (Papua New Guinea)": "ped", +"Taje": "pee", +"Northeastern Pomo": "pef", +"Pengo": "peg", +"Bonan": "peh", +"Chichimeca-Jonaz": "pei", +"NorthernPomo": "pej", +"Penchal": "pek", +"Pekal": "pel", +"Phende": "pem", +"Old Persian (ca. 600-400 B.C.)": "peo", +"Kunja": "pep", +"SouthernPomo": "peq", +"IranianPersian": "pes", +"Pémono": "pev", +"Petats": "pex", +"Petjo": "pey", +"EasternPenan": "pez", +"Pááfang": "pfa", +"Peere": "pfe", +"Pfaelzisch": "pfl", +"Sudanese Creole Arabic": "pga", +"Gāndhārī": "pgd", +"Pangwali": "pgg", +"Pagi": "pgi", +"Rerep": "pgk", +"Primitive Irish": "pgl", +"Paelignian": "pgn", +"Pangseng": "pgs", +"Pagu": "pgu", +"Papua New Guinean Sign Language": "pgz", +"Pa-Hng": "pha", +"Phudagi": "phd", +"Phuong": "phg", +"Phukha": "phh", +"Phake": "phk", +"Phalura": "phl", +"Phimbi": "phm", +"Phoenician": "phn", +"Phunoi": "pho", +"Phana'": "phq", +"Pahari-Potwari": "phr", +"Phu Thai": "pht", +"Phuan": "phu", +"Pahlavani": "phv", +"Phangduwali": "phw", +"Pima Bajo": "pia", +"Yine": "pib", +"Pinji": "pic", +"Piaroa": "pid", +"Piro": "pie", +"Pingelapese": "pif", +"Pisabo": "pig", +"Pitcairn-Norfolk": "pih", +"Pini": "pii", +"Pijao": "pij", +"Yom": "pil", +"Powhatan": "pim", +"Piame": "pin", +"Piapoco": "pio", +"Pero": "pip", +"Piratapuyo": "pir", +"Pijin": "pis", +"PittaPitta": "pit", +"Pintupi-Luritja": "piu", +"Pileni": "piv", +"Pimbwe": "piw", +"Piu": "pix", +"Piya-Kwonci": "piy", +"Pije": "piz", +"Pitjantjatjara": "pjt", +"ArdhamāgadhīPrākrit": "pka", +"Pokomo": "pkb", +"Paekche": "pkc", +"Pak-Tong": "pkg", +"Pankhu": "pkh", +"Pakanha": "pkn", +"Pökoot": "pko", +"Pukapuka": "pkp", +"AttapadyKurumba": "pkr", +"Pakistan Sign Language": "pks", +"Maleng": "pkt", +"Paku": "pku", +"Miani": "pla", +"Polonombauk": "plb", +"CentralPalawano": "plc", +"Polari": "pld", +"Palu'e": "ple", +"Pilagá": "plg", +"Paulohi": "plh", +"Pali": "pli", +"Polci": "plj", +"KohistaniShina": "plk", +"ShwePalaung": "pll", +"Palenquero": "pln", +"OlutaPopoluca": "plo", +"Palaic": "plq", +"PalakaSenoufo": "plr", +"San Marcos Tlalcoyalco Popoloca": "pls", +"PlateauMalagasy": "plt", +"Palikúr": "plu", +"Southwest Palawano": "plv", +"Brooke'sPoint Palawano": "plw", +"Bolyu": "ply", +"Paluan": "plz", +"Paama": "pma", +"Pambia": "pmb", +"Pallanganmiddang": "pmd", +"Pwaamei": "pme", +"Pamona": "pmf", +"Māhārāṣṭri Prākrit": "pmh", +"NorthernPumi": "pmi", +"Southern Pumi": "pmj", +"Pamlico": "pmk", +"LinguaFranca": "pml", +"Pomo": "pmm", +"Pam": "pmn", +"Pom": "pmo", +"Northern Pame": "pmq", +"Paynamar": "pmr", +"Piemontese": "pms", +"Tuamotuan": "pmt", +"PlainsMiwok": "pmw", +"PoumeiNaga": "pmx", +"PapuanMalay": "pmy", +"Southern Pame": "pmz", +"PunanBah-Biau": "pna", +"Western Panjabi": "pnb", +"Pannei": "pnc", +"Mpinda": "pnd", +"Western Penan": "pne", +"Pongu": "png", +"Penrhyn": "pnh", +"Aoheng": "pni", +"Pinjarup": "pnj", +"Paunaka": "pnk", +"Paleni": "pnl", +"PunanBatu 1": "pnm", +"Pinai-Hagahai": "pnn", +"Panobo": "pno", +"Pancana": "pnp", +"Pana(Burkina Faso)": "pnq", +"Panim": "pnr", +"Ponosakan": "pns", +"Pontic": "pnt", +"JiongnaiBunu": "pnu", +"Pinigura": "pnv", +"Panytyima": "pnw", +"Phong-Kniang": "pnx", +"Pinyin": "pny", +"Pana (Central African Republic)": "pnz", +"Poqomam": "poc", +"San Juan Atzingo Popoloca": "poe", +"Poke": "pof", +"Potiguára": "pog", +"Poqomchi'": "poh", +"Highland Popoluca": "poi", +"Pokangá": "pok", +"Polish": "pol", +"SoutheasternPomo": "pom", +"Pohnpeian": "pon", +"CentralPomo": "poo", +"Pwapwa": "pop", +"TexistepecPopoluca": "poq", +"Portuguese": "por", +"Sayula Popoluca": "pos", +"Potawatomi": "pot", +"Upper Guinea Crioulo": "pov", +"San Felipe Otlaltepec Popoloca": "pow", +"Polabian": "pox", +"Pogolo": "poy", +"Papi": "ppe", +"Paipai": "ppi", +"Uma": "ppk", +"Pipil": "ppl", +"Papuma": "ppm", +"Papapana": "ppn", +"Folopa": "ppo", +"Pelende": "ppp", +"Pei": "ppq", +"San Luís Temalacayuca Popoloca": "pps", +"Pare": "ppt", +"Papora": "ppu", +"Pa'a": "pqa", +"Malecite-Passamaquoddy": "pqm", +"Parachi": "prc", +"Parsi-Dari": "prd", +"Principense": "pre", +"Paranan": "prf", +"Prussian": "prg", +"Porohanon": "prh", +"Paicî": "pri", +"Parauk": "prk", +"PeruvianSign Language": "prl", +"Kibiri": "prm", +"Prasuni": "prn", +"Old Provençal (to 1500)": "pro", +"Parsi": "prp", +"AshéninkaPerené": "prq", +"Puri": "prr", +"Dari": "prs", +"Phai": "prt", +"Puragi": "pru", +"Parawen": "prw", +"Purik": "prx", +"ProvidenciaSign Language": "prz", +"Asue Awyu": "psa", +"Persian Sign Language": "psc", +"Plains Indian Sign Language": "psd", +"Central Malay": "pse", +"PenangSign Language": "psg", +"SouthwestPashayi": "psh", +"Southeast Pashayi": "psi", +"Puerto Rican Sign Language": "psl", +"Pauserna": "psm", +"Panasuan": "psn", +"PolishSign Language": "pso", +"PhilippineSign Language": "psp", +"Pasi": "psq", +"Portuguese Sign Language": "psr", +"Kaulong": "pss", +"Central Pashto": "pst", +"Sauraseni Prākrit": "psu", +"Port Sandwich": "psw", +"Piscataway": "psy", +"Pai Tavytera": "pta", +"PataxóHã-Ha-Hãe": "pth", +"Pintiini": "pti", +"Patani": "ptn", +"Zo'é": "pto", +"Patep": "ptp", +"Pattapu": "ptq", +"Piamatsina": "ptr", +"Enrekang": "ptt", +"Bambam": "ptu", +"PortVato": "ptv", +"Pentlatch": "ptw", +"Pathiya": "pty", +"WesternHighland Purepecha": "pua", +"Purum": "pub", +"PunanMerap": "puc", +"Punan Aput": "pud", +"Puelche": "pue", +"Punan Merah": "puf", +"Phuie": "pug", +"Puinave": "pui", +"PunanTubu": "puj", +"Puma": "pum", +"Puoc": "puo", +"Pulabu": "pup", +"Puquina": "puq", +"Puruborá": "pur", +"Pushto": "pus", +"Putoh": "put", +"Punu": "puu", +"Puluwatese": "puw", +"Puare": "pux", +"Purisimeño": "puy", +"Pawaia": "pwa", +"Panawa": "pwb", +"Gapapaiwa": "pwg", +"Patwin": "pwi", +"Molbog": "pwm", +"Paiwan": "pwn", +"PwoWestern Karen": "pwo", +"Powari": "pwr", +"Pwo Northern Karen": "pww", +"QuetzaltepecMixe": "pxm", +"Pye Krumen": "pye", +"Fyam": "pym", +"Poyanáwa": "pyn", +"Paraguayan Sign Language": "pys", +"Puyuma": "pyu", +"Pyu(Myanmar)": "pyx", +"Pyen": "pyy", +"Para Naga": "pzn", +"Quapaw": "qua", +"Huallaga Huánuco Quechua": "qub", +"K'iche'": "quc", +"CalderónHighland Quichua": "qud", +"Quechua": "que", +"Lambayeque Quechua": "quf", +"Chimborazo Highland Quichua": "qug", +"South Bolivian Quechua": "quh", +"Quileute": "qui", +"ChachapoyasQuechua": "quk", +"NorthBolivian Quechua": "qul", +"Sipacapense": "qum", +"Quinault": "qun", +"Southern Pastaza Quechua": "qup", +"Quinqui": "quq", +"Yanahuanca Pasco Quechua": "qur", +"Santiago del Estero Quichua": "qus", +"Sacapulteco": "quv", +"TenaLowland Quichua": "quw", +"YauyosQuechua": "qux", +"AyacuchoQuechua": "quy", +"CuscoQuechua": "quz", +"Ambo-PascoQuechua": "qva", +"Cajamarca Quechua": "qvc", +"Eastern Apurímac Quechua": "qve", +"Huamalíes-Dos de Mayo Huánuco Quechua": "qvh", +"ImbaburaHighland Quichua": "qvi", +"Loja Highland Quichua": "qvj", +"CajatamboNorth Lima Quechua": "qvl", +"Margos-Yarowilca-Lauricocha Quechua": "qvm", +"NorthJunín Quechua": "qvn", +"NapoLowland Quechua": "qvo", +"PacaraosQuechua": "qvp", +"SanMartín Quechua": "qvs", +"Huaylla Wanca Quechua": "qvw", +"Queyu": "qvy", +"Northern Pastaza Quichua": "qvz", +"Corongo Ancash Quechua": "qwa", +"Classical Quechua": "qwc", +"HuaylasAncash Quechua": "qwh", +"Kuman(Russia)": "qwm", +"SihuasAncash Quechua": "qws", +"Kwalhioqua-Tlatskanai": "qwt", +"Chiquián Ancash Quechua": "qxa", +"Chincha Quechua": "qxc", +"Panao Huánuco Quechua": "qxh", +"SalasacaHighland Quichua": "qxl", +"Northern Conchucos Ancash Quechua": "qxn", +"Southern Conchucos Ancash Quechua": "qxo", +"PunoQuechua": "qxp", +"Qashqa'i": "qxq", +"CañarHighland Quichua": "qxr", +"Southern Qiang": "qxs", +"SantaAna de Tusi Pasco Quechua": "qxt", +"Arequipa-La Unión Quechua": "qxu", +"Jauja Wanca Quechua": "qxw", +"Quenya": "qya", +"Quiripi": "qyp", +"Dungmali": "raa", +"Camling": "rab", +"Rasawa": "rac", +"Rade": "rad", +"WesternMeohang": "raf", +"Logooli": "rag", +"Rabha": "rah", +"Ramoaaina": "rai", +"Rajasthani": "raj", +"Tulu-Bohuai": "rak", +"Ralte": "ral", +"Canela": "ram", +"Riantana": "ran", +"Rao": "rao", +"Rapanui": "rap", +"Saam": "raq", +"Rarotongan": "rar", +"Tegali": "ras", +"Razajerdi": "rat", +"Raute": "rau", +"Sampang": "rav", +"Rawang": "raw", +"Rang": "rax", +"Rapa": "ray", +"Rahambuu": "raz", +"RumaiPalaung": "rbb", +"NorthernBontok": "rbk", +"MirayaBikol": "rbl", +"Barababaraba": "rbp", +"Réunion Creole French": "rcf", +"Rudbari": "rdb", +"Rerau": "rea", +"Rembong": "reb", +"RejangKayan": "ree", +"Kara(Tanzania)": "reg", +"Reli": "rei", +"Rejang": "rej", +"Rendille": "rel", +"Remo": "rem", +"Rengao": "ren", +"RerBare": "rer", +"Reshe": "res", +"Retta": "ret", +"Reyesano": "rey", +"Roria": "rga", +"Romano-Greek": "rge", +"Rangkas": "rgk", +"Romagnol": "rgn", +"Resígaro": "rgr", +"SouthernRoglai": "rgs", +"Ringgou": "rgu", +"Rohingya": "rhg", +"Yahang": "rhp", +"Riang(India)": "ria", +"Tarifit": "rif", +"Riang(Myanmar)": "ril", +"Nyaturu": "rim", +"Nungu": "rin", +"Ribun": "rir", +"Ritarungo": "rit", +"Riung": "riu", +"Rajong": "rjg", +"Raji": "rji", +"Rajbanshi": "rjs", +"Kraol": "rka", +"Rikbaktsa": "rkb", +"Rakahanga-Manihiki": "rkh", +"Rakhine": "rki", +"Marka": "rkm", +"Rangpuri": "rkt", +"Arakwal": "rkw", +"Rama": "rma", +"Rembarunga": "rmb", +"Carpathian Romani": "rmc", +"TravellerDanish": "rmd", +"Angloromani": "rme", +"KaloFinnish Romani": "rmf", +"Traveller Norwegian": "rmg", +"Murkim": "rmh", +"Lomavren": "rmi", +"Romkun": "rmk", +"Baltic Romani": "rml", +"Roma": "rmm", +"Balkan Romani": "rmn", +"SinteRomani": "rmo", +"Rempi": "rmp", +"Caló": "rmq", +"RomanianSign Language": "rms", +"Domari": "rmt", +"Tavringer Romani": "rmu", +"Romanova": "rmv", +"WelshRomani": "rmw", +"Romam": "rmx", +"Vlax Romani": "rmy", +"Marma": "rmz", +"Ruund": "rnd", +"Ronga": "rng", +"Ranglong": "rnl", +"Roon": "rnn", +"Rongpo": "rnp", +"Nari Nari": "rnr", +"Rungwa": "rnw", +"Tae'": "rob", +"Cacgia Roglai": "roc", +"Rogo": "rod", +"Ronji": "roe", +"Rombo": "rof", +"NorthernRoglai": "rog", +"Romansh": "roh", +"Romblomanon": "rol", +"Romany": "rom", +"Romanian": "ron", +"Rotokas": "roo", +"Kriol": "rop", +"Rongga": "ror", +"Runga": "rou", +"Dela-Oenale": "row", +"Repanbitip": "rpn", +"Rapting": "rpt", +"Ririo": "rri", +"Waima": "rro", +"Arritinngithigh": "rrt", +"Romano-Serbian": "rsb", +"RussianSign Language": "rsl", +"Miriwoong Sign Language": "rsm", +"Rungtu Chin": "rtc", +"Ratahan": "rth", +"Rotuman": "rtm", +"Yurats": "rts", +"Rathawi": "rtw", +"Gungu": "rub", +"Ruuli": "ruc", +"Rusyn": "rue", +"Luguru": "ruf", +"Roviana": "rug", +"Ruga": "ruh", +"Rufiji": "rui", +"Che": "ruk", +"Rundi": "run", +"IstroRomanian": "ruo", +"Macedo-Romanian": "rup", +"MeglenoRomanian": "ruq", +"Russian": "rus", +"Rutul": "rut", +"LanasLobu": "ruu", +"Mala(Nigeria)": "ruy", +"Ruma": "ruz", +"Rawo": "rwa", +"Rwa": "rwk", +"Ruwila": "rwl", +"Amba (Uganda)": "rwm", +"Rawa": "rwo", +"Marwari(India)": "rwr", +"Ngardi": "rxd", +"Karuwali": "rxw", +"Northern Amami-Oshima": "ryn", +"Yaeyama": "rys", +"Central Okinawan": "ryu", +"Rāziḥī": "rzh", +"Saba": "saa", +"Buglere": "sab", +"Meskwaki": "sac", +"Sandawe": "sad", +"Sabanê": "sae", +"Safaliba": "saf", +"Sango": "sag", +"Yakut": "sah", +"Sahu": "saj", +"Sake": "sak", +"SamaritanAramaic": "sam", +"Sanskrit": "san", +"Sause": "sao", +"Samburu": "saq", +"Saraveca": "sar", +"Sasak": "sas", +"Santali": "sat", +"Saleman": "sau", +"Saafi-Saafi": "sav", +"Sawi": "saw", +"Sa": "sax", +"Saya": "say", +"Saurashtra": "saz", +"Ngambay": "sba", +"Simbo": "sbb", +"Kele (Papua New Guinea)": "sbc", +"SouthernSamo": "sbd", +"Saliba": "sbe", +"Shabo": "sbf", +"Seget": "sbg", +"Sori-Harengan": "sbh", +"Seti": "sbi", +"Surbakhal": "sbj", +"Safwa": "sbk", +"Botolan Sambal": "sbl", +"Sagala": "sbm", +"SindhiBhil": "sbn", +"Sabüm": "sbo", +"Sangu(Tanzania)": "sbp", +"Sileibi": "sbq", +"Sembakung Murut": "sbr", +"Subiya": "sbs", +"Kimki": "sbt", +"StodBhoti": "sbu", +"Sabine": "sbv", +"Simba": "sbw", +"Seberuang": "sbx", +"Soli": "sby", +"Sara Kaba": "sbz", +"Chut": "scb", +"Dongxiang": "sce", +"SanMiguel Creole French": "scf", +"Sanggau": "scg", +"Sakachep": "sch", +"SriLankan Creole Malay": "sci", +"Sadri": "sck", +"Shina": "scl", +"Sicilian": "scn", +"Scots": "sco", +"HelambuSherpa": "scp", +"Sa'och": "scq", +"NorthSlavey": "scs", +"Southern Katang": "sct", +"Shumcho": "scu", +"Sheni": "scv", +"Sha": "scw", +"Sicel": "scx", +"Toraja-Sa'dan": "sda", +"Shabak": "sdb", +"SassareseSardinian": "sdc", +"Surubu": "sde", +"Sarli": "sdf", +"Savi": "sdg", +"Southern Kurdish": "sdh", +"Suundi": "sdj", +"SosKundi": "sdk", +"Saudi Arabian Sign Language": "sdl", +"Gallurese Sardinian": "sdn", +"Bukar-SadungBidayuh": "sdo", +"Sherdukpen": "sdp", +"Semandang": "sdq", +"Oraon Sadri": "sdr", +"Sened": "sds", +"Shuadit": "sdt", +"Sarudu": "sdu", +"SibuMelanau": "sdx", +"Sallands": "sdz", +"Semai": "sea", +"ShempireSenoufo": "seb", +"Sechelt": "sec", +"Sedang": "sed", +"Seneca": "see", +"Cebaara Senoufo": "sef", +"Segeju": "seg", +"Sena": "seh", +"Seri": "sei", +"Sene": "sej", +"Sekani": "sek", +"Selkup": "sel", +"Nanerigé Sénoufo": "sen", +"Suarmin": "seo", +"SìcìtéSénoufo": "sep", +"SenaraSénoufo": "seq", +"Serrano": "ser", +"Koyraboro Senni Songhai": "ses", +"Sentani": "set", +"Serui-Laut": "seu", +"Nyarafolo Senoufo": "sev", +"SewaBay": "sew", +"Secoya": "sey", +"SenthangChin": "sez", +"Langue des signes de Belgique Francophone": "sfb", +"Eastern Subanen": "sfe", +"Small Flowery Miao": "sfm", +"SouthAfrican Sign Language": "sfs", +"Sehwi": "sfw", +"OldIrish (to 900)": "sga", +"Mag-antsiAyta": "sgb", +"Kipsigis": "sgc", +"Surigaonon": "sgd", +"Segai": "sge", +"Swiss-GermanSign Language": "sgg", +"Shughni": "sgh", +"Suga": "sgi", +"Surgujia": "sgj", +"Sangkong": "sgk", +"Singa": "sgm", +"Singpho": "sgp", +"Sangisari": "sgr", +"Samogitian": "sgs", +"Brokpake": "sgt", +"Salas": "sgu", +"Sebat Bet Gurage": "sgw", +"SierraLeone Sign Language": "sgx", +"Sanglechi": "sgy", +"Sursurunga": "sgz", +"Shall-Zwall": "sha", +"Ninam": "shb", +"Sonde": "shc", +"KundalShahi": "shd", +"Sheko": "she", +"Shua": "shg", +"Shoshoni": "shh", +"Tachelhit": "shi", +"Shatt": "shj", +"Shilluk": "shk", +"Shendu": "shl", +"Shahrudi": "shm", +"Shan": "shn", +"Shanga": "sho", +"Shipibo-Conibo": "shp", +"Sala": "shq", +"Shi": "shr", +"Shuswap": "shs", +"Shasta": "sht", +"ChadianArabic": "shu", +"Shehri": "shv", +"Shwai": "shw", +"She": "shx", +"Tachawit": "shy", +"SyenaraSenoufo": "shz", +"AkkalaSami": "sia", +"Sebop": "sib", +"Sidamo": "sid", +"Simaa": "sie", +"Siamou": "sif", +"Paasaal": "sig", +"Zire": "sih", +"ShomPeng": "sii", +"Numbami": "sij", +"Sikiana": "sik", +"Tumulung Sisaala": "sil", +"Mende (Papua New Guinea)": "sim", +"Sinhala": "sin", +"Sikkimese": "sip", +"Sonia": "siq", +"Siri": "sir", +"Siuslaw": "sis", +"Sinagen": "siu", +"Sumariup": "siv", +"Siwai": "siw", +"Sumau": "six", +"Sivandi": "siy", +"Siwi": "siz", +"Epena": "sja", +"Sajau Basap": "sjb", +"KildinSami": "sjd", +"PiteSami": "sje", +"Assangori": "sjg", +"KemiSami": "sjk", +"Sajalong": "sjl", +"Mapun": "sjm", +"Sindarin": "sjn", +"Xibe": "sjo", +"Surjapuri": "sjp", +"Siar-Lak": "sjr", +"SenhajaDe Srair": "sjs", +"TerSami": "sjt", +"Ume Sami": "sju", +"Shawnee": "sjw", +"Skagit": "ska", +"Saek": "skb", +"Sauk": "skc", +"Southern Sierra Miwok": "skd", +"Seke (Vanuatu)": "ske", +"Sakirabiá": "skf", +"SakalavaMalagasy": "skg", +"Sikule": "skh", +"Sika": "ski", +"Seke(Nepal)": "skj", +"Sakam": "skm", +"KolibuganSubanon": "skn", +"Seko Tengah": "sko", +"Sekapan": "skp", +"Sininkere": "skq", +"Seraiki": "skr", +"Maia": "sks", +"Sakata": "skt", +"Sakao": "sku", +"Skou": "skv", +"Skepi Creole Dutch": "skw", +"SekoPadang": "skx", +"Sikaiana": "sky", +"Sekar": "skz", +"Sáliba": "slc", +"Sissala": "sld", +"Sholaga": "sle", +"Swiss-Italian Sign Language": "slf", +"SelungaiMurut": "slg", +"SouthernPuget Sound Salish": "slh", +"Lower Silesian": "sli", +"Salumá": "slj", +"Slovak": "slk", +"Salt-Yui": "sll", +"PangutaranSama": "slm", +"Salinan": "sln", +"Lamaholot": "slp", +"Salchuq": "slq", +"Salar": "slr", +"SingaporeSign Language": "sls", +"Sila": "slt", +"Selaru": "slu", +"Slovenian": "slv", +"Sialum": "slw", +"Salampasu": "slx", +"Selayar": "sly", +"Ma'ya": "slz", +"SouthernSami": "sma", +"Simbari": "smb", +"Som": "smc", +"Sama": "smd", +"Northern Sami": "sme", +"Auwe": "smf", +"Simbali": "smg", +"Samei": "smh", +"LuleSami": "smj", +"Bolinao": "smk", +"CentralSama": "sml", +"Musasa": "smm", +"InariSami": "smn", +"Samoan": "smo", +"Samaritan": "smp", +"Samo": "smq", +"Simeulue": "smr", +"SkoltSami": "sms", +"Simte": "smt", +"Somray": "smu", +"Samvedi": "smv", +"Sumbawa": "smw", +"Samba": "smx", +"Semnani": "smy", +"Simeku": "smz", +"Shona": "sna", +"Sebuyau": "snb", +"Sinaugoro": "snc", +"Sindhi": "snd", +"Bau Bidayuh": "sne", +"Noon": "snf", +"Sanga (Democratic Republic of Congo)": "sng", +"Sensi": "sni", +"RiverainSango": "snj", +"Soninke": "snk", +"Sangil": "snl", +"SouthernMa'di": "snm", +"Siona": "snn", +"Snohomish": "sno", +"Siane": "snp", +"Sangu (Gabon)": "snq", +"Sihan": "snr", +"SouthWest Bay": "sns", +"Senggi": "snu", +"Sa'ban": "snv", +"Selee": "snw", +"Sam": "snx", +"Saniyo-Hiyewe": "sny", +"Sinsauru": "snz", +"Thai Song": "soa", +"Sobei": "sob", +"So(Democratic Republic of Congo)": "soc", +"Songoora": "sod", +"Songomeno": "soe", +"Sogdian": "sog", +"Aka": "soh", +"Sonha": "soi", +"Soi": "soj", +"Sokoro": "sok", +"Solos": "sol", +"Somali": "som", +"Songo": "soo", +"Songe": "sop", +"Kanasi": "soq", +"Somrai": "sor", +"Seeku": "sos", +"SouthernSotho": "sot", +"SouthernThai": "sou", +"Sonsorol": "sov", +"Sowanda": "sow", +"So (Cameroon)": "sox", +"Miyobe": "soy", +"Temi": "soz", +"Spanish": "spa", +"Sepa (Indonesia)": "spb", +"Sapé": "spc", +"Saep": "spd", +"Sepa(Papua New Guinea)": "spe", +"Sian": "spg", +"Saponi": "spi", +"Sengo": "spk", +"Selepet": "spl", +"Sepen": "spm", +"Sanapaná": "spn", +"Spokane": "spo", +"SupyireSenoufo": "spp", +"Loreto-UcayaliSpanish": "spq", +"Saparua": "spr", +"Saposa": "sps", +"SpitiBhoti": "spt", +"Sapuan": "spu", +"Sambalpuri": "spv", +"SouthPicene": "spx", +"Sabaot": "spy", +"Shama-Sambuga": "sqa", +"Shau": "sqh", +"Albanian": "sqi", +"Albanian Sign Language": "sqk", +"Suma": "sqm", +"Susquehannock": "sqn", +"Sorkhei": "sqo", +"Sou": "sqq", +"SiculoArabic": "sqr", +"Sri Lankan Sign Language": "sqs", +"Soqotri": "sqt", +"Squamish": "squ", +"Kufr Qassem Sign Language (KQSL)": "sqx", +"Saruga": "sra", +"Sora": "srb", +"LogudoreseSardinian": "src", +"Sardinian": "srd", +"Sara": "sre", +"Nafi": "srf", +"Sulod": "srg", +"Sarikoli": "srh", +"Siriano": "sri", +"SerudungMurut": "srk", +"Isirawa": "srl", +"Saramaccan": "srm", +"SrananTongo": "srn", +"CampidaneseSardinian": "sro", +"Serbian": "srp", +"Sirionó": "srq", +"Serer": "srr", +"Sarsi": "srs", +"Sauri": "srt", +"Suruí": "sru", +"SouthernSorsoganon": "srv", +"Serua": "srw", +"Sirmauri": "srx", +"Sera": "sry", +"Shahmirzadi": "srz", +"Southern Sama": "ssb", +"Suba-Simbiti": "ssc", +"Siroi": "ssd", +"Balangingi": "sse", +"Thao": "ssf", +"Seimat": "ssg", +"ShihhiArabic": "ssh", +"Sansi": "ssi", +"Sausi": "ssj", +"Sunam": "ssk", +"WesternSisaala": "ssl", +"Semnam": "ssm", +"Waata": "ssn", +"Sissano": "sso", +"Spanish Sign Language": "ssp", +"So'a": "ssq", +"Swiss-French Sign Language": "ssr", +"Sô": "sss", +"Sinasina": "sst", +"Susuami": "ssu", +"SharkBay": "ssv", +"Swati": "ssw", +"Samberigi": "ssx", +"Saho": "ssy", +"Sengseng": "ssz", +"Settla": "sta", +"Northern Subanen": "stb", +"Sentinel": "std", +"Liana-Seti": "ste", +"Seta": "stf", +"Trieng": "stg", +"Shelta": "sth", +"BuloStieng": "sti", +"MatyaSamo": "stj", +"Arammba": "stk", +"Stellingwerfs": "stl", +"Setaman": "stm", +"Owa": "stn", +"Stoney": "sto", +"Southeastern Tepehuan": "stp", +"Saterfriesisch": "stq", +"StraitsSalish": "str", +"Shumashti": "sts", +"BudehStieng": "stt", +"Samtao": "stu", +"Silt'e": "stv", +"Satawalese": "stw", +"Siberian Tatar": "sty", +"Sulka": "sua", +"Suku": "sub", +"WesternSubanon": "suc", +"Suena": "sue", +"Suganga": "sug", +"Suki": "sui", +"Shubi": "suj", +"Sukuma": "suk", +"Sundanese": "sun", +"Bouni": "suo", +"Suri": "suq", +"Mwaghavul": "sur", +"Susu": "sus", +"Subtiaba": "sut", +"Sulung": "suv", +"Sumbwa": "suw", +"Sumerian": "sux", +"Suyá": "suy", +"Sunwar": "suz", +"Svan": "sva", +"Ulau-Suain": "svb", +"Vincentian Creole English": "svc", +"Serili": "sve", +"SlovakianSign Language": "svk", +"Slavomolisano": "svm", +"Savosavo": "svs", +"Skalvian": "svx", +"Swahili(macrolanguage)": "swa", +"MaoreComorian": "swb", +"CongoSwahili": "swc", +"Swedish": "swe", +"Sere": "swf", +"Swabian": "swg", +"Swahili(individual language)": "swh", +"Sui": "swi", +"Sira": "swj", +"Malawi Sena": "swk", +"SwedishSign Language": "swl", +"Samosa": "swm", +"Sawknah": "swn", +"Shanenawa": "swo", +"Suau": "swp", +"Sharwa": "swq", +"Saweru": "swr", +"Seluwasan": "sws", +"Sawila": "swt", +"Suwawa": "swu", +"Shekhawati": "swv", +"Sowa": "sww", +"Suruahá": "swx", +"Sarua": "swy", +"Suba": "sxb", +"Sicanian": "sxc", +"Sighu": "sxe", +"Shixing": "sxg", +"SouthernKalapuya": "sxk", +"Selian": "sxl", +"Samre": "sxm", +"Sangir": "sxn", +"Sorothaptic": "sxo", +"Saaroa": "sxr", +"Sasaru": "sxs", +"Upper Saxon": "sxu", +"SaxweGbe": "sxw", +"Siang": "sya", +"Central Subanen": "syb", +"ClassicalSyriac": "syc", +"Seki": "syi", +"Sukur": "syk", +"Sylheti": "syl", +"MayaSamo": "sym", +"Senaya": "syn", +"Suoy": "syo", +"Syriac": "syr", +"Sinyar": "sys", +"Kagate": "syw", +"Samay": "syx", +"Al-Sayyid Bedouin Sign Language": "syy", +"Semelai": "sza", +"Ngalum": "szb", +"SemaqBeri": "szc", +"Seru": "szd", +"Seze": "sze", +"Sengele": "szg", +"Silesian": "szl", +"Sula": "szn", +"Suabo": "szp", +"Solomon Islands Sign Language": "szs", +"Isu(Fako Division)": "szv", +"Sawai": "szw", +"Sakizaya": "szy", +"Lower Tanana": "taa", +"Tabassaran": "tab", +"LowlandTarahumara": "tac", +"Tause": "tad", +"Tariana": "tae", +"Tapirapé": "taf", +"Tagoi": "tag", +"Tahitian": "tah", +"Eastern Tamang": "taj", +"Tala": "tak", +"Tal": "tal", +"Tamil": "tam", +"Tangale": "tan", +"Yami": "tao", +"Taabwa": "tap", +"Tamasheq": "taq", +"Central Tarahumara": "tar", +"TayBoi": "tas", +"Tatar": "tat", +"Upper Tanana": "tau", +"Tatuyo": "tav", +"Tai": "taw", +"Tamki": "tax", +"Atayal": "tay", +"Tocho": "taz", +"Aikanã": "tba", +"Takia": "tbc", +"KakiAe": "tbd", +"Tanimbili": "tbe", +"Mandara": "tbf", +"NorthTairora": "tbg", +"Thurawal": "tbh", +"Gaam": "tbi", +"Tiang": "tbj", +"Calamian Tagbanwa": "tbk", +"Tboli": "tbl", +"Tagbu": "tbm", +"BarroNegro Tunebo": "tbn", +"Tawala": "tbo", +"Taworta": "tbp", +"Tumtum": "tbr", +"Tanguat": "tbs", +"Tembo (Kitembo)": "tbt", +"Tubar": "tbu", +"Tobo": "tbv", +"Tagbanwa": "tbw", +"Kapin": "tbx", +"Tabaru": "tby", +"Ditammari": "tbz", +"Ticuna": "tca", +"Tanacross": "tcb", +"Datooga": "tcc", +"Tafi": "tcd", +"Southern Tutchone": "tce", +"Malinaltepec Me'phaa": "tcf", +"Tamagario": "tcg", +"Turks And Caicos Creole English": "tch", +"Wára": "tci", +"Tchitchege": "tck", +"Taman (Myanmar)": "tcl", +"Tanahmerah": "tcm", +"Tichurong": "tcn", +"Taungyo": "tco", +"TawrChin": "tcp", +"Kaiy": "tcq", +"TorresStrait Creole": "tcs", +"T'en": "tct", +"SoutheasternTarahumara": "tcu", +"TecpatlánTotonac": "tcw", +"Toda": "tcx", +"Tulu": "tcy", +"ThadoChin": "tcz", +"Tagdal": "tda", +"Panchpargania": "tdb", +"Emberá-Tadó": "tdc", +"Tai Nüa": "tdd", +"Tiranige Diga Dogon": "tde", +"Talieng": "tdf", +"Western Tamang": "tdg", +"Thulung": "tdh", +"Tomadino": "tdi", +"Tajio": "tdj", +"Tambas": "tdk", +"Sur": "tdl", +"Taruma": "tdm", +"Tondano": "tdn", +"Teme": "tdo", +"Tita": "tdq", +"Todrah": "tdr", +"Doutai": "tds", +"TetunDili": "tdt", +"Toro": "tdv", +"Tandroy-Mahafaly Malagasy": "tdx", +"Tadyawan": "tdy", +"Temiar": "tea", +"Tetete": "teb", +"Terik": "tec", +"TepoKrumen": "ted", +"HuehuetlaTepehua": "tee", +"Teressa": "tef", +"Teke-Tege": "teg", +"Tehuelche": "teh", +"Torricelli": "tei", +"Ibali Teke": "tek", +"Telugu": "tel", +"Timne": "tem", +"Tama (Colombia)": "ten", +"Teso": "teo", +"Tepecano": "tep", +"Temein": "teq", +"Tereno": "ter", +"Tengger": "tes", +"Tetum": "tet", +"Soo": "teu", +"Teor": "tev", +"Tewa(USA)": "tew", +"Tennet": "tex", +"Tulishi": "tey", +"Tetserret": "tez", +"TofinGbe": "tfi", +"Tanaina": "tfn", +"Tefaro": "tfo", +"Teribe": "tfr", +"Ternate": "tft", +"Sagalla": "tga", +"Tobilung": "tgb", +"Tigak": "tgc", +"Ciwogai": "tgd", +"Eastern Gorkha Tamang": "tge", +"Chalikha": "tgf", +"TobagonianCreole English": "tgh", +"Lawunuia": "tgi", +"Tagin": "tgj", +"Tajik": "tgk", +"Tagalog": "tgl", +"Tandaganon": "tgn", +"Sudest": "tgo", +"Tangoa": "tgp", +"Tring": "tgq", +"Tareng": "tgr", +"Nume": "tgs", +"CentralTagbanwa": "tgt", +"Tanggu": "tgu", +"Tingui-Boto": "tgv", +"TagwanaSenoufo": "tgw", +"Tagish": "tgx", +"Togoyo": "tgy", +"Tagalaka": "tgz", +"Thai": "tha", +"Thayore": "thd", +"Chitwania Tharu": "the", +"Thangmi": "thf", +"NorthernTarahumara": "thh", +"TaiLong": "thi", +"Tharaka": "thk", +"DangauraTharu": "thl", +"Aheu": "thm", +"Thachanadan": "thn", +"Thompson": "thp", +"KochilaTharu": "thq", +"RanaTharu": "thr", +"Thakali": "ths", +"Tahltan": "tht", +"Thuri": "thu", +"Tahaggart Tamahaq": "thv", +"Tha": "thy", +"TayartTamajeq": "thz", +"Tidikelt Tamazight": "tia", +"Tira": "tic", +"Tifal": "tif", +"Tigre": "tig", +"TimugonMurut": "tih", +"Tiene": "tii", +"Tilung": "tij", +"Tikar": "tik", +"Tillamook": "til", +"Timbe": "tim", +"Tindi": "tin", +"Teop": "tio", +"Trimuris": "tip", +"Tiéfo": "tiq", +"Tigrinya": "tir", +"MasadiitItneg": "tis", +"Tinigua": "tit", +"Adasen": "tiu", +"Tiv": "tiv", +"Tiwi": "tiw", +"SouthernTiwa": "tix", +"Tiruray": "tiy", +"Tai Hongjin": "tiz", +"Tajuasohn": "tja", +"Tunjung": "tjg", +"Northern Tujia": "tji", +"Tjungundji": "tjj", +"Tai Laing": "tjl", +"Timucua": "tjm", +"Tonjon": "tjn", +"Temacine Tamazight": "tjo", +"Tjupany": "tjp", +"SouthernTujia": "tjs", +"Tjurruru": "tju", +"Djabwurrung": "tjw", +"Truká": "tka", +"Buksa": "tkb", +"Tukudede": "tkd", +"Takwane": "tke", +"Tukumanféd": "tkf", +"Tesaka Malagasy": "tkg", +"Tokelau": "tkl", +"Takelma": "tkm", +"Toku-No-Shima": "tkn", +"Tikopia": "tkp", +"Tee": "tkq", +"Tsakhur": "tkr", +"Takestani": "tks", +"Kathoriya Tharu": "tkt", +"UpperNecaxa Totonac": "tku", +"Mur Pano": "tkv", +"Teanu": "tkw", +"Tangko": "tkx", +"Takua": "tkz", +"SouthwesternTepehuan": "tla", +"Tobelo": "tlb", +"Yecuatla Totonac": "tlc", +"Talaud": "tld", +"Telefol": "tlf", +"Tofanma": "tlg", +"Klingon": "tlh", +"Tlingit": "tli", +"Talinga-Bwisi": "tlj", +"Taloki": "tlk", +"Tetela": "tll", +"Tolomako": "tlm", +"Talondo'": "tln", +"Talodi": "tlo", +"Filomena Mata-Coahuitlán Totonac": "tlp", +"TaiLoi": "tlq", +"Talise": "tlr", +"Tambotalo": "tls", +"Teluti": "tlt", +"Tulehu": "tlu", +"Taliabu": "tlv", +"Khehek": "tlx", +"Talysh": "tly", +"Tama(Chad)": "tma", +"Katbol": "tmb", +"Tumak": "tmc", +"Haruai": "tmd", +"Tremembé": "tme", +"Toba-Maskoy": "tmf", +"Ternateño": "tmg", +"Tamashek": "tmh", +"Tutuba": "tmi", +"Samarokena": "tmj", +"NorthwesternTamang": "tmk", +"Tamnim Citak": "tml", +"TaiThanh": "tmm", +"Taman(Indonesia)": "tmn", +"Temoq": "tmo", +"Tumleo": "tmq", +"Jewish Babylonian Aramaic (ca. 200-1200 CE)": "tmr", +"Tima": "tms", +"Tasmate": "tmt", +"Iau": "tmu", +"Tembo(Motembo)": "tmv", +"Temuan": "tmw", +"Tami": "tmy", +"Tamanaku": "tmz", +"Tacana": "tna", +"Western Tunebo": "tnb", +"Tanimuca-Retuarã": "tnc", +"AngosturasTunebo": "tnd", +"Tobanga": "tng", +"Maiani": "tnh", +"Tandia": "tni", +"Kwamera": "tnk", +"Lenakel": "tnl", +"Tabla": "tnm", +"North Tanna": "tnn", +"Toromono": "tno", +"Whitesands": "tnp", +"Taino": "tnq", +"Bedik": "tnr", +"Tenis": "tns", +"Tontemboan": "tnt", +"TayKhang": "tnu", +"Tangchangya": "tnv", +"Tonsawang": "tnw", +"Tanema": "tnx", +"Tongwe": "tny", +"Tonga(Thailand)": "tnz", +"Toba": "tob", +"CoyutlaTotonac": "toc", +"Toma": "tod", +"Gizrra": "tof", +"Tonga(Nyasa)": "tog", +"Gitonga": "toh", +"Tonga (Zambia)": "toi", +"Tojolabal": "toj", +"Tolowa": "tol", +"Tombulu": "tom", +"Tonga(Tonga Islands)": "ton", +"Xicotepec De Juárez Totonac": "too", +"Papantla Totonac": "top", +"Toposa": "toq", +"Togbo-Vara Banda": "tor", +"Highland Totonac": "tos", +"Tho": "tou", +"Upper Taromi": "tov", +"Jemez": "tow", +"Tobian": "tox", +"Topoiyo": "toy", +"To": "toz", +"Taupota": "tpa", +"AzoyúMe'phaa": "tpc", +"Tippera": "tpe", +"Tarpia": "tpf", +"Kula": "tpg", +"TokPisin": "tpi", +"Tapieté": "tpj", +"Tupinikin": "tpk", +"Tlacoapa Me'phaa": "tpl", +"Tampulma": "tpm", +"Tupinambá": "tpn", +"TaiPao": "tpo", +"PisafloresTepehua": "tpp", +"Tukpa": "tpq", +"Tuparí": "tpr", +"TlachichilcoTepehua": "tpt", +"Tampuan": "tpu", +"Tanapag": "tpv", +"Tupí": "tpw", +"AcatepecMe'phaa": "tpx", +"Trumai": "tpy", +"Tinputz": "tpz", +"Tembé": "tqb", +"Lehali": "tql", +"Turumsa": "tqm", +"Tenino": "tqn", +"Toaripi": "tqo", +"Tomoip": "tqp", +"Tunni": "tqq", +"Torona": "tqr", +"WesternTotonac": "tqt", +"Touo": "tqu", +"Tonkawa": "tqw", +"Tirahi": "tra", +"Terebu": "trb", +"Copala Triqui": "trc", +"Turi": "trd", +"EastTarangan": "tre", +"Trinidadian Creole English": "trf", +"LishánDidán": "trg", +"Turaka": "trh", +"Trió": "tri", +"Toram": "trj", +"TravellerScottish": "trl", +"Tregami": "trm", +"Trinitario": "trn", +"TaraoNaga": "tro", +"KokBorok": "trp", +"San Martín Itunyoso Triqui": "trq", +"Taushiro": "trr", +"ChicahuaxtlaTriqui": "trs", +"Tunggare": "trt", +"Turoyo": "tru", +"Taroko": "trv", +"Torwali": "trw", +"Tringgus-Sembaan Bidayuh": "trx", +"Turung": "try", +"Torá": "trz", +"Tsaangi": "tsa", +"Tsamai": "tsb", +"Tswa": "tsc", +"Tsakonian": "tsd", +"TunisianSign Language": "tse", +"Tausug": "tsg", +"Tsuvan": "tsh", +"Tsimshian": "tsi", +"Tshangla": "tsj", +"Tseku": "tsk", +"Ts'ün-Lao": "tsl", +"TurkishSign Language": "tsm", +"Tswana": "tsn", +"Tsonga": "tso", +"NorthernToussian": "tsp", +"ThaiSign Language": "tsq", +"Akei": "tsr", +"TaiwanSign Language": "tss", +"Tondi Songway Kiini": "tst", +"Tsou": "tsu", +"Tsogo": "tsv", +"Tsishingini": "tsw", +"Mubami": "tsx", +"TebulSign Language": "tsy", +"Purepecha": "tsz", +"Tutelo": "tta", +"Gaa": "ttb", +"Tektiteko": "ttc", +"Tauade": "ttd", +"Bwanabwana": "tte", +"Tuotomb": "ttf", +"Tutong": "ttg", +"UpperTa'oih": "tth", +"Tobati": "tti", +"Tooro": "ttj", +"Totoro": "ttk", +"Totela": "ttl", +"NorthernTutchone": "ttm", +"Towei": "ttn", +"LowerTa'oih": "tto", +"Tombelala": "ttp", +"TawallammatTamajaq": "ttq", +"Tera": "ttr", +"NortheasternThai": "tts", +"MuslimTat": "ttt", +"Torau": "ttu", +"Titan": "ttv", +"LongWat": "ttw", +"Sikaritai": "tty", +"Tsum": "ttz", +"Wiarumus": "tua", +"Tübatulabal": "tub", +"Mutu": "tuc", +"Tuxá": "tud", +"Tuyuca": "tue", +"CentralTunebo": "tuf", +"Tunia": "tug", +"Taulil": "tuh", +"Tupuri": "tui", +"Tugutil": "tuj", +"Turkmen": "tuk", +"Tula": "tul", +"Tumbuka": "tum", +"Tunica": "tun", +"Tucano": "tuo", +"Tedaga": "tuq", +"Turkish": "tur", +"Tuscarora": "tus", +"Tututni": "tuu", +"Turkana": "tuv", +"Tuxináwa": "tux", +"Tugen": "tuy", +"Turka": "tuz", +"Vaghua": "tva", +"Tsuvadi": "tvd", +"Te'un": "tve", +"SoutheastAmbrym": "tvk", +"Tuvalu": "tvl", +"Tela-Masbuar": "tvm", +"Tavoyan": "tvn", +"Tidore": "tvo", +"Taveta": "tvs", +"Tutsa Naga": "tvt", +"Tunen": "tvu", +"Sedoa": "tvw", +"Taivoan": "tvx", +"Timor Pidgin": "tvy", +"Twana": "twa", +"WesternTawbuid": "twb", +"Teshenawa": "twc", +"Twents": "twd", +"Tewa (Indonesia)": "twe", +"NorthernTiwa": "twf", +"Tereweng": "twg", +"TaiDón": "twh", +"Twi": "twi", +"Tawara": "twl", +"TawangMonpa": "twm", +"Twendi": "twn", +"Tswapong": "two", +"Ere": "twp", +"Tasawaq": "twq", +"Southwestern Tarahumara": "twr", +"Turiwára": "twt", +"Termanu": "twu", +"Tuwari": "tww", +"Tewe": "twx", +"Tawoyan": "twy", +"Tombonuo": "txa", +"TokharianB": "txb", +"Tsetsaut": "txc", +"Totoli": "txe", +"Tangut": "txg", +"Thracian": "txh", +"Ikpeng": "txi", +"Tarjumo": "txj", +"Tomini": "txm", +"WestTarangan": "txn", +"Toto": "txo", +"Tii": "txq", +"Tartessian": "txr", +"Tonsea": "txs", +"Citak": "txt", +"Kayapó": "txu", +"Tatana": "txx", +"TanosyMalagasy": "txy", +"Tauya": "tya", +"Kyenga": "tye", +"O'du": "tyh", +"Teke-Tsaayi": "tyi", +"TaiDo": "tyj", +"Thu Lao": "tyl", +"Kombai": "tyn", +"Thaypan": "typ", +"TaiDaeng": "tyr", +"TàySa Pa": "tys", +"TàyTac": "tyt", +"Kua": "tyu", +"Tuvinian": "tyv", +"Teke-Tyee": "tyx", +"Tiyaa": "tyy", +"Tày": "tyz", +"Tanzanian Sign Language": "tza", +"Tzeltal": "tzh", +"Tz'utujil": "tzj", +"Talossan": "tzl", +"Central Atlas Tamazight": "tzm", +"Tugun": "tzn", +"Tzotzil": "tzo", +"Tabriak": "tzx", +"Uamué": "uam", +"Kuan": "uan", +"Tairuma": "uar", +"Ubang": "uba", +"Ubi": "ubi", +"Buhi'nonBikol": "ubl", +"Ubir": "ubr", +"Umbu-Ungu": "ubu", +"Ubykh": "uby", +"Uda": "uda", +"Udihe": "ude", +"Muduga": "udg", +"Udi": "udi", +"Ujir": "udj", +"Wuzlam": "udl", +"Udmurt": "udm", +"Uduk": "udu", +"Kioko": "ues", +"Ufim": "ufi", +"Ugaritic": "uga", +"Kuku-Ugbanh": "ugb", +"Ughele": "uge", +"Ugandan Sign Language": "ugn", +"Ugong": "ugo", +"UruguayanSign Language": "ugy", +"Uhami": "uha", +"Damal": "uhn", +"Uighur": "uig", +"Uisai": "uis", +"Iyive": "uiv", +"Tanjijili": "uji", +"Kaburi": "uka", +"Ukuriguma": "ukg", +"Ukhwejo": "ukh", +"Kui (India)": "uki", +"Muak Sa-aak": "ukk", +"Ukrainian Sign Language": "ukl", +"Ukpe-Bayobiri": "ukp", +"Ukwa": "ukq", +"Ukrainian": "ukr", +"Urubú-Kaapor Sign Language": "uks", +"Ukue": "uku", +"Kuku": "ukv", +"Ukwuani-Aboh-Ndoni": "ukw", +"Kuuk-Yak": "uky", +"Fungwa": "ula", +"Ulukwumi": "ulb", +"Ulch": "ulc", +"Lule": "ule", +"Usku": "ulf", +"Ulithian": "uli", +"Meriam": "ulk", +"Ullatan": "ull", +"Ulumanda'": "ulm", +"Unserdeutsch": "uln", +"Uma'Lung": "ulu", +"Ulwa": "ulw", +"Umatilla": "uma", +"Umbundu": "umb", +"Marrucinian": "umc", +"Umbindhamu": "umd", +"Umbuygamu": "umg", +"Ukit": "umi", +"Umon": "umm", +"MakyanNaga": "umn", +"Umotína": "umo", +"Umpila": "ump", +"Umbugarla": "umr", +"Pendau": "ums", +"Munsee": "umu", +"NorthWatut": "una", +"Undetermined": "und", +"Uneme": "une", +"Ngarinyin": "ung", +"Uni": "uni", +"Enawené-Nawé": "unk", +"Unami": "unm", +"Kurnai": "unn", +"Mundari": "unr", +"Unubahe": "unu", +"Munda": "unx", +"UndeKaili": "unz", +"Umeda": "upi", +"Uripiv-Wala-Rano-Atchin": "upv", +"Urarina": "ura", +"Urubú-Kaapor": "urb", +"Urningangg": "urc", +"Urdu": "urd", +"Uru": "ure", +"Uradhi": "urf", +"Urigina": "urg", +"Urhobo": "urh", +"Urim": "uri", +"Urak Lawoi'": "urk", +"Urali": "url", +"Urapmin": "urm", +"Uruangnirin": "urn", +"Ura (Papua New Guinea)": "uro", +"Uru-Pa-In": "urp", +"Lehalurup": "urr", +"Urat": "urt", +"Urumi": "uru", +"Uruava": "urv", +"Sop": "urw", +"Urimo": "urx", +"Orya": "ury", +"Uru-Eu-Wau-Wau": "urz", +"Usarufa": "usa", +"Ushojo": "ush", +"Usui": "usi", +"Usaghade": "usk", +"Uspanteco": "usp", +"us-Saare": "uss", +"Uya": "usu", +"Otank": "uta", +"Ute-SouthernPaiute": "ute", +"ut-Hun": "uth", +"Amba(Solomon Islands)": "utp", +"Etulo": "utr", +"Utu": "utu", +"Urum": "uum", +"Kulon-Pazeh": "uun", +"Ura(Vanuatu)": "uur", +"U": "uuu", +"West Uvean": "uve", +"Uri": "uvh", +"Lote": "uvl", +"Kuku-Uwanh": "uwa", +"Doko-Uyanga": "uya", +"Uzbek": "uzb", +"Northern Uzbek": "uzn", +"SouthernUzbek": "uzs", +"Vaagri Booli": "vaa", +"Vale": "vae", +"Vafsi": "vaf", +"Vagla": "vag", +"Varhadi-Nagpuri": "vah", +"Vai": "vai", +"Vasekela Bushman": "vaj", +"Vehes": "val", +"Vanimo": "vam", +"Valman": "van", +"Vao": "vao", +"Vaiphei": "vap", +"Huarijio": "var", +"Vasavi": "vas", +"Vanuma": "vau", +"Varli": "vav", +"Wayu": "vay", +"Southeast Babar": "vbb", +"SouthwesternBontok": "vbk", +"Venetian": "vec", +"Veddah": "ved", +"Veluws": "vel", +"Vemgo-Mabas": "vem", +"Venda": "ven", +"Ventureño": "veo", +"Veps": "vep", +"MomJango": "ver", +"Vaghri": "vgr", +"VlaamseGebarentaal": "vgt", +"Virgin Islands Creole English": "vic", +"Vidunda": "vid", +"Vietnamese": "vie", +"Vili": "vif", +"Viemo": "vig", +"Vilela": "vil", +"Vinza": "vin", +"Vishavan": "vis", +"Viti": "vit", +"Iduna": "viv", +"Kariyarra": "vka", +"Kujarge": "vkj", +"Kaur": "vkk", +"Kulisusu": "vkl", +"Kamakan": "vkm", +"Koro Nulu": "vkn", +"Kodeoha": "vko", +"Korlai Creole Portuguese": "vkp", +"TenggarongKutai Malay": "vkt", +"Kurrama": "vku", +"Koro Zuba": "vkz", +"Valpei": "vlp", +"Vlaams": "vls", +"Martuyhunira": "vma", +"Mbabaram": "vmb", +"JuxtlahuacaMixtec": "vmc", +"MuduKoraga": "vmd", +"East Masela": "vme", +"Mainfränkisch": "vmf", +"Minigir": "vmg", +"Maraghei": "vmh", +"Miwa": "vmi", +"IxtayutlaMixtec": "vmj", +"Makhuwa-Shirima": "vmk", +"Malgana": "vml", +"MitlatongoMixtec": "vmm", +"Soyaltepec Mazatec": "vmp", +"SoyaltepecMixtec": "vmq", +"Marenje": "vmr", +"Moksela": "vms", +"Muluridyi": "vmu", +"ValleyMaidu": "vmv", +"Makhuwa": "vmw", +"TamazolaMixtec": "vmx", +"AyautlaMazatec": "vmy", +"MazatlánMazatec": "vmz", +"Vano": "vnk", +"Vinmavis": "vnm", +"Vunapu": "vnp", +"Volapük": "vol", +"Voro": "vor", +"Votic": "vot", +"Vera'a": "vra", +"Võro": "vro", +"Varisi": "vrs", +"Burmbar": "vrt", +"MoldovaSign Language": "vsi", +"Venezuelan Sign Language": "vsl", +"ValencianSign Language": "vsv", +"Vitou": "vto", +"Vumbu": "vum", +"Vunjo": "vun", +"Vute": "vut", +"Awa(China)": "vwa", +"Walla Walla": "waa", +"Wab": "wab", +"Wasco-Wishram": "wac", +"Wandamen": "wad", +"Walser": "wae", +"Wakoná": "waf", +"Wa'ema": "wag", +"Watubela": "wah", +"Wares": "wai", +"Waffa": "waj", +"Wolaytta": "wal", +"Wampanoag": "wam", +"Wan": "wan", +"Wappo": "wao", +"Wapishana": "wap", +"Wageman": "waq", +"Waray (Philippines)": "war", +"Washo": "was", +"Kaninuwa": "wat", +"Waurá": "wau", +"Waka": "wav", +"Waiwai": "waw", +"Watam": "wax", +"Wayana": "way", +"Wampur": "waz", +"Warao": "wba", +"Wabo": "wbb", +"Waritai": "wbe", +"Wara": "wbf", +"Wanda": "wbh", +"Vwanji": "wbi", +"Alagwa": "wbj", +"Waigali": "wbk", +"Wakhi": "wbl", +"Wa": "wbm", +"Warlpiri": "wbp", +"Waddar": "wbq", +"Wagdi": "wbr", +"West Bengal Sign Language": "wbs", +"Wanman": "wbt", +"Wajarri": "wbv", +"Woi": "wbw", +"Yanomámi": "wca", +"WaciGbe": "wci", +"Wandji": "wdd", +"Wadaginam": "wdg", +"Wadjiginy": "wdj", +"Wadikali": "wdk", +"Wadjigu": "wdu", +"Wadjabangayi": "wdy", +"Wewaw": "wea", +"Wè Western": "wec", +"Wedau": "wed", +"Wergaia": "weg", +"Weh": "weh", +"Were": "wei", +"WemeGbe": "wem", +"North Wemale": "weo", +"Westphalien": "wep", +"Weri": "wer", +"CameroonPidgin": "wes", +"Perai": "wet", +"Welaung": "weu", +"Wejewa": "wew", +"Yafi": "wfg", +"Wagaya": "wga", +"Wagawaga": "wgb", +"Wangganguru": "wgg", +"Wahgi": "wgi", +"Waigeo": "wgo", +"Wirangu": "wgu", +"Warrgamay": "wgy", +"Manusela": "wha", +"NorthWahgi": "whg", +"Wahau Kenyah": "whk", +"WahauKayan": "whu", +"Southern Toussian": "wib", +"Wichita": "wic", +"Wik-Epa": "wie", +"Wik-Keyangan": "wif", +"Wik-Ngathana": "wig", +"Wik-Me'anha": "wih", +"Minidien": "wii", +"Wik-Iiyanh": "wij", +"Wikalkan": "wik", +"Wilawila": "wil", +"Wik-Mungkan": "wim", +"Ho-Chunk": "win", +"Wiraféd": "wir", +"Wiru": "wiu", +"Muduapa": "wiv", +"Wiyot": "wiy", +"Waja": "wja", +"Warji": "wji", +"Kw'adza": "wka", +"Kumbaran": "wkb", +"Wakde": "wkd", +"Kalanadi": "wkl", +"Keerray-Woorroong": "wkr", +"Kunduvadi": "wku", +"Wakawaka": "wkw", +"Wangkayutyuru": "wky", +"Walio": "wla", +"MwaliComorian": "wlc", +"Wolane": "wle", +"Kunbarlang": "wlg", +"Welaun": "wlh", +"Waioli": "wli", +"Wailaki": "wlk", +"Wali(Sudan)": "wll", +"Middle Welsh": "wlm", +"Walloon": "wln", +"Wolio": "wlo", +"Wailapa": "wlr", +"Wallisian": "wls", +"Wuliwuli": "wlu", +"Wichí Lhamtés Vejoz": "wlv", +"Walak": "wlw", +"Wali (Ghana)": "wlx", +"Waling": "wly", +"Mawa(Nigeria)": "wma", +"Wambaya": "wmb", +"Wamas": "wmc", +"Mamaindé": "wmd", +"Wambule": "wme", +"Western Minyag": "wmg", +"Waima'a": "wmh", +"Wamin": "wmi", +"Maiwa(Indonesia)": "wmm", +"Waamwang": "wmn", +"Wom (Papua New Guinea)": "wmo", +"Wambon": "wms", +"Walmajarri": "wmt", +"Mwani": "wmw", +"Womo": "wmx", +"Wanambre": "wnb", +"Wantoat": "wnc", +"Wandarang": "wnd", +"Waneci": "wne", +"Wanggom": "wng", +"NdzwaniComorian": "wni", +"Wanukaka": "wnk", +"Wanggamala": "wnm", +"Wunumara": "wnn", +"Wano": "wno", +"Wanap": "wnp", +"Usan": "wnu", +"Wintu": "wnw", +"Wanyi": "wny", +"Tyaraity": "woa", +"WèNorthern": "wob", +"Wogeo": "woc", +"Wolani": "wod", +"Woleaian": "woe", +"GambianWolof": "wof", +"Wogamusin": "wog", +"Kamang": "woi", +"Longto": "wok", +"Wolof": "wol", +"Wom(Nigeria)": "wom", +"Wongo": "won", +"Manombai": "woo", +"Woria": "wor", +"Hanga Hundi": "wos", +"Wawonii": "wow", +"Weyto": "woy", +"Maco": "wpc", +"Warluwara": "wrb", +"Warduji": "wrd", +"Warungu": "wrg", +"Wiradhuri": "wrh", +"Wariyangga": "wri", +"Garrwa": "wrk", +"Warlmanpa": "wrl", +"Warumungu": "wrm", +"Warnang": "wrn", +"Worrorra": "wro", +"Waropen": "wrp", +"Wardaman": "wrr", +"Waris": "wrs", +"Waru": "wru", +"Waruna": "wrv", +"Gugu Warra": "wrw", +"Wae Rana": "wrx", +"Merwari": "wry", +"Waray(Australia)": "wrz", +"Warembori": "wsa", +"Adilabad Gondi": "wsg", +"Wusi": "wsi", +"Waskia": "wsk", +"Owenia": "wsr", +"Wasa": "wss", +"Wasu": "wsu", +"Wotapuri-Katarqalai": "wsv", +"Dumpu": "wtf", +"Wathawurrung": "wth", +"Berta": "wti", +"Watakataui": "wtk", +"Mewati": "wtm", +"Wotu": "wtw", +"Wikngenchera": "wua", +"Wunambal": "wub", +"Wudu": "wud", +"Wutunhua": "wuh", +"Silimo": "wul", +"Wumbvu": "wum", +"Bungu": "wun", +"Wurrugu": "wur", +"Wutung": "wut", +"WuChinese": "wuu", +"Wuvulu-Aua": "wuv", +"Wulna": "wux", +"Wauyai": "wuy", +"Waama": "wwa", +"Wakabunga": "wwb", +"Wetamut": "wwo", +"Warrwa": "wwr", +"Wawa": "www", +"Waxianghua": "wxa", +"Wardandi": "wxw", +"Wyandot": "wya", +"Wangaaybuwan-Ngiyambaa": "wyb", +"Woiwurrung": "wyi", +"Wymysorys": "wym", +"Wayoró": "wyr", +"WesternFijian": "wyy", +"Andalusian Arabic": "xaa", +"Sambe": "xab", +"Kachari": "xac", +"Adai": "xad", +"Aequian": "xae", +"Aghwan": "xag", +"Kaimbé": "xai", +"Ararandewára": "xaj", +"Máku": "xak", +"Kalmyk": "xal", +"/Xam": "xam", +"Xamtanga": "xan", +"Khao": "xao", +"Apalachee": "xap", +"Aquitanian": "xaq", +"Karami": "xar", +"Kamas": "xas", +"Katawixi": "xat", +"Kauwera": "xau", +"Xavánte": "xav", +"Kawaiisu": "xaw", +"Kayan Mahakam": "xay", +"LowerBurdekin": "xbb", +"Bactrian": "xbc", +"Bindal": "xbd", +"Bigambal": "xbe", +"Bunganditj": "xbg", +"Kombio": "xbi", +"Birrpayi": "xbj", +"Middle Breton": "xbm", +"Kenaboi": "xbn", +"Bolgarian": "xbo", +"Bibbulman": "xbp", +"Kambera": "xbr", +"Kambiwá": "xbw", +"Batjala": "xby", +"Cumbric": "xcb", +"Camunic": "xcc", +"Celtiberian": "xce", +"Cisalpine Gaulish": "xcg", +"Chemakum": "xch", +"ClassicalArmenian": "xcl", +"Comecrudo": "xcm", +"Cotoname": "xcn", +"Chorasmian": "xco", +"Carian": "xcr", +"Classical Tibetan": "xct", +"Curonian": "xcu", +"Chuvantsy": "xcv", +"Coahuilteco": "xcw", +"Cayuse": "xcy", +"Darkinyung": "xda", +"Dacian": "xdc", +"Dharuk": "xdk", +"Edomite": "xdm", +"Kwandu": "xdo", +"Malayic Dayak": "xdy", +"Eblan": "xeb", +"Hdi": "xed", +"//Xegwi": "xeg", +"Kelo": "xel", +"Kembayan": "xem", +"Epi-Olmec": "xep", +"Xerénte": "xer", +"Kesawai": "xes", +"Xetá": "xet", +"Keoru-Ahia": "xeu", +"Faliscan": "xfa", +"Galatian": "xga", +"Gbin": "xgb", +"Gudang": "xgd", +"Gabrielino-Fernandeño": "xgf", +"Goreng": "xgg", +"Garingbal": "xgi", +"Galindan": "xgl", +"Dharumbal": "xgm", +"Garza": "xgr", +"Unggumi": "xgu", +"Guwa": "xgw", +"Harami": "xha", +"Hunnic": "xhc", +"Hadrami": "xhd", +"Khetrani": "xhe", +"Xhosa": "xho", +"Hernican": "xhr", +"Hattic": "xht", +"Hurrian": "xhu", +"Khua": "xhv", +"Iberian": "xib", +"Xiri": "xii", +"Illyrian": "xil", +"Xinca": "xin", +"Xiriâna": "xir", +"Kisan": "xis", +"IndusValley Language": "xiv", +"Xipaya": "xiy", +"Minjungbal": "xjb", +"Jaitmatang": "xjt", +"Kalkoti": "xka", +"Northern Nago": "xkb", +"Kho'ini": "xkc", +"Mendalam Kayan": "xkd", +"Kereho": "xke", +"Khengkha": "xkf", +"Kagoro": "xkg", +"Kenyan Sign Language": "xki", +"Kajali": "xkj", +"Kaco'": "xkk", +"MainstreamKenyah": "xkl", +"KayanRiver Kayan": "xkn", +"Kiorr": "xko", +"Kabatei": "xkp", +"Koroni": "xkq", +"Xakriabá": "xkr", +"Kumbewaha": "xks", +"Kantosi": "xkt", +"Kaamba": "xku", +"Kgalagadi": "xkv", +"Kembra": "xkw", +"Karore": "xkx", +"Uma'Lasan": "xky", +"Kurtokha": "xkz", +"Kamula": "xla", +"Loup B": "xlb", +"Lycian": "xlc", +"Lydian": "xld", +"Lemnian": "xle", +"Ligurian(Ancient)": "xlg", +"Liburnian": "xli", +"Alanic": "xln", +"LoupA": "xlo", +"Lepontic": "xlp", +"Lusitanian": "xls", +"Cuneiform Luwian": "xlu", +"Elymian": "xly", +"Mushungulu": "xma", +"Mbonga": "xmb", +"Makhuwa-Marrevone": "xmc", +"Mbedam": "xmd", +"Median": "xme", +"Mingrelian": "xmf", +"Mengaka": "xmg", +"Kuku-Muminh": "xmh", +"Majera": "xmj", +"AncientMacedonian": "xmk", +"Malaysian Sign Language": "xml", +"ManadoMalay": "xmm", +"ManichaeanMiddle Persian": "xmn", +"Morerebi": "xmo", +"Kuku-Mu'inh": "xmp", +"Kuku-Mangk": "xmq", +"Meroitic": "xmr", +"Moroccan Sign Language": "xms", +"Matbat": "xmt", +"Kamu": "xmu", +"AntankaranaMalagasy": "xmv", +"TsimihetyMalagasy": "xmw", +"Maden": "xmx", +"Mayaguduna": "xmy", +"MoriBawah": "xmz", +"Ancient North Arabian": "xna", +"Kanakanabu": "xnb", +"Middle Mongolian": "xng", +"Kuanhua": "xnh", +"Ngarigu": "xni", +"Ngoni (Tanzania)": "xnj", +"Nganakarti": "xnk", +"Ngumbarl": "xnm", +"NorthernKankanay": "xnn", +"Anglo-Norman": "xno", +"Ngoni (Mozambique)": "xnq", +"Kangri": "xnr", +"Kanashi": "xns", +"Narragansett": "xnt", +"Nukunul": "xnu", +"Nyiyaparli": "xny", +"Kenzi": "xnz", +"O'chi'chi'": "xoc", +"Kokoda": "xod", +"Soga": "xog", +"Kominimung": "xoi", +"Xokleng": "xok", +"Komo (Sudan)": "xom", +"Konkomba": "xon", +"Xukurú": "xoo", +"Kopar": "xop", +"Korubo": "xor", +"Kowaki": "xow", +"Pirriya": "xpa", +"Northeastern Tasmanian": "xpb", +"Pecheneg": "xpc", +"Oyster Bay Tasmanian": "xpd", +"LiberiaKpelle": "xpe", +"Southeast Tasmanian": "xpf", +"Phrygian": "xpg", +"North Midlands Tasmanian": "xph", +"Pictish": "xpi", +"Mpalitjanh": "xpj", +"KulinaPano": "xpk", +"Port Sorell Tasmanian": "xpl", +"Pumpokol": "xpm", +"Kapinawá": "xpn", +"Pochutec": "xpo", +"Puyo-Paekche": "xpp", +"Mohegan-Pequot": "xpq", +"Parthian": "xpr", +"Pisidian": "xps", +"Punthamara": "xpt", +"Punic": "xpu", +"Northern Tasmanian": "xpv", +"Northwestern Tasmanian": "xpw", +"Southwestern Tasmanian": "xpx", +"Puyo": "xpy", +"Bruny Island Tasmanian": "xpz", +"Karakhanid": "xqa", +"Qatabanian": "xqt", +"Krahô": "xra", +"EasternKaraboro": "xrb", +"Gundungurra": "xrd", +"Kreye": "xre", +"Minang": "xrg", +"Krikati-Timbira": "xri", +"Armazic": "xrm", +"Arin": "xrn", +"Raetic": "xrr", +"Aranama-Tamique": "xrt", +"Marriammu": "xru", +"Karawa": "xrw", +"Sabaean": "xsa", +"Tinà Sambal": "xsb", +"Scythian": "xsc", +"Sidetic": "xsd", +"Sempan": "xse", +"Shamang": "xsh", +"Sio": "xsi", +"Subi": "xsj", +"South Slavey": "xsl", +"Kasem": "xsm", +"Sanga(Nigeria)": "xsn", +"Solano": "xso", +"Silopi": "xsp", +"Makhuwa-Saka": "xsq", +"Sherpa": "xsr", +"Assan": "xss", +"Sanumá": "xsu", +"Sudovian": "xsv", +"Saisiyat": "xsy", +"AlcozaucaMixtec": "xta", +"ChazumbaMixtec": "xtb", +"Katcha-Kadugli-Miri": "xtc", +"Diuxi-Tilantongo Mixtec": "xtd", +"Ketengban": "xte", +"TransalpineGaulish": "xtg", +"Yitha Yitha": "xth", +"SinicahuaMixtec": "xti", +"SanJuan Teita Mixtec": "xtj", +"Tijaltepec Mixtec": "xtl", +"MagdalenaPeñasco Mixtec": "xtm", +"Northern Tlaxiaco Mixtec": "xtn", +"Tokharian A": "xto", +"SanMiguel Piedras Mixtec": "xtp", +"Tumshuqese": "xtq", +"EarlyTripuri": "xtr", +"Sindihui Mixtec": "xts", +"TacahuaMixtec": "xtt", +"CuyamecalcoMixtec": "xtu", +"Thawa": "xtv", +"Tawandê": "xtw", +"YoloxochitlMixtec": "xty", +"AluKurumba": "xua", +"BettaKurumba": "xub", +"Umiida": "xud", +"Kunigami": "xug", +"JennuKurumba": "xuj", +"Ngunawal": "xul", +"Umbrian": "xum", +"Unggaranggu": "xun", +"Kuo": "xuo", +"UpperUmpqua": "xup", +"Urartian": "xur", +"Kuthant": "xut", +"Kxoe": "xuu", +"Venetic": "xve", +"Kamviri": "xvi", +"Vandalic": "xvn", +"Volscian": "xvo", +"Vestinian": "xvs", +"Kwaza": "xwa", +"Woccon": "xwc", +"Wadi Wadi": "xwd", +"Xwela Gbe": "xwe", +"Kwegu": "xwg", +"Wajuk": "xwj", +"Wangkumara": "xwk", +"Western Xwla Gbe": "xwl", +"WrittenOirat": "xwo", +"KwerbaMamberamo": "xwr", +"Wotjobaluk": "xwt", +"Wemba Wemba": "xww", +"Boro (Ghana)": "xxb", +"Ke'o": "xxk", +"Minkin": "xxm", +"Koropó": "xxr", +"Tambora": "xxt", +"Yaygir": "xya", +"Yandjibara": "xyb", +"Mayi-Yapi": "xyj", +"Mayi-Kulan": "xyk", +"Yalakalore": "xyl", +"Mayi-Thakurti": "xyt", +"Yorta Yorta": "xyy", +"Zhang-Zhung": "xzh", +"Zemgalian": "xzm", +"AncientZapotec": "xzp", +"Yaminahua": "yaa", +"Yuhup": "yab", +"PassValley Yali": "yac", +"Yagua": "yad", +"Pumé": "yae", +"Yaka(Democratic Republic of Congo)": "yaf", +"Yámana": "yag", +"Yazgulyam": "yah", +"Yagnobi": "yai", +"Banda-Yangere": "yaj", +"Yakama": "yak", +"Yalunka": "yal", +"Yamba": "yam", +"Mayangna": "yan", +"Yao": "yao", +"Yapese": "yap", +"Yaqui": "yaq", +"Yabarana": "yar", +"Nugunu(Cameroon)": "yas", +"Yambeta": "yat", +"Yuwana": "yau", +"Yangben": "yav", +"Yawalapití": "yaw", +"Yauma": "yax", +"Agwagwune": "yay", +"Lokaa": "yaz", +"Yala": "yba", +"Yemba": "ybb", +"WestYugur": "ybe", +"Yakha": "ybh", +"Yamphu": "ybi", +"Hasha": "ybj", +"Bokha": "ybk", +"Yukuben": "ybl", +"Yaben": "ybm", +"Yabaâna": "ybn", +"Yabong": "ybo", +"Yawiyo": "ybx", +"Yaweyuha": "yby", +"Chesu": "ych", +"Lolopo": "ycl", +"Yucuna": "ycn", +"Chepya": "ycp", +"Yanda": "yda", +"Eastern Yiddish": "ydd", +"YangumDey": "yde", +"Yidgha": "ydg", +"Yoidik": "ydk", +"Ravula": "yea", +"Yeniche": "yec", +"Yimas": "yee", +"Yeni": "yei", +"Yevanic": "yej", +"Yela": "yel", +"Tarok": "yer", +"Yeskwa": "yes", +"Yetfa": "yet", +"Yerukula": "yeu", +"Yapunda": "yev", +"Yeyi": "yey", +"Malyangapa": "yga", +"Yiningayi": "ygi", +"Yangum Gel": "ygl", +"Yagomi": "ygm", +"Gepo": "ygp", +"Yagaria": "ygr", +"Yolŋu Sign Language": "ygs", +"Yugul": "ygu", +"Yagwoia": "ygw", +"BahaBuyang": "yha", +"Judeo-Iraqi Arabic": "yhd", +"Hlepho Phowa": "yhl", +"Yan-nhaŋu Sign Language": "yhs", +"Yinggarda": "yia", +"Yiddish": "yid", +"Ache": "yif", +"WusaNasu": "yig", +"WesternYiddish": "yih", +"Yidiny": "yii", +"Yindjibarndi": "yij", +"DongshanbaLalo": "yik", +"Yindjilandji": "yil", +"YimchungruNaga": "yim", +"Yinchia": "yin", +"Pholo": "yip", +"Miqie": "yiq", +"NorthAwyu": "yir", +"Yis": "yis", +"EasternLalu": "yit", +"Awu": "yiu", +"NorthernNisu": "yiv", +"AxiYi": "yix", +"Azhe": "yiz", +"Yakan": "yka", +"NorthernYukaghir": "ykg", +"Yoke": "yki", +"Yakaikeke": "ykk", +"Khlula": "ykl", +"Kap": "ykm", +"Kua-nsi": "ykn", +"Yasa": "yko", +"Yekora": "ykr", +"Kathu": "ykt", +"Kuamasi": "yku", +"Yakoma": "yky", +"Yaul": "yla", +"Yaleba": "ylb", +"Yele": "yle", +"Yelogu": "ylg", +"AnggurukYali": "yli", +"Yil": "yll", +"Limi": "ylm", +"LangnianBuyang": "yln", +"NaluoYi": "ylo", +"Yalarnnga": "ylr", +"Aribwaung": "ylu", +"Nyâlayu": "yly", +"Yambes": "ymb", +"Southern Muji": "ymc", +"Muda": "ymd", +"Yameo": "yme", +"Yamongeri": "ymg", +"Mili": "ymh", +"Moji": "ymi", +"Makwe": "ymk", +"Iamalele": "yml", +"Maay": "ymm", +"Yamna": "ymn", +"YangumMon": "ymo", +"Yamap": "ymp", +"QilaMuji": "ymq", +"Malasar": "ymr", +"Mysian": "yms", +"NorthernMuji": "ymx", +"Muzi": "ymz", +"Aluo": "yna", +"Yandruwandha": "ynd", +"Lang'e": "yne", +"Yango": "yng", +"NaukanYupik": "ynk", +"Yangulam": "ynl", +"Yana": "ynn", +"Yong": "yno", +"Yendang": "ynq", +"Yansi": "yns", +"Yahuna": "ynu", +"Yoba": "yob", +"Yogad": "yog", +"Yonaguni": "yoi", +"Yokuts": "yok", +"Yola": "yol", +"Yombe": "yom", +"Yonggom": "yon", +"Yoruba": "yor", +"Yotti": "yot", +"Yoron": "yox", +"Yoy": "yoy", +"Phala": "ypa", +"LaboPhowa": "ypb", +"Phola": "ypg", +"Phupha": "yph", +"Phuma": "ypm", +"AniPhowa": "ypn", +"AloPhola": "ypo", +"Phupa": "ypp", +"Phuza": "ypz", +"Yerakai": "yra", +"Yareba": "yrb", +"Yaouré": "yre", +"Nenets": "yrk", +"Nhengatu": "yrl", +"Yirrk-Mel": "yrm", +"Yerong": "yrn", +"Yaroamë": "yro", +"Yarsun": "yrs", +"Yarawata": "yrw", +"Yarluyandi": "yry", +"Yassic": "ysc", +"Samatao": "ysd", +"Sonaga": "ysg", +"YugoslavianSign Language": "ysl", +"Myanmar Sign Language": "ysm", +"Sani": "ysn", +"Nisi(China)": "yso", +"SouthernLolopo": "ysp", +"Sirenik Yupik": "ysr", +"Yessan-Mayo": "yss", +"Sanie": "ysy", +"Talu": "yta", +"Tanglang": "ytl", +"Thopho": "ytp", +"YoutWam": "ytw", +"Yatay": "yty", +"Yucateco": "yua", +"Yugambal": "yub", +"Yuchi": "yuc", +"Judeo-Tripolitanian Arabic": "yud", +"YueChinese": "yue", +"Havasupai-Walapai-Yavapai": "yuf", +"Yug": "yug", +"Yurutí": "yui", +"Karkar-Yuri": "yuj", +"Yuki": "yuk", +"Yulu": "yul", +"Quechan": "yum", +"Bena(Nigeria)": "yun", +"Yukpa": "yup", +"Yuqui": "yuq", +"Yurok": "yur", +"Yopno": "yut", +"Yau(Morobe Province)": "yuw", +"Southern Yukaghir": "yux", +"East Yugur": "yuy", +"Yuracare": "yuz", +"Yawa": "yva", +"Yavitero": "yvt", +"Kalou": "ywa", +"Yinhawangka": "ywg", +"Western Lalu": "ywl", +"Yawanawa": "ywn", +"Wuding-Luquan Yi": "ywq", +"Yawuru": "ywr", +"XishanbaLalo": "ywt", +"WumengNasu": "ywu", +"Yawarawarga": "yww", +"Mayawali": "yxa", +"Yagara": "yxg", +"Yardliyawarra": "yxl", +"Yinwum": "yxm", +"Yuyu": "yxu", +"Yabula Yabula": "yxy", +"Yir Yoront": "yyr", +"Yau (Sandaun Province)": "yyu", +"Ayizi": "yyz", +"E'maBuyang": "yzg", +"Zokhuo": "yzk", +"Sierrade Juárez Zapotec": "zaa", +"San Juan Guelavía Zapotec": "zab", +"Ocotlán Zapotec": "zac", +"Cajonos Zapotec": "zad", +"YareniZapotec": "zae", +"AyoquescoZapotec": "zaf", +"Zaghawa": "zag", +"Zangwal": "zah", +"Isthmus Zapotec": "zai", +"Zaramo": "zaj", +"Zanaki": "zak", +"Zauzou": "zal", +"Miahuatlán Zapotec": "zam", +"OzolotepecZapotec": "zao", +"Zapotec": "zap", +"AloápamZapotec": "zaq", +"RincónZapotec": "zar", +"Santo Domingo Albarradas Zapotec": "zas", +"Tabaa Zapotec": "zat", +"Zangskari": "zau", +"Yatzachi Zapotec": "zav", +"Mitla Zapotec": "zaw", +"XadaniZapotec": "zax", +"Zayse-Zergulla": "zay", +"Zari": "zaz", +"Balaibalan": "zba", +"CentralBerawan": "zbc", +"East Berawan": "zbe", +"Blissymbols": "zbl", +"Batui": "zbt", +"Bu (Bauchi State)": "zbu", +"WestBerawan": "zbw", +"Coatecas Altas Zapotec": "zca", +"CentralHongshuihe Zhuang": "zch", +"Ngazidja Comorian": "zdj", +"Zeeuws": "zea", +"Zenag": "zeg", +"Eastern Hongshuihe Zhuang": "zeh", +"Zenaga": "zen", +"Kinga": "zga", +"Guibei Zhuang": "zgb", +"Standard Moroccan Tamazight": "zgh", +"MinzZhuang": "zgm", +"GuibianZhuang": "zgn", +"Magori": "zgr", +"Zhuang": "zha", +"Zhaba": "zhb", +"Dai Zhuang": "zhd", +"Zhire": "zhi", +"NongZhuang": "zhn", +"Chinese": "zho", +"Zhoa": "zhw", +"Zia": "zia", +"Zimbabwe Sign Language": "zib", +"Zimakani": "zik", +"Zialo": "zil", +"Mesme": "zim", +"Zinza": "zin", +"Zigula": "ziw", +"Zizilivakan": "ziz", +"Kaimbulawa": "zka", +"Koibal": "zkb", +"Kadu": "zkd", +"Koguryo": "zkg", +"Khorezmian": "zkh", +"Karankawa": "zkk", +"Kanan": "zkn", +"Kott": "zko", +"São Paulo Kaingáng": "zkp", +"Zakhring": "zkr", +"Kitan": "zkt", +"Kaurna": "zku", +"Krevinian": "zkv", +"Khazar": "zkz", +"Zula": "zla", +"LiujiangZhuang": "zlj", +"Malay(individual language)": "zlm", +"Lianshan Zhuang": "zln", +"LiuqianZhuang": "zlq", +"Manda (Australia)": "zma", +"Zimba": "zmb", +"Margany": "zmc", +"Maridan": "zmd", +"Mangerr": "zme", +"Mfinu": "zmf", +"Marti Ke": "zmg", +"Makolkol": "zmh", +"Negeri Sembilan Malay": "zmi", +"Maridjabin": "zmj", +"Mandandanyi": "zmk", +"Madngele": "zml", +"Marimanindji": "zmm", +"Mbangwe": "zmn", +"Molo": "zmo", +"Mpuono": "zmp", +"Mituku": "zmq", +"Maranunggu": "zmr", +"Mbesa": "zms", +"Maringarr": "zmt", +"Muruwari": "zmu", +"Mbariman-Gudhinma": "zmv", +"Mbo (Democratic Republic of Congo)": "zmw", +"Bomitaba": "zmx", +"Mariyedi": "zmy", +"Mbandja": "zmz", +"Zan Gula": "zna", +"Zande(individual language)": "zne", +"Mang": "zng", +"Manangkari": "znk", +"Mangas": "zns", +"CopainaláZoque": "zoc", +"ChimalapaZoque": "zoh", +"Zou": "zom", +"AsunciónMixtepec Zapotec": "zoo", +"TabascoZoque": "zoq", +"Rayón Zoque": "zor", +"FranciscoLeón Zoque": "zos", +"Lachiguiri Zapotec": "zpa", +"Yautepec Zapotec": "zpb", +"ChoapanZapotec": "zpc", +"Southeastern Ixtlán Zapotec": "zpd", +"Petapa Zapotec": "zpe", +"SanPedro Quiatoni Zapotec": "zpf", +"Guevea De Humboldt Zapotec": "zpg", +"TotomachapanZapotec": "zph", +"Santa María Quiegolani Zapotec": "zpi", +"Quiavicuzas Zapotec": "zpj", +"Tlacolulita Zapotec": "zpk", +"LachixíoZapotec": "zpl", +"MixtepecZapotec": "zpm", +"Santa Inés Yatzechi Zapotec": "zpn", +"AmatlánZapotec": "zpo", +"ElAlto Zapotec": "zpp", +"Zoogocho Zapotec": "zpq", +"SantiagoXanica Zapotec": "zpr", +"CoatlánZapotec": "zps", +"SanVicente Coatlán Zapotec": "zpt", +"YalálagZapotec": "zpu", +"Chichicapan Zapotec": "zpv", +"ZanizaZapotec": "zpw", +"San Baltazar Loxicha Zapotec": "zpx", +"MazaltepecZapotec": "zpy", +"Texmelucan Zapotec": "zpz", +"QiubeiZhuang": "zqe", +"Kara(Korea)": "zra", +"Mirgan": "zrg", +"Zerenkel": "zrn", +"Záparo": "zro", +"Zarphatic": "zrp", +"Mairasi": "zrs", +"Sarasira": "zsa", +"Kaskean": "zsk", +"ZambianSign Language": "zsl", +"Standard Malay": "zsm", +"Southern Rincon Zapotec": "zsr", +"Sukurum": "zsu", +"ElotepecZapotec": "zte", +"XanaguíaZapotec": "ztg", +"Lapaguía-Guivini Zapotec": "ztl", +"San Agustín Mixtepec Zapotec": "ztm", +"Santa Catarina Albarradas Zapotec": "ztn", +"Loxicha Zapotec": "ztp", +"Quioquitani-QuieríZapotec": "ztq", +"TilquiapanZapotec": "zts", +"TejalapanZapotec": "ztt", +"GüiláZapotec": "ztu", +"Zaachila Zapotec": "ztx", +"YateeZapotec": "zty", +"Zeem": "zua", +"Tokano": "zuh", +"Zulu": "zul", +"Kumzari": "zum", +"Zuni": "zun", +"Zumaya": "zuy", +"Zay": "zwa", +"Nolinguistic content": "zxx", +"Yongbei Zhuang": "zyb", +"YangZhuang": "zyg", +"YoujiangZhuang": "zyj", +"YongnanZhuang": "zyn", +"Zyphe": "zyp", +"Zaza": "zza", +"ZuojiangZhuang": "zzj" +} diff --git a/dspace-api/src/test/data/dspaceFolder/config/local.cfg b/dspace-api/src/test/data/dspaceFolder/config/local.cfg index 51d050c296a2..6b31cfc98123 100644 --- a/dspace-api/src/test/data/dspaceFolder/config/local.cfg +++ b/dspace-api/src/test/data/dspaceFolder/config/local.cfg @@ -310,4 +310,8 @@ webui.supported.locales = en # Type bind configuration for the submission form with special type-bind field # When title is something like "Type-bind test" the type-bind field will popped up -submit.type-bind.field = dc.type,dc.identifier.citation=>dc.title \ No newline at end of file +submit.type-bind.field = dc.type,dc.identifier.citation=>dc.title + +autocomplete.custom.separator.solr-subject_ac = \\|\\|\\| +autocomplete.custom.separator.solr-title_ac = \\|\\|\\| +autocomplete.custom.allowed = solr-author_ac,solr-publisher_ac,solr-dataProvider_ac,solr-dctype_ac,solr-subject_ac,solr-handle_title_ac,json_static-iso_langs.json,solr-title_ac diff --git a/dspace-api/src/test/data/dspaceFolder/config/submission-forms.xml b/dspace-api/src/test/data/dspaceFolder/config/submission-forms.xml index 81eecc680164..95c2dbb727e7 100644 --- a/dspace-api/src/test/data/dspaceFolder/config/submission-forms.xml +++ b/dspace-api/src/test/data/dspaceFolder/config/submission-forms.xml @@ -225,7 +225,7 @@ it, please enter the types and the actual numbers or codes. true - twobox + autocomplete Enter appropriate subject keywords or phrases. srsc diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/SubmissionFormConverter.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/SubmissionFormConverter.java index 855a80c4a3af..8021e4e0d771 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/SubmissionFormConverter.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/converter/SubmissionFormConverter.java @@ -164,6 +164,7 @@ private SubmissionFormFieldRest getField(DCInput dcinput, String formName) { inputField.setSelectableMetadata(selectableMetadata); inputField.setTypeBind(dcinput.getTypeBindList()); inputField.setComplexDefinition(dcinput.getComplexDefinitionJSONString()); + inputField.setAutocompleteCustom(dcinput.getAutocompleteCustom()); } if (dcinput.isRelationshipField()) { selectableRelationship = getSelectableRelationships(dcinput); diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/SubmissionFormFieldRest.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/SubmissionFormFieldRest.java index 28a67730ea64..efafa5927e8a 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/SubmissionFormFieldRest.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/model/SubmissionFormFieldRest.java @@ -92,6 +92,13 @@ public class SubmissionFormFieldRest { * ComplexDefinition transformed to the JSON string */ private String complexDefinition; + + /** + * Autocomplete custom field. Give suggestions from this specific autocomplete solr index/file. + */ + private String autocompleteCustom; + + /** * Getter for {@link #selectableMetadata} * @@ -298,4 +305,12 @@ public void setComplexDefinition(String complexDefinition) { public String getComplexDefinition() { return this.complexDefinition; } + + public String getAutocompleteCustom() { + return autocompleteCustom; + } + + public void setAutocompleteCustom(String autocompleteCustom) { + this.autocompleteCustom = autocompleteCustom; + } } diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/MetadataValueRestRepository.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/MetadataValueRestRepository.java index 7174dae9f12f..d192abb7b6c7 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/MetadataValueRestRepository.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/MetadataValueRestRepository.java @@ -10,16 +10,7 @@ import java.io.IOException; import java.sql.SQLException; import java.util.ArrayList; -import java.util.Arrays; -import java.util.LinkedList; import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Function; -import java.util.function.Predicate; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; @@ -29,6 +20,7 @@ import org.dspace.app.rest.exception.DSpaceBadRequestException; import org.dspace.app.rest.model.MetadataValueWrapper; import org.dspace.app.rest.model.MetadataValueWrapperRest; +import org.dspace.app.rest.utils.Utils; import org.dspace.content.MetadataField; import org.dspace.content.MetadataValue; import org.dspace.content.service.ItemService; @@ -51,7 +43,7 @@ /** * This is the repository responsible to manage MetadataValueWrapper Rest object. * - * @author Milan Majchrak (milan.majchrak at dataquest.sk) + * @author Milan Majchrak (dspace at dataquest.sk) */ @Component(MetadataValueWrapperRest.CATEGORY + "." + MetadataValueWrapperRest.NAME) public class MetadataValueRestRepository extends DSpaceRestRepository { @@ -122,31 +114,17 @@ public Page findByValue(@Parameter(value = "schema", r // Find matches in Solr Search core DiscoverQuery discoverQuery = - this.createDiscoverQuery(metadataField, searchValue, pageable); + this.createDiscoverQuery(metadataField, searchValue); if (ObjectUtils.isEmpty(discoverQuery)) { throw new IllegalArgumentException("Cannot create a DiscoverQuery from the arguments."); } - // regex if searchValue consist of numbers and characters - // \d - digit - String regexNumber = "(.)*(\\d)(.)*"; - // \D - non digit - String regexString = "(.)*(\\D)(.)*"; - Pattern patternNumber = Pattern.compile(regexNumber); - Pattern patternString = Pattern.compile(regexString); - // if the searchValue is mixed with numbers and characters the Solr ignore numbers by default - // divide the characters and numbers from searchValue to the separate queries and from separate queries - // create one complex query - if (patternNumber.matcher(searchValue).matches() && patternString.matcher(searchValue).matches()) { - List characterList = this.extractCharacterListFromString(searchValue); - List numberList = this.extractNumberListFromString(searchValue); - - String newQuery = this.composeQueryWithNumbersAndChars(metadataField, characterList, numberList); - discoverQuery.setQuery(newQuery); + String normalizedQuery = Utils.normalizeDiscoverQuery(searchValue, metadataField); + if (StringUtils.isNotBlank(normalizedQuery)) { + discoverQuery.setQuery(normalizedQuery); } - List metadataValueWrappers = new ArrayList<>(); try { DiscoverResult searchResult = searchService.search(context, discoverQuery); @@ -183,40 +161,6 @@ public Page findByValue(@Parameter(value = "schema", r return converter.toRestPage(metadataValueWrappers, pageable, utils.obtainProjection()); } - /** - * From searchValue get all String values which are separated by the number to the List of Strings. - * @param searchValue e.g. 'my1Search2' - * @return e.g. [my, Search] - */ - private List extractCharacterListFromString(String searchValue) { - List characterList = null; - // get characters from searchValue as List - searchValue = searchValue.replaceAll("[0-9]", " "); - characterList = new LinkedList<>(Arrays.asList(searchValue.split(" "))); - // remove empty characters from the characterList - characterList.removeIf(characters -> characters == null || "".equals(characters)); - - return characterList; - } - - /** - * From searchValue get all number values which are separated by the number to the List of Strings. - * @param searchValue e.g. 'my1Search2' - * @return e.g. [1, 2] - */ - private List extractNumberListFromString(String searchValue) { - List numberList = new ArrayList<>(); - - // get numbers from searchValue as List - Pattern numberRegex = Pattern.compile("-?\\d+"); - Matcher numberMatcher = numberRegex.matcher(searchValue); - while (numberMatcher.find()) { - numberList.add(numberMatcher.group()); - } - - return numberList; - } - public List filterEUSponsors(List metadataWrappers) { return metadataWrappers.stream().filter(m -> !m.getMetadataValue().getValue().contains("info:eu-repo")) .collect(Collectors.toList()); @@ -224,51 +168,14 @@ public List filterEUSponsors(List me public List distinctMetadataValues(List metadataWrappers) { return metadataWrappers.stream().filter( - distinctByKey(metadataValueWrapper -> metadataValueWrapper.getMetadataValue().getValue()) ) + Utils.distinctByKey(metadataValueWrapper -> metadataValueWrapper.getMetadataValue().getValue()) ) .collect( Collectors.toList() ); } - /** - * From list of String and list of Numbers create a query for the SolrQuery. - * @param metadataField e.g. `dc.contributor.author` - * @param characterList e.g. [my, Search] - * @param numberList e.g. [1, 2] - * @return "dc.contributor.author:*my* AND dc.contributor.author:*Search* AND dc.contributor.author:*1* AND ..." - */ - private String composeQueryWithNumbersAndChars(String metadataField, List characterList, - List numberList) { - this.addQueryTemplateToList(metadataField, characterList); - this.addQueryTemplateToList(metadataField, numberList); - - String joinedChars = String.join(" AND ", characterList); - String joinedNumbers = String.join(" AND ", numberList); - return joinedChars + " AND " + joinedNumbers; - - } - - /** - * Add SolrQuery template to the every item of the List - * @param metadataField e.g. `dc.contributor.author` - * @param stringList could be List of String or List of Numbers which are in the String format because of Solr - * e.g. [my, Search] - * @return [dc.contributor.author:*my*, dc.contributor.author:*Search*] - */ - private List addQueryTemplateToList(String metadataField, List stringList) { - String template = metadataField + ":" + "*" + " " + "*"; - - AtomicInteger index = new AtomicInteger(); - stringList.forEach(characters -> { - String queryString = template.replaceAll(" ", characters); - stringList.set(index.getAndIncrement(), queryString); - }); - return stringList; - } - - private DiscoverQuery createDiscoverQuery(String metadataField, String searchValue, Pageable pageable) { + private DiscoverQuery createDiscoverQuery(String metadataField, String searchValue) { DiscoverQuery discoverQuery = new DiscoverQuery(); discoverQuery.setQuery(metadataField + ":" + "*" + searchValue + "*"); - discoverQuery.setStart(Math.toIntExact(pageable.getOffset())); - discoverQuery.setMaxResults(pageable.getPageSize()); + discoverQuery.setMaxResults(500); // return only metadata field values discoverQuery.addSearchField(metadataField); discoverQuery.addFilterQueries("search.resourcetype:" + IndexableItem.TYPE); @@ -286,14 +193,6 @@ private List convertMetadataValuesToWrappers(List Predicate distinctByKey(Function keyExtractor) { - Map map = new ConcurrentHashMap<>(); - return t -> map.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null; - } @Override @PreAuthorize("permitAll()") diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/SuggestionRestController.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/SuggestionRestController.java new file mode 100644 index 000000000000..b0f5c051979d --- /dev/null +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/repository/SuggestionRestController.java @@ -0,0 +1,400 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ +package org.dspace.app.rest.repository; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; +import javax.annotation.Nullable; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.BadRequestException; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.logging.log4j.Logger; +import org.dspace.app.rest.model.VocabularyEntryRest; +import org.dspace.app.rest.model.hateoas.VocabularyEntryResource; +import org.dspace.app.rest.utils.Utils; +import org.dspace.core.Context; +import org.dspace.discovery.DiscoverQuery; +import org.dspace.discovery.DiscoverResult; +import org.dspace.discovery.SearchService; +import org.dspace.discovery.SearchServiceException; +import org.dspace.discovery.indexobject.IndexableItem; +import org.dspace.services.ConfigurationService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.ClassPathResource; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.Pageable; +import org.springframework.data.web.PagedResourcesAssembler; +import org.springframework.hateoas.PagedModel; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +/** + * Returns VocabularyEntries that contain searchValue. The search is performed on the specific index that is defined by + * the `autocompleteCustom` parameter in the `submission-forms.xml`. + * + * @author Milan Majchrak (dspace at dataquest.sk) + */ +@RestController +@RequestMapping("/api/suggestions") +public class SuggestionRestController extends AbstractDSpaceRestRepository { + + private static final Logger log = org.apache.logging.log4j.LogManager.getLogger(SuggestionRestController.class); + + + /** + * Prefix for the configuration that defines the separator for the autocompleteCustom parameter. + */ + private static final String AUTOCOMPLETE_CUSTOM_CFG_FORMAT_PREFIX = "autocomplete.custom.separator."; + + /** + * Solr prefix for the autocompleteCustom parameter that define the source of the suggestions. + */ + private static final String AUTOCOMPLETE_CUSTOM_SOLR_PREFIX = "solr-"; + + /** + * Json file prefix for the autocompleteCustom parameter that define the source of the suggestions. + */ + private static final String AUTOCOMPLETE_CUSTOM_JSON_PREFIX = "json_static-"; + + /** + * Query parameter from the autocompleteCustom parameter that define specific query for the Solr search. + */ + private static final String AUTOCOMPLETE_CUSTOM_SOLR_QUERY_PARAM = "query="; + + /** + * Limit of suggestions that will be returned from the JSON file. The limit is used to prevent + * the loading of a large amount of data from the JSON file. + */ + private static final int JSON_SUGGESTIONS_LIMIT = 8; + + @Autowired + private SearchService searchService; + + @Autowired + private ConfigurationService configurationService; + + /** + * Map that contains loaded JSON suggestions. The key is the autocompleteCustom parameter and the value is the + * loaded JSON data. The JSON data is loaded only once and stored in the map for further use. + */ + Map jsonSuggestions = new HashMap<>(); + + /** + * Returns a list of VocabularyEntryRest objects that contain values that contain searchValue. + * The search is performed on the specific index or a specific json file that is defined + * by the autocompleteCustom parameter. + */ + @PreAuthorize("hasAuthority('AUTHENTICATED')") + @RequestMapping(method = RequestMethod.GET) + public PagedModel filter(@Nullable HttpServletRequest request, + @Nullable Pageable optionalPageable, + @RequestParam(name = "autocompleteCustom", required = false) + String autocompleteCustom, + @RequestParam(name = "searchValue", required = false) + String searchValue, + PagedResourcesAssembler assembler) throws SearchServiceException { + // If the searching for the autocompleteCustom parameter is not allowed, return an error + if (!isAllowedSearching(autocompleteCustom)) { + String errorMessage = "Searching for autocompleteCustom: " + autocompleteCustom + " is not allowed"; + log.warn(errorMessage); + throw new BadRequestException(errorMessage); + } + + Pageable pageable = utils.getPageable(optionalPageable); + List results; + // Load suggestions from the specific source (Solr or JSON) + if (autocompleteCustom.startsWith(AUTOCOMPLETE_CUSTOM_JSON_PREFIX)) { + results = getSuggestions(autocompleteCustom, searchValue, AUTOCOMPLETE_CUSTOM_JSON_PREFIX); + } else if (autocompleteCustom.startsWith(AUTOCOMPLETE_CUSTOM_SOLR_PREFIX)) { + results = getSuggestions(autocompleteCustom, searchValue, AUTOCOMPLETE_CUSTOM_SOLR_PREFIX); + } else { + log.warn("Cannot fetch suggestions for autocompleteCustom: {} with searching value: {}", + autocompleteCustom, searchValue); + // Return empty list + results = new ArrayList<>(0); + } + + // If no results are found, return null + if (CollectionUtils.isEmpty(results)) { + log.info("No suggestions found for autocompleteCustom: {} with searching value: {}", + autocompleteCustom, searchValue); + } + + // Remove duplicates from the results + List finalResults = results.stream() + .filter(Utils.distinctByKey(VocabularyEntryRest::getValue)) + .collect(Collectors.toList()); + + // Remove `?query` from the autocompleteCustom parameter if it contains this specific query parameter + String autocompleteCustomWithoutQuery = updateAutocompleteAndQuery(autocompleteCustom, null); + // Format the values according to the configuration + finalResults = finalResults.stream() + .map(ver -> formatValue(ver, autocompleteCustomWithoutQuery)) + .collect(Collectors.toList()); + + // Create a page with the final results. The page is needed for the better processing in the frontend. + Page resultsPage = new PageImpl<>(finalResults, pageable, finalResults.size()); + PagedModel response = assembler.toModel(resultsPage); + return response; + } + + /** + * Returns a list of VocabularyEntryRest objects which contain values with searching value. + * The search is performed on the specific index or json file that is defined by the autocompleteCustom parameter. + */ + private List getSuggestions(String autocompleteCustom, String searchValue, String prefix) + throws SearchServiceException { + // Remove the prefix from the autocompleteCustom parameter + String normalizedAutocompleteCustom = removeAutocompleteCustomPrefix(prefix, autocompleteCustom); + // Normalize the search value - remove leading and trailing whitespaces + String normalizedSearchValue = searchValue.trim(); + // Create a list of VocabularyEntryRest objects that will be filtered from duplicate values and returned + // as a response. + List results = new ArrayList<>(); + + if (prefix.equals(AUTOCOMPLETE_CUSTOM_SOLR_PREFIX)) { + // Load suggestions from Solr + results = loadSuggestionsFromSolr(normalizedAutocompleteCustom, normalizedSearchValue, results); + } else if (prefix.equals(AUTOCOMPLETE_CUSTOM_JSON_PREFIX)) { + // Load suggestions from JSON + results = loadSuggestionsFromJson(normalizedAutocompleteCustom, normalizedSearchValue, results); + } + + return results; + + } + + /** + * Load suggestions from the JSON file. The JSON file is loaded only once and stored in the map for further use. + * The search is performed on the specific key in the JSON file. The key is the autocompleteCustom parameter. + */ + private List loadSuggestionsFromJson(String autocompleteCustom, String searchValue, + List results) { + try { + // Load the JSON data from the file. + JsonNode jsonData; + if (!jsonSuggestions.containsKey(autocompleteCustom)) { + // Load the JSON data from the file and store it in the map for further use. + JsonNode loadedJsonSuggestions = loadJsonFromFile(autocompleteCustom); + jsonData = loadedJsonSuggestions; + jsonSuggestions.put(autocompleteCustom, loadedJsonSuggestions); + } else { + // Get the JSON data from the map + jsonData = jsonSuggestions.get(autocompleteCustom); + } + + if (jsonData == null) { + log.warn("Cannot load JSON suggestions from file: {}", autocompleteCustom); + return results; + } + + // Search for a specific key + results = searchByKey(jsonData, searchValue, results); + + } catch (IOException e) { + log.error("Error while loading JSON suggestions from file: {} because: {}", autocompleteCustom, + e.getMessage()); + } + return results; + } + + /** + * Load suggestions from Solr. The search is performed on the specific index that is defined by the + * autocompleteCustom parameter. + */ + private List loadSuggestionsFromSolr(String autocompleteCustom, String searchValue, + List results) + throws SearchServiceException { + Context context = obtainContext(); + // Create a DiscoverQuery object that will be used to search for the results. + DiscoverQuery discoverQuery = new DiscoverQuery(); + // Process the custom query if it contains the specific query parameter `?query=` + autocompleteCustom = updateAutocompleteAndQuery(autocompleteCustom, discoverQuery); + // TODO - search facets and process facet results instead of indexable objects + discoverQuery.setMaxResults(500); + // return only metadata field values + discoverQuery.addSearchField(autocompleteCustom); + + String normalizedQuery = Utils.normalizeDiscoverQuery(searchValue, autocompleteCustom); + if (StringUtils.isNotBlank(normalizedQuery)) { + discoverQuery.setQuery(normalizedQuery); + } + + // Search for the results + DiscoverResult searchResult = searchService.search(context, discoverQuery); + + // Iterate over all indexable objects in the search result. We need indexable object to get search documents. + // Each search document contains values from the specific index. + processSolrSearchResults(searchResult, autocompleteCustom, searchValue, results); + + return results; + } + + /** + * Process the search results from Solr. The search results are processed and filtered according to the searchValue. + */ + private void processSolrSearchResults(DiscoverResult searchResult, String autocompleteCustom, String searchValue, + List results) { + searchResult.getIndexableObjects().forEach(object -> { + if (!(object instanceof IndexableItem)) { + return; + } + IndexableItem item = (IndexableItem) object; + // Get all search documents for the item. + searchResult.getSearchDocument(item).forEach((searchDocument) -> { + VocabularyEntryRest vocabularyEntryRest = new VocabularyEntryRest(); + // All values from Item's specific index - it could contain values we are not looking for. + // The must be filtered out. + List docValues = searchDocument.getSearchFieldValues(autocompleteCustom); + + // Filter values that contain searchValue + List filteredValues = docValues.stream() + .filter(value -> value.contains(searchValue)) + .collect(Collectors.toList()); + + // Add filtered values to the results. It contains only values that contain searchValue. + filteredValues.forEach(value -> { + vocabularyEntryRest.setDisplay(value); + vocabularyEntryRest.setValue(value); + results.add(vocabularyEntryRest); + }); + }); + }); + } + + /** + * Process the custom query if it contains the specific query parameter `?query=`. + * The query is processed and set to the DiscoverQuery object. + * The method returns the part before the query parameter as the new autocompleteCustom parameter. + * @param discoverQuery could be null + */ + private String updateAutocompleteAndQuery(String autocompleteCustom, DiscoverQuery discoverQuery) { + if (!autocompleteCustom.contains(AUTOCOMPLETE_CUSTOM_SOLR_QUERY_PARAM)) { + return autocompleteCustom; + } + + // Query parameter starts with `?` + String[] parts = autocompleteCustom.split("\\?" + AUTOCOMPLETE_CUSTOM_SOLR_QUERY_PARAM); + // 2 parts are expected - the part before the query parameter and after the query parameter + if (parts.length == 2) { + if (discoverQuery != null) { + discoverQuery.setQuery(parts[1]); + } + return parts[0]; // Return the part before "?query=" + } + + return autocompleteCustom; + } + + /** + * Load JSON data from the file. The JSON data is loaded from the resources' folder. + */ + public JsonNode loadJsonFromFile(String filePath) throws IOException { + // Load the file from the resources folder + ClassPathResource resource = new ClassPathResource(filePath); + + // Use Jackson ObjectMapper to read the JSON file + ObjectMapper objectMapper = new ObjectMapper(); + return objectMapper.readTree(resource.getInputStream()); + } + + /** + * Search for the specific key in the JSON object. The search is performed on the specific key in the JSON object. + * The key is the autocompleteCustom parameter. + */ + public List searchByKey(JsonNode jsonNode, String searchKey, + List results) { + // Iterate over all fields (keys) in the JSON object + Iterator fieldNames = jsonNode.fieldNames(); + while (fieldNames.hasNext() && results.size() < JSON_SUGGESTIONS_LIMIT) { + String key = fieldNames.next(); + + // If the key matches or contains the search term (case-insensitive) + if (key.toLowerCase().contains(searchKey.toLowerCase())) { + // Add key-value pair to the result + VocabularyEntryRest vocabularyEntryRest = new VocabularyEntryRest(); + vocabularyEntryRest.setDisplay(key); + vocabularyEntryRest.setValue(jsonNode.get(key).asText()); + results.add(vocabularyEntryRest); + } + } + return results; + } + + /** + * Format the value according to the configuration. + * The result value could consist of multiple parts separated by a separator. Keep the correct part separated by + * the separator loaded from the configuration. + */ + private VocabularyEntryRest formatValue(VocabularyEntryRest ver, String autocompleteCustom) { + if (StringUtils.isEmpty(ver.getValue()) || StringUtils.isEmpty(autocompleteCustom)) { + return ver; + } + + // Load separator from the configuration `autocomplete.custom.separator. + String separator = configurationService.getProperty(AUTOCOMPLETE_CUSTOM_CFG_FORMAT_PREFIX + autocompleteCustom); + if (StringUtils.isEmpty(separator)) { + return ver; + } + + // Split the value by the separator and keep the correct - second part + String[] parts = ver.getValue().split(separator); + // Check the length of the parts - the correct value is the second part + if (parts.length > 1) { + String formattedValue = parts[1].trim(); // The correct value is the second part + ver.setValue(formattedValue); + ver.setDisplay(formattedValue); + } + + return ver; + } + + /** + * Remove the prefix from the autocompleteCustom parameter. E.g. remove "solr-" or "json_static-". + */ + private String removeAutocompleteCustomPrefix(String prefix, String autocompleteCustom) { + return autocompleteCustom.replace(prefix, ""); + } + + /** + * Check if the autocompleteCustom parameter is allowed to be searched. + * To allow searching, the `autocomplete.custom.allowed` property must be defined in the configuration. + */ + private boolean isAllowedSearching(String autocompleteCustom) { + // Check if the autocompleteCustom parameter is allowed to be searched + String[] allowedAutocompleteCustom = configurationService.getArrayProperty("autocomplete.custom.allowed", + new String[0]); + + // Remove `?query` from the autocompleteCustom parameter if it contains this specific query parameter + String normalizedAutocompleteCustom = updateAutocompleteAndQuery(autocompleteCustom, null); + + // If the allowedAutocompleteCustom parameter is not defined, return false + if (Objects.isNull(allowedAutocompleteCustom)) { + return false; + } + + // Convert the allowedAutocompleteCustom array to a list + List allowedAutocompleteCustomList = Arrays.asList(allowedAutocompleteCustom); + return allowedAutocompleteCustomList.contains(normalizedAutocompleteCustom); + } +} diff --git a/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/Utils.java b/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/Utils.java index 347a23b86de5..4d47e6484b64 100644 --- a/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/Utils.java +++ b/dspace-server-webapp/src/main/java/org/dspace/app/rest/utils/Utils.java @@ -48,6 +48,12 @@ import java.util.Set; import java.util.TreeSet; import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import javax.annotation.Nullable; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLContext; @@ -1133,4 +1139,109 @@ public static String encodeNonAsciiCharacters(String input) { } return result.toString(); } + + /** + * Update the solr DiscoverQuery because in some cases it won't search properly numbers and characters together. + * @param searchValue searching value + * @param searchField it could be special solr index or metadata field + * @return updated DiscoverQuery + */ + public static String normalizeDiscoverQuery(String searchValue, + String searchField) { + // regex if searchValue consist of numbers and characters + // \d - digit + String regexNumber = "(.)*(\\d)(.)*"; + // \D - non digit + String regexString = "(.)*(\\D)(.)*"; + Pattern patternNumber = Pattern.compile(regexNumber); + Pattern patternString = Pattern.compile(regexString); + // if the searchValue is mixed with numbers and characters the Solr ignore numbers by default + // divide the characters and numbers from searchValue to the separate queries and from separate queries + // create one complex query + if (patternNumber.matcher(searchValue).matches() && patternString.matcher(searchValue).matches()) { + List characterList = extractCharacterListFromString(searchValue); + List numberList = extractNumberListFromString(searchValue); + return composeQueryWithNumbersAndChars(searchField, characterList, numberList); + } + return null; + } + + /** + * From searchValue get all number values which are separated by the number to the List of Strings. + * @param searchValue e.g. 'my1Search2' + * @return e.g. [1, 2] + */ + private static List extractNumberListFromString(String searchValue) { + List numberList = new ArrayList<>(); + + // get numbers from searchValue as List + Pattern numberRegex = Pattern.compile("-?\\d+"); + Matcher numberMatcher = numberRegex.matcher(searchValue); + while (numberMatcher.find()) { + numberList.add(numberMatcher.group()); + } + + return numberList; + } + + /** + * From searchValue get all String values which are separated by the number to the List of Strings. + * @param searchValue e.g. 'my1Search2' + * @return e.g. [my, Search] + */ + private static List extractCharacterListFromString(String searchValue) { + List characterList = null; + // get characters from searchValue as List + searchValue = searchValue.replaceAll("[0-9]", " "); + characterList = new LinkedList<>(Arrays.asList(searchValue.split(" "))); + // remove empty characters from the characterList + characterList.removeIf(characters -> characters == null || "".equals(characters)); + + return characterList; + } + + /** + * From list of String and list of Numbers create a query for the SolrQuery. + * @param metadataField e.g. `dc.contributor.author` + * @param characterList e.g. [my, Search] + * @param numberList e.g. [1, 2] + * @return "dc.contributor.author:*my* AND dc.contributor.author:*Search* AND dc.contributor.author:*1* AND ..." + */ + private static String composeQueryWithNumbersAndChars(String metadataField, List characterList, + List numberList) { + addQueryTemplateToList(metadataField, characterList); + addQueryTemplateToList(metadataField, numberList); + + String joinedChars = String.join(" AND ", characterList); + String joinedNumbers = String.join(" AND ", numberList); + return joinedChars + " AND " + joinedNumbers; + + } + + /** + * Add SolrQuery template to the every item of the List + * @param metadataField e.g. `dc.contributor.author` + * @param stringList could be List of String or List of Numbers which are in the String format because of Solr + * e.g. [my, Search] + * @return [dc.contributor.author:*my*, dc.contributor.author:*Search*] + */ + private static List addQueryTemplateToList(String metadataField, List stringList) { + String template = metadataField + ":" + "*" + " " + "*"; + + AtomicInteger index = new AtomicInteger(); + stringList.forEach(characters -> { + String queryString = template.replaceAll(" ", characters); + stringList.set(index.getAndIncrement(), queryString); + }); + return stringList; + } + + /** + * Filter unique values from the list and return list with unique values + * @return List with unique values + */ + public static Predicate distinctByKey(Function keyExtractor) { + Map map = new ConcurrentHashMap<>(); + return t -> map.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null; + } } diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/BrowsesResourceControllerIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/BrowsesResourceControllerIT.java index 57a8dbb3c2b7..e1f9788a517e 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/BrowsesResourceControllerIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/BrowsesResourceControllerIT.java @@ -1422,7 +1422,7 @@ public void testBrowseByEntriesStartsWith() throws Exception { //Verify that the index filters to the "Universe" entries and Counts 2 Items. .andExpect(jsonPath("$._embedded.entries", - contains(BrowseEntryResourceMatcher.matchBrowseEntry("Universe", 2) + contains(BrowseEntryResourceMatcher.matchBrowseEntry("Universe".toLowerCase(), 2) ))) //Verify startsWith parameter is included in the links .andExpect(jsonPath("$._links.self.href", containsString("?startsWith=U"))); @@ -1446,7 +1446,8 @@ public void testBrowseByEntriesStartsWith() throws Exception { //Verify that the index filters to the "Turing, Alan'" items. .andExpect(jsonPath("$._embedded.entries", - contains(BrowseEntryResourceMatcher.matchBrowseEntry("Turing, Alan Mathison", 1) + contains(BrowseEntryResourceMatcher.matchBrowseEntry( + "Turing, Alan Mathison".toLowerCase(), 1) ))) //Verify that the startsWith paramater is included in the links .andExpect(jsonPath("$._links.self.href", containsString("?startsWith=T"))); @@ -1469,7 +1470,8 @@ public void testBrowseByEntriesStartsWith() throws Exception { //Verify that the index filters to the "Computing'" items. .andExpect(jsonPath("$._embedded.entries", - contains(BrowseEntryResourceMatcher.matchBrowseEntry("Computing", 3) + contains(BrowseEntryResourceMatcher.matchBrowseEntry( + "Computing".toLowerCase(), 3) ))) //Verify that the startsWith paramater is included in the links .andExpect(jsonPath("$._links.self.href", containsString("?startsWith=C"))); @@ -1544,9 +1546,12 @@ public void testBrowseByEntriesStartsWithAndDiacritics() throws Exception { //Verify that the index filters to the "Alonso, Nombre", "Álvarez, Nombre" and "Azuaga, Nombre" // and diacritics are ignored in sorting .andExpect(jsonPath("$._embedded.entries", - contains(BrowseEntryResourceMatcher.matchBrowseEntry("Alonso, Nombre", 1), - BrowseEntryResourceMatcher.matchBrowseEntry("Álvarez, Nombre", 1), - BrowseEntryResourceMatcher.matchBrowseEntry("Azuaga, Nombre", 1) + contains(BrowseEntryResourceMatcher.matchBrowseEntry( + "Alonso, Nombre".toLowerCase(), 1), + BrowseEntryResourceMatcher.matchBrowseEntry( + "Álvarez, Nombre".toLowerCase(), 1), + BrowseEntryResourceMatcher.matchBrowseEntry( + "Azuaga, Nombre".toLowerCase(), 1) ))) //Verify startsWith parameter is included in the links @@ -1570,8 +1575,10 @@ public void testBrowseByEntriesStartsWithAndDiacritics() throws Exception { //Verify that the index filters to the "Ögren, Name"" and "Ortiz, Nombre" .andExpect(jsonPath("$._embedded.entries", - contains(BrowseEntryResourceMatcher.matchBrowseEntry("Ögren, Name", 1), - BrowseEntryResourceMatcher.matchBrowseEntry("Ortiz, Nombre", 1) + contains(BrowseEntryResourceMatcher.matchBrowseEntry( + "Ögren, Name".toLowerCase(), 1), + BrowseEntryResourceMatcher.matchBrowseEntry( + "Ortiz, Nombre".toLowerCase(), 1) ))) //Verify that the startsWith paramater is included in the links .andExpect(jsonPath("$._links.self.href", containsString("?startsWith=Ó"))); @@ -1596,9 +1603,12 @@ public void testBrowseByEntriesStartsWithAndDiacritics() throws Exception { //Verify that the index filters to the "Telecomunicaciones', "Teléfono" and "Televisor" and // it is sorted ignoring diacritics .andExpect(jsonPath("$._embedded.entries", - contains(BrowseEntryResourceMatcher.matchBrowseEntry("Telecomunicaciones", 1), - BrowseEntryResourceMatcher.matchBrowseEntry("Teléfono", 1), - BrowseEntryResourceMatcher.matchBrowseEntry("Televisor", 1) + contains(BrowseEntryResourceMatcher.matchBrowseEntry( + "Telecomunicaciones".toLowerCase(), 1), + BrowseEntryResourceMatcher.matchBrowseEntry( + "Teléfono".toLowerCase(), 1), + BrowseEntryResourceMatcher.matchBrowseEntry( + "Televisor".toLowerCase(), 1) ))) //Verify that the startsWith paramater is included in the links .andExpect(jsonPath("$._links.self.href", containsString("?startsWith=Tele"))); @@ -1621,7 +1631,7 @@ public void testBrowseByEntriesStartsWithAndDiacritics() throws Exception { //Verify that the index filters to the "Guion" .andExpect(jsonPath("$._embedded.entries", - contains(BrowseEntryResourceMatcher.matchBrowseEntry("Guion", 1) + contains(BrowseEntryResourceMatcher.matchBrowseEntry("Guion".toLowerCase(), 1) ))) //Verify that the startsWith paramater is included in the links .andExpect(jsonPath("$._links.self.href", containsString("?startsWith=Guión"))); diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ClarinDiscoveryRestControllerIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ClarinDiscoveryRestControllerIT.java index e1361a023b0c..cd2829dc626a 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/ClarinDiscoveryRestControllerIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/ClarinDiscoveryRestControllerIT.java @@ -358,8 +358,8 @@ public void discoverFacetsAuthorTestWithPrefix() throws Exception { // up in different items //These authors are order according to count. Only two show up because of the prefix. .andExpect(jsonPath("$._embedded.values", containsInAnyOrder( - FacetValueMatcher.entryAuthor("Smith, Maria"), - FacetValueMatcher.entryAuthor("Smith, Donald") + FacetValueMatcher.entryAuthor("Smith, Maria".toLowerCase()), + FacetValueMatcher.entryAuthor("Smith, Donald".toLowerCase()) ))) ; } @@ -1003,7 +1003,8 @@ public void discoverSearchTest() throws Exception { SearchFilterMatcher.clarinItemsCommunityFilter(), SearchFilterMatcher.clarinItemsTypeFilter(), SearchFilterMatcher.clarinSubjectFirstValueFilter(), - SearchFilterMatcher.clarinDataProviderFacet() + SearchFilterMatcher.clarinDataProviderFacet(), + SearchFilterMatcher.dcTypeFilter() ))) //These sortOptions need to be present as it's the default in the configuration .andExpect(jsonPath("$.sortOptions", contains( diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/SuggestionRestControllerIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/SuggestionRestControllerIT.java new file mode 100644 index 000000000000..a449bfd29bc5 --- /dev/null +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/SuggestionRestControllerIT.java @@ -0,0 +1,176 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ +package org.dspace.app.rest; + +import static com.jayway.jsonpath.matchers.JsonPathMatchers.hasJsonPath; +import static org.hamcrest.Matchers.allOf; +import static org.hamcrest.Matchers.is; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import org.dspace.app.rest.test.AbstractControllerIntegrationTest; +import org.dspace.builder.CollectionBuilder; +import org.dspace.builder.CommunityBuilder; +import org.dspace.builder.ItemBuilder; +import org.dspace.content.Collection; +import org.dspace.content.Item; +import org.hamcrest.Matchers; +import org.junit.Before; +import org.junit.Test; + +/** + * Integration test for the {@link org.dspace.app.rest.repository.SuggestionRestController} + * + * @author Milan Majchrak (dspace at dataquest.sk) + */ +public class SuggestionRestControllerIT extends AbstractControllerIntegrationTest { + + private Item publicItem; + private Collection col; + private final String SUBJECT_SEARCH_VALUE = "test subject"; + private final String LANGUAGE_SEARCH_VALUE_KEY = "Alumu-Tesu"; + private final String LANGUAGE_SEARCH_VALUE_VALUE = "aab"; + private final String ITEM_TITLE = "Item title"; + + @Before + public void setup() throws Exception { + context.turnOffAuthorisationSystem(); + // 1. A community-collection structure with one parent community and one collection + parentCommunity = CommunityBuilder.createCommunity(context) + .withName("Parent Community") + .build(); + + col = CollectionBuilder.createCollection(context, parentCommunity).withName("Collection").build(); + + // 2. Create item and add it to the collection + publicItem = ItemBuilder.createItem(context, col) + .withTitle(ITEM_TITLE) + .withMetadata("dc", "subject", null, SUBJECT_SEARCH_VALUE ) + .build(); + + context.restoreAuthSystemState(); + } + + /** + * Should return formatted suggestions in the VocabularyEntryRest objects + */ + @Test + public void testSearchBySubjectAcSolrIndex() throws Exception { + String userToken = getAuthToken(eperson.getEmail(), password); + // substring = find only by the `test` value + getClient(userToken).perform(get("/api/suggestions?autocompleteCustom=solr-subject_ac&searchValue=" + + SUBJECT_SEARCH_VALUE.substring(0, 4))) + .andExpect(status().isOk()) + .andExpect(content().contentType(contentType)) + .andExpect(jsonPath("$._embedded.vocabularyEntryRests", Matchers.hasItem( + allOf( + hasJsonPath("$.display", is(SUBJECT_SEARCH_VALUE)), + hasJsonPath("$.value", is(SUBJECT_SEARCH_VALUE)), + hasJsonPath("$.type", is("vocabularyEntry")) + )))); + } + + /** + * Should return no suggestions + */ + @Test + public void testSearchBySubjectAcSolrIndex_noResults() throws Exception { + String userToken = getAuthToken(eperson.getEmail(), password); + // substring = find only by the `test` value + getClient(userToken).perform(get("/api/suggestions?autocompleteCustom=solr-subject_ac&searchValue=" + + "no such subject")) + .andExpect(status().isOk()) + .andExpect(content().contentType(contentType)) + .andExpect(jsonPath("$.page.totalElements", is(0))) + .andExpect(jsonPath("$._embedded.vocabularyEntryRests").doesNotExist()); + } + + /** + * Should return suggestions from the JSON file + */ + @Test + public void testSearchByLanguageFromJson() throws Exception { + String userToken = getAuthToken(eperson.getEmail(), password); + getClient(userToken).perform( + get("/api/suggestions?autocompleteCustom=json_static-iso_langs.json&searchValue=" + + LANGUAGE_SEARCH_VALUE_KEY)) + .andExpect(status().isOk()) + .andExpect(content().contentType(contentType)) + .andExpect(jsonPath("$.page.totalElements", is(1))) + .andExpect(jsonPath("$._embedded.vocabularyEntryRests", Matchers.hasItem( + allOf( + hasJsonPath("$.display", is(LANGUAGE_SEARCH_VALUE_KEY)), + hasJsonPath("$.value", is(LANGUAGE_SEARCH_VALUE_VALUE)), + hasJsonPath("$.type", is("vocabularyEntry")) + )))); + } + + /** + * Should return no suggestions from the JSON file + */ + @Test + public void testSearchByLanguageFromJson_noResults() throws Exception { + String userToken = getAuthToken(eperson.getEmail(), password); + getClient(userToken).perform( + get("/api/suggestions?autocompleteCustom=json_static-iso_langs.json&searchValue=" + + "no such language")) + .andExpect(status().isOk()) + .andExpect(content().contentType(contentType)) + .andExpect(jsonPath("$.page.totalElements", is(0))) + .andExpect(jsonPath("$._embedded.vocabularyEntryRests").doesNotExist()); + } + + /** + * Should return suggestions from the solr `title_ac` index. + * Compose specific query from the definition and the search value. + */ + @Test + public void testSearchBySpecificQueryFromSolr() throws Exception { + String userToken = getAuthToken(eperson.getEmail(), password); + getClient(userToken).perform( + get("/api/suggestions?autocompleteCustom=solr-title_ac?query=title_ac:**&searchValue=" + + ITEM_TITLE.substring(0, 4))) + .andExpect(status().isOk()) + .andExpect(content().contentType(contentType)) + .andExpect(jsonPath("$.page.totalElements", is(1))) + .andExpect(jsonPath("$._embedded.vocabularyEntryRests", Matchers.hasItem( + allOf( + hasJsonPath("$.display", is(ITEM_TITLE)), + hasJsonPath("$.value", is(ITEM_TITLE)), + hasJsonPath("$.type", is("vocabularyEntry")) + )))); + } + + /** + * Should return suggestions from the solr `title_ac` index. + * Compose specific query from the definition and the search value. + */ + @Test + public void testSearchBySpecificQueryFromSolr_noresults() throws Exception { + String userToken = getAuthToken(eperson.getEmail(), password); + getClient(userToken).perform( + get("/api/suggestions?autocompleteCustom=solr-title_ac?query=title_ac:**&searchValue=" + + "no such title")) + .andExpect(status().isOk()) + .andExpect(content().contentType(contentType)) + .andExpect(jsonPath("$.page.totalElements", is(0))) + .andExpect(jsonPath("$._embedded.vocabularyEntryRests").doesNotExist()); + } + + /** + * Should return 401 Forbidden + */ + @Test + public void testShouldNotAuthorized() throws Exception { + getClient().perform(get("/api/suggestions?autocompleteCustom=solr-title_ac?query=title_ac:**&searchValue=" + + "no such title")) + .andExpect(status().isUnauthorized()); + } +} diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/matcher/FacetEntryMatcher.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/matcher/FacetEntryMatcher.java index 23d66754dcc6..939873b5c4ba 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/matcher/FacetEntryMatcher.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/matcher/FacetEntryMatcher.java @@ -131,6 +131,16 @@ public static Matcher clarinLicenseRightsFacet(boolean hasNext) ); } + public static Matcher dcTypeFacet(boolean hasNext) { + return allOf( + hasJsonPath("$.name", is("dctype")), + hasJsonPath("$.facetType", is("text")), + hasJsonPath("$.facetLimit", any(Integer.class)), + hasJsonPath("$._links.self.href", containsString("api/discover/facets/dctype")), + hasJsonPath("$._links", matchNextLink(hasNext, "api/discover/facets/dctype")) + ); + } + public static Matcher clarinItemsLanguageFacet(boolean hasNext) { return allOf( hasJsonPath("$.name", is("language")), @@ -162,11 +172,11 @@ public static Matcher clarinItemsCommunityFacet(boolean hasNext) */ public static Matcher typeFacet(boolean b) { return allOf( - hasJsonPath("$.name", is("itemtype")), + hasJsonPath("$.name", is("type")), hasJsonPath("$.facetType", is("text")), hasJsonPath("$.facetLimit", any(Integer.class)), - hasJsonPath("$._links.self.href", containsString("api/discover/facets/itemtype")), - hasJsonPath("$._links", matchNextLink(b, "api/discover/facets/itemtype")) + hasJsonPath("$._links.self.href", containsString("api/discover/facets/type")), + hasJsonPath("$._links", matchNextLink(b, "api/discover/facets/type")) ); } diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/matcher/SearchFilterMatcher.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/matcher/SearchFilterMatcher.java index b5533a955505..c708ca96b98c 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/matcher/SearchFilterMatcher.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/matcher/SearchFilterMatcher.java @@ -188,7 +188,7 @@ public static Matcher clarinItemsCommunityFilter() { public static Matcher clarinItemsTypeFilter() { return allOf( - hasJsonPath("$.filter", is("itemtype")), + hasJsonPath("$.filter", is("type")), hasJsonPath("$.hasFacets", is(true)), hasJsonPath("$.type", is("text")), hasJsonPath("$.openByDefault", is(false)), @@ -226,4 +226,14 @@ public static Matcher clarinDataProviderFacet() { checkOperators() ); } + + public static Matcher dcTypeFilter() { + return allOf( + hasJsonPath("$.filter", is("dctype")), + hasJsonPath("$.hasFacets", is(false)), + hasJsonPath("$.type", is("text")), + hasJsonPath("$.openByDefault", is(false)), + checkOperators() + ); + } } diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/utils/UtilsTest.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/utils/UtilsTest.java new file mode 100644 index 000000000000..68c521bfaf06 --- /dev/null +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/utils/UtilsTest.java @@ -0,0 +1,61 @@ +/** + * The contents of this file are subject to the license and copyright + * detailed in the LICENSE and NOTICE files at the root of the source + * tree and available online at + * + * http://www.dspace.org/license/ + */ +package org.dspace.app.rest.utils; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import org.dspace.AbstractUnitTest; +import org.junit.Test; + +/** + * Unit tests for {@link Utils} + * + * @author Milan Majchrak (dspace at dataquest.sk) + */ +public class UtilsTest extends AbstractUnitTest { + + @Test + public void testNormalizeDiscoverQueryWithMixedCharactersAndNumbers() { + String searchValue = "my1Search2"; + String searchField = "dc.contributor.author"; + + String expected = "dc.contributor.author:*my* AND dc.contributor.author:*Search* AND " + + "dc.contributor.author:*1* AND dc.contributor.author:*2*"; + + String result = Utils.normalizeDiscoverQuery(searchValue, searchField); + assertEquals(expected, result); + } + + @Test + public void testNormalizeDiscoverQueryWithOnlyCharacters() { + String searchValue = "mySearch"; + String searchField = "dc.contributor.author"; + + String result = Utils.normalizeDiscoverQuery(searchValue, searchField); + assertNull(result); + } + + @Test + public void testNormalizeDiscoverQueryWithOnlyNumbers() { + String searchValue = "12345"; + String searchField = "dc.contributor.author"; + + String result = Utils.normalizeDiscoverQuery(searchValue, searchField); + assertNull(result); + } + + @Test + public void testNormalizeDiscoverQueryWithEmptyString() { + String searchValue = ""; + String searchField = "dc.contributor.author"; + + String result = Utils.normalizeDiscoverQuery(searchValue, searchField); + assertNull(result); + } +} diff --git a/dspace/config/clarin-dspace.cfg b/dspace/config/clarin-dspace.cfg index 6c00f45b5a1e..708e5c9b1c9b 100644 --- a/dspace/config/clarin-dspace.cfg +++ b/dspace/config/clarin-dspace.cfg @@ -288,3 +288,14 @@ elg.download-location.exposed = 0 # left here for reference #download.email.cc = ${info.recipient} download.email.cc = ${mail.admin} + +#### Submission forms #### +# `autocomplete.custom.separator.*` is a special separator used to distinguish values +# in the results from the current Solr index. For example, `solr-subject_ac` is a special index for subjects, +# and its values look like this: `value1 ||| VALUE1`. The correct value is the second one. +# `//` is because of special character +autocomplete.custom.separator.solr-subject_ac = \\|\\|\\| +autocomplete.custom.separator.solr-publisher_ac = \\|\\|\\| +autocomplete.custom.separator.solr-dataProvider_ac = \\|\\|\\| +autocomplete.custom.separator.solr-dctype_ac = \\|\\|\\| +autocomplete.custom.allowed = solr-author_ac,solr-publisher_ac,solr-dataProvider_ac,solr-dctype_ac,solr-subject_ac,solr-handle_title_ac,json_static-iso_langs.json diff --git a/dspace/config/spring/api/discovery.xml b/dspace/config/spring/api/discovery.xml index a5cce1ffd2b9..c83e3b011aff 100644 --- a/dspace/config/spring/api/discovery.xml +++ b/dspace/config/spring/api/discovery.xml @@ -200,6 +200,7 @@ + @@ -2545,7 +2546,7 @@ - + dc.type @@ -2557,6 +2558,17 @@ + + + + + dc.type + + + + + + diff --git a/dspace/config/submission-forms.dtd b/dspace/config/submission-forms.dtd index 932494dc7728..01bb8ea60d9f 100644 --- a/dspace/config/submission-forms.dtd +++ b/dspace/config/submission-forms.dtd @@ -81,6 +81,7 @@ + diff --git a/dspace/config/submission-forms.xml b/dspace/config/submission-forms.xml index 1a63054ec9d2..e00cf2fb5936 100644 --- a/dspace/config/submission-forms.xml +++ b/dspace/config/submission-forms.xml @@ -85,7 +85,7 @@ author true - clarin-name + autocomplete Enter the author's name (Family name, Given names). true - tag + autocomplete Enter appropriate subject keyword or phrase and press the Add button. You can repeat it for multiple keywords or use separators i.e., Enter and comma, which will split it accordingly. Start typing the keyword and use autocomplete form that will appear. End your input by pressing @@ -1703,7 +1703,7 @@ true - autocomplete + autocomplete The name of the publisher of the original analog or born digital object. Use your home institution if this is a born digital object being published now. Start typing the publisher and use autocomplete form that will appear if applicable. End your input by pressing ESC if you @@ -1719,9 +1719,9 @@ false - autocomplete + autocomplete This concerns the digital object (not the analog - original). An institution from which the data come. Used eg. to give proper attribution. Generally + original). An institution from which the data come. Used e.g. to give proper attribution. Generally different from publisher. @@ -1757,7 +1757,7 @@ false - autocomplete + autocomplete The type should be different from what you have entered in the first step. Examples: photo or painting for IMAGE, book or letter for TEXT, etc. Type is required @@ -1787,7 +1787,7 @@ true TEXT - autocomplete + autocomplete Select the language of the main content of the item. Multiple languages are possible. Start typing the language and use autocomplete form that will appear if applicable. Better to list all the languages then to use the 'mul' iso code (if there are too many, contact support). @@ -1802,7 +1802,7 @@ true VIDEO,IMAGE,SOUND,3D - autocomplete + autocomplete Optionally, select the language of the main content of the item. Multiple languages are possible. Start typing the language and use autocomplete form that will appear if applicable. Better to list all the languages then to use the 'mul' iso code (if there are too many, contact support). @@ -1818,7 +1818,7 @@ true - tag + autocomplete Enter appropriate subject keyword or phrase and press the Add button. Use keywords to specify also people, places and times (period, era, date range etc) the resource is about. You can use hierarchical subjects, separate the hierarchy levels with two colons (::). Eg. @@ -1985,7 +1985,7 @@ true - autocomplete + autocomplete The name of the publisher of the original analog or born digital object. Use your home institution if this is a born digital object being published now. Start typing the publisher and use autocomplete form that will appear if applicable. End your input by pressing ESC if you @@ -2052,7 +2052,7 @@ iso true - autocomplete + autocomplete Select the language of the main content of the item. Multiple languages are possible. Start typing the language and use autocomplete form that will appear if applicable. Better to list all the languages then to use the 'mul' iso code (if there are too many, contact support). @@ -2067,7 +2067,7 @@ true - autocomplete + autocomplete Enter appropriate subject keyword or phrase and press the Add button. You can repeat it for multiple keywords or use separators i.e., comma and semicolon, which will split it accordingly. Start typing the keyword and use autocomplete form that will appear. End your input by pressing @@ -2116,7 +2116,7 @@ replaces true - onebox + autocomplete URL to a related resource that is supplanted, displaced, or superseded by the described resource. If the replaced resource is in this repository start typing its name or handle and select the resource from the autocomplete popup. @@ -2130,7 +2130,7 @@ isreplacedby true - onebox + autocomplete A related resource that supplants, displaces, or supersedes the described resource. @@ -3225,7 +3225,7 @@ - + diff --git a/dspace/config/submission-forms_cs.xml b/dspace/config/submission-forms_cs.xml index bd06c7fdeac4..227508071cb2 100644 --- a/dspace/config/submission-forms_cs.xml +++ b/dspace/config/submission-forms_cs.xml @@ -85,7 +85,7 @@ author true - clarin-name + autocomplete Enter the author's name (Family name, Given names). true - tag + autocomplete Enter appropriate subject keyword or phrase and press the Add button. You can repeat it for multiple keywords or use separators i.e., Enter and comma, which will split it accordingly. Start typing the keyword and use autocomplete form that will appear. End your input by pressing @@ -1703,7 +1703,7 @@ true - autocomplete + autocomplete The name of the publisher of the original analog or born digital object. Use your home institution if this is a born digital object being published now. Start typing the publisher and use autocomplete form that will appear if applicable. End your input by pressing ESC if you @@ -1719,9 +1719,9 @@ false - autocomplete + autocomplete This concerns the digital object (not the analog - original). An institution from which the data come. Used eg. to give proper attribution. Generally + original). An institution from which the data come. Used e.g. to give proper attribution. Generally different from publisher. @@ -1757,7 +1757,7 @@ false - autocomplete + autocomplete The type should be different from what you have entered in the first step. Examples: photo or painting for IMAGE, book or letter for TEXT, etc. Type is required @@ -1771,7 +1771,6 @@ false - aaa textarea Enter a description of the submitted data. Please give us a description @@ -1785,7 +1784,7 @@ true TEXT - autocomplete + autocomplete Select the language of the main content of the item. Multiple languages are possible. Start typing the language and use autocomplete form that will appear if applicable. Better to list all the languages then to use the 'mul' iso code (if there are too many, contact support). @@ -1800,7 +1799,7 @@ true VIDEO,IMAGE,SOUND,3D - autocomplete + autocomplete Optionally, select the language of the main content of the item. Multiple languages are possible. Start typing the language and use autocomplete form that will appear if applicable. Better to list all the languages then to use the 'mul' iso code (if there are too many, contact support). @@ -1816,7 +1815,7 @@ true - tag + autocomplete Enter appropriate subject keyword or phrase and press the Add button. Use keywords to specify also people, places and times (period, era, date range etc) the resource is about. You can use hierarchical subjects, separate the hierarchy levels with two colons (::). Eg. @@ -1983,7 +1982,7 @@ true - autocomplete + autocomplete The name of the publisher of the original analog or born digital object. Use your home institution if this is a born digital object being published now. Start typing the publisher and use autocomplete form that will appear if applicable. End your input by pressing ESC if you @@ -2050,7 +2049,7 @@ iso true - autocomplete + autocomplete Select the language of the main content of the item. Multiple languages are possible. Start typing the language and use autocomplete form that will appear if applicable. Better to list all the languages then to use the 'mul' iso code (if there are too many, contact support). @@ -2065,7 +2064,7 @@ true - autocomplete + autocomplete Enter appropriate subject keyword or phrase and press the Add button. You can repeat it for multiple keywords or use separators i.e., comma and semicolon, which will split it accordingly. Start typing the keyword and use autocomplete form that will appear. End your input by pressing @@ -2106,7 +2105,7 @@ - + dc @@ -2114,7 +2113,7 @@ replaces true - onebox + autocomplete URL příbuzného záznamu, který je tímto záznamem nahrazen. Pokud je příbuzný záznam v tomto repozitáři, začněte psát jeho název, nebo handle a vyberte záznam z nabídky. @@ -2128,7 +2127,7 @@ isreplacedby true - onebox + autocomplete Příbuzný záznam, který nahrazuje tento. @@ -3223,7 +3222,7 @@ - + diff --git a/dspace/solr/search/conf/schema.xml b/dspace/solr/search/conf/schema.xml index a80cfdedfd34..3a6125c1f9ac 100644 --- a/dspace/solr/search/conf/schema.xml +++ b/dspace/solr/search/conf/schema.xml @@ -126,6 +126,7 @@ + @@ -140,6 +141,7 @@ + - + @@ -194,11 +197,17 @@ - + + + + + + + - + - + @@ -361,5 +370,21 @@ + + + + + + + + + + + + + + + +