diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 18:07:22 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-10 18:07:22 +0000 |
commit | c04dcc2e7d834218ef2d4194331e383402495ae1 (patch) | |
tree | 7333e38d10d75386e60f336b80c2443c1166031d /xbmc/utils/LangCodeExpander.cpp | |
parent | Initial commit. (diff) | |
download | kodi-c04dcc2e7d834218ef2d4194331e383402495ae1.tar.xz kodi-c04dcc2e7d834218ef2d4194331e383402495ae1.zip |
Adding upstream version 2:20.4+dfsg.upstream/2%20.4+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'xbmc/utils/LangCodeExpander.cpp')
-rw-r--r-- | xbmc/utils/LangCodeExpander.cpp | 1792 |
1 files changed, 1792 insertions, 0 deletions
diff --git a/xbmc/utils/LangCodeExpander.cpp b/xbmc/utils/LangCodeExpander.cpp new file mode 100644 index 0000000..f683905 --- /dev/null +++ b/xbmc/utils/LangCodeExpander.cpp @@ -0,0 +1,1792 @@ +/* + * Copyright (C) 2005-2020 Team Kodi + * This file is part of Kodi - https://kodi.tv + * + * SPDX-License-Identifier: GPL-2.0-or-later + * See LICENSES/README.md for more information. + */ + +#include "LangCodeExpander.h" + +#include "LangInfo.h" +#include "utils/RegExp.h" +#include "utils/StringUtils.h" +#include "utils/XBMCTinyXML.h" + +#include <algorithm> +#include <array> + +#define MAKECODE(a, b, c, d) \ + ((((long)(a)) << 24) | (((long)(b)) << 16) | (((long)(c)) << 8) | (long)(d)) +#define MAKETWOCHARCODE(a, b) ((((long)(a)) << 8) | (long)(b)) + +typedef struct LCENTRY +{ + long code; + const char* name; +} LCENTRY; + +extern const std::array<struct LCENTRY, 186> g_iso639_1; +extern const std::array<struct LCENTRY, 540> g_iso639_2; + +struct ISO639 +{ + const char* iso639_1; + const char* iso639_2b; + const char* iso639_2t; + const char* win_id; +}; + +struct ISO3166_1 +{ + const char* alpha2; + const char* alpha3; +}; + +// declared as extern to allow forward declaration +extern const std::array<ISO639, 190> LanguageCodes; +extern const std::array<ISO3166_1, 245> RegionCodes; + +CLangCodeExpander::CLangCodeExpander() = default; + +CLangCodeExpander::~CLangCodeExpander() = default; + +void CLangCodeExpander::Clear() +{ + m_mapUser.clear(); +} + +void CLangCodeExpander::LoadUserCodes(const TiXmlElement* pRootElement) +{ + if (pRootElement != NULL) + { + m_mapUser.clear(); + + std::string sShort, sLong; + + const TiXmlNode* pLangCode = pRootElement->FirstChild("code"); + while (pLangCode != NULL) + { + const TiXmlNode* pShort = pLangCode->FirstChildElement("short"); + const TiXmlNode* pLong = pLangCode->FirstChildElement("long"); + if (pShort != NULL && pLong != NULL) + { + sShort = pShort->FirstChild()->Value(); + sLong = pLong->FirstChild()->Value(); + StringUtils::ToLower(sShort); + + m_mapUser[sShort] = sLong; + } + + pLangCode = pLangCode->NextSibling(); + } + } +} + +bool CLangCodeExpander::Lookup(const std::string& code, std::string& desc) +{ + if (LookupInUserMap(code, desc)) + return true; + + if (LookupInISO639Tables(code, desc)) + return true; + + if (LookupInLangAddons(code, desc)) + return true; + + // Language code with subtag is supported only with language addons + // or with user defined map, then if not found we fallback by obtaining + // the primary code description only and appending the remaining + int iSplit = code.find('-'); + if (iSplit > 0) + { + std::string primaryTagDesc; + const bool hasPrimaryTagDesc = Lookup(code.substr(0, iSplit), primaryTagDesc); + std::string subtagCode = code.substr(iSplit + 1); + if (hasPrimaryTagDesc) + { + if (primaryTagDesc.length() > 0) + desc = primaryTagDesc; + else + desc = code.substr(0, iSplit); + + if (subtagCode.length() > 0) + desc += " - " + subtagCode; + + return true; + } + } + + return false; +} + +bool CLangCodeExpander::Lookup(const int code, std::string& desc) +{ + char lang[3]; + lang[2] = 0; + lang[1] = (code & 0xFF); + lang[0] = (code >> 8) & 0xFF; + + return Lookup(lang, desc); +} + +bool CLangCodeExpander::ConvertISO6391ToISO6392B(const std::string& strISO6391, + std::string& strISO6392B, + bool checkWin32Locales /*= false*/) +{ + // not a 2 char code + if (strISO6391.length() != 2) + return false; + + std::string strISO6391Lower(strISO6391); + StringUtils::ToLower(strISO6391Lower); + StringUtils::Trim(strISO6391Lower); + + for (const auto& codes : LanguageCodes) + { + if (strISO6391Lower == codes.iso639_1) + { + if (checkWin32Locales && codes.win_id) + { + strISO6392B = codes.win_id; + return true; + } + + strISO6392B = codes.iso639_2b; + return true; + } + } + + return false; +} + +bool CLangCodeExpander::ConvertToISO6392B(const std::string& strCharCode, + std::string& strISO6392B, + bool checkWin32Locales /* = false */) +{ + + //first search in the user defined map + if (LookupUserCode(strCharCode, strISO6392B)) + return true; + + if (strCharCode.size() == 2) + return g_LangCodeExpander.ConvertISO6391ToISO6392B(strCharCode, strISO6392B, checkWin32Locales); + + if (strCharCode.size() == 3) + { + std::string charCode(strCharCode); + StringUtils::ToLower(charCode); + for (const auto& codes : LanguageCodes) + { + if (charCode == codes.iso639_2b || + (checkWin32Locales && codes.win_id != NULL && charCode == codes.win_id)) + { + strISO6392B = charCode; + return true; + } + } + + for (const auto& codes : RegionCodes) + { + if (charCode == codes.alpha3) + { + strISO6392B = charCode; + return true; + } + } + } + else if (strCharCode.size() > 3) + { + for (const auto& codes : g_iso639_2) + { + if (StringUtils::EqualsNoCase(strCharCode, codes.name)) + { + strISO6392B = CodeToString(codes.code); + return true; + } + } + + // Try search on language addons + strISO6392B = g_langInfo.ConvertEnglishNameToAddonLocale(strCharCode); + if (!strISO6392B.empty()) + return true; + } + return false; +} + +bool CLangCodeExpander::ConvertToISO6392T(const std::string& strCharCode, + std::string& strISO6392T, + bool checkWin32Locales /* = false */) +{ + if (!ConvertToISO6392B(strCharCode, strISO6392T, checkWin32Locales)) + return false; + + for (const auto& codes : LanguageCodes) + { + if (strISO6392T == codes.iso639_2b || + (checkWin32Locales && codes.win_id != NULL && strISO6392T == codes.win_id)) + { + if (codes.iso639_2t != nullptr) + strISO6392T = codes.iso639_2t; + return true; + } + } + return false; +} + + +bool CLangCodeExpander::LookupUserCode(const std::string& desc, std::string& userCode) +{ + for (STRINGLOOKUPTABLE::const_iterator it = m_mapUser.begin(); it != m_mapUser.end(); ++it) + { + if (StringUtils::EqualsNoCase(desc, it->first) || StringUtils::EqualsNoCase(desc, it->second)) + { + userCode = it->first; + return true; + } + } + return false; +} + +#ifdef TARGET_WINDOWS +bool CLangCodeExpander::ConvertISO31661Alpha2ToISO31661Alpha3(const std::string& strISO31661Alpha2, + std::string& strISO31661Alpha3) +{ + if (strISO31661Alpha2.length() != 2) + return false; + + std::string strLower(strISO31661Alpha2); + StringUtils::ToLower(strLower); + StringUtils::Trim(strLower); + for (const auto& codes : RegionCodes) + { + if (strLower == codes.alpha2) + { + strISO31661Alpha3 = codes.alpha3; + return true; + } + } + + return true; +} + +bool CLangCodeExpander::ConvertWindowsLanguageCodeToISO6392B( + const std::string& strWindowsLanguageCode, std::string& strISO6392B) +{ + if (strWindowsLanguageCode.length() != 3) + return false; + + std::string strLower(strWindowsLanguageCode); + StringUtils::ToLower(strLower); + for (const auto& codes : LanguageCodes) + { + if ((codes.win_id && strLower == codes.win_id) || strLower == codes.iso639_2b) + { + strISO6392B = codes.iso639_2b; + return true; + } + } + + return false; +} +#endif + +bool CLangCodeExpander::ConvertToISO6391(const std::string& lang, std::string& code) +{ + if (lang.empty()) + return false; + + //first search in the user defined map + if (LookupUserCode(lang, code)) + return true; + + if (lang.length() == 2) + { + std::string tmp; + if (Lookup(lang, tmp)) + { + code = lang; + return true; + } + } + else if (lang.length() == 3) + { + std::string lower(lang); + StringUtils::ToLower(lower); + for (const auto& codes : LanguageCodes) + { + if (lower == codes.iso639_2b || (codes.win_id && lower == codes.win_id)) + { + code = codes.iso639_1; + return true; + } + } + + for (const auto& codes : RegionCodes) + { + if (lower == codes.alpha3) + { + code = codes.alpha2; + return true; + } + } + } + + // check if lang is full language name + std::string tmp; + if (ReverseLookup(lang, tmp)) + { + if (tmp.length() == 2) + { + code = tmp; + return true; + } + + if (tmp.length() == 3) + { + // there's only an iso639-2 code that is identical to the language name, e.g. Yao + if (StringUtils::EqualsNoCase(tmp, lang)) + return false; + + return ConvertToISO6391(tmp, code); + } + } + + return false; +} + +bool CLangCodeExpander::ReverseLookup(const std::string& desc, std::string& code) +{ + if (desc.empty()) + return false; + + std::string descTmp(desc); + StringUtils::Trim(descTmp); + + // First find to user-defined languages + for (STRINGLOOKUPTABLE::const_iterator it = m_mapUser.begin(); it != m_mapUser.end(); ++it) + { + if (StringUtils::EqualsNoCase(descTmp, it->second)) + { + code = it->first; + return true; + } + } + + for (const auto& codes : g_iso639_1) + { + if (StringUtils::EqualsNoCase(descTmp, codes.name)) + { + code = CodeToString(codes.code); + return true; + } + } + + for (const auto& codes : g_iso639_2) + { + if (StringUtils::EqualsNoCase(descTmp, codes.name)) + { + code = CodeToString(codes.code); + return true; + } + } + + // Find on language addons + code = g_langInfo.ConvertEnglishNameToAddonLocale(descTmp); + if (!code.empty()) + return true; + + return false; +} + +bool CLangCodeExpander::LookupInUserMap(const std::string& code, std::string& desc) +{ + if (code.empty()) + return false; + + // make sure we convert to lowercase before trying to find it + std::string sCode(code); + StringUtils::ToLower(sCode); + StringUtils::Trim(sCode); + + STRINGLOOKUPTABLE::iterator it = m_mapUser.find(sCode); + if (it != m_mapUser.end()) + { + desc = it->second; + return true; + } + + return false; +} + +bool CLangCodeExpander::LookupInLangAddons(const std::string& code, std::string& desc) +{ + if (code.empty()) + return false; + + std::string sCode{code}; + StringUtils::Trim(sCode); + StringUtils::ToLower(sCode); + StringUtils::Replace(sCode, '-', '_'); + + desc = g_langInfo.GetEnglishLanguageName(sCode); + return !desc.empty(); +} + +bool CLangCodeExpander::LookupInISO639Tables(const std::string& code, std::string& desc) +{ + if (code.empty()) + return false; + + long longcode; + std::string sCode(code); + StringUtils::ToLower(sCode); + StringUtils::Trim(sCode); + + if (sCode.length() == 2) + { + longcode = MAKECODE('\0', '\0', sCode[0], sCode[1]); + for (const auto& codes : g_iso639_1) + { + if (codes.code == longcode) + { + desc = codes.name; + return true; + } + } + } + else if (sCode.length() == 3) + { + longcode = MAKECODE('\0', sCode[0], sCode[1], sCode[2]); + for (const auto& codes : g_iso639_2) + { + if (codes.code == longcode) + { + desc = codes.name; + return true; + } + } + } + return false; +} + +std::string CLangCodeExpander::CodeToString(long code) +{ + std::string ret; + for (unsigned int j = 0; j < 4; j++) + { + char c = (char)code & 0xFF; + if (c == '\0') + break; + + ret.insert(0, 1, c); + code >>= 8; + } + return ret; +} + +bool CLangCodeExpander::CompareFullLanguageNames(const std::string& lang1, const std::string& lang2) +{ + if (StringUtils::EqualsNoCase(lang1, lang2)) + return true; + + std::string expandedLang1, expandedLang2, code1, code2; + + if (!ReverseLookup(lang1, code1)) + return false; + + code1 = lang1; + if (!ReverseLookup(lang2, code2)) + return false; + + code2 = lang2; + Lookup(expandedLang1, code1); + Lookup(expandedLang2, code2); + + return StringUtils::EqualsNoCase(expandedLang1, expandedLang2); +} + +std::vector<std::string> CLangCodeExpander::GetLanguageNames( + LANGFORMATS format /* = CLangCodeExpander::ISO_639_1 */, + LANG_LIST list /* = LANG_LIST::DEFAULT */) +{ + std::map<std::string, std::string> langMap; + + if (format == CLangCodeExpander::ISO_639_2) + std::transform(g_iso639_2.begin(), g_iso639_2.end(), std::inserter(langMap, langMap.end()), + [](const LCENTRY& e) { return std::make_pair(CodeToString(e.code), e.name); }); + else + std::transform(g_iso639_1.begin(), g_iso639_1.end(), std::inserter(langMap, langMap.end()), + [](const LCENTRY& e) { return std::make_pair(CodeToString(e.code), e.name); }); + + if (list == LANG_LIST::INCLUDE_ADDONS || list == LANG_LIST::INCLUDE_ADDONS_USERDEFINED) + { + g_langInfo.GetAddonsLanguageCodes(langMap); + } + + // User-defined languages can override existing ones + if (list == LANG_LIST::INCLUDE_USERDEFINED || list == LANG_LIST::INCLUDE_ADDONS_USERDEFINED) + { + for (const auto& value : m_mapUser) + { + langMap[value.first] = value.second; + } + } + + // Sort by name and remove duplicates + std::set<std::string, sortstringbyname> languages; + for (const auto& lang : langMap) + { + languages.insert(lang.second); + } + + return std::vector<std::string>(languages.begin(), languages.end()); +} + +bool CLangCodeExpander::CompareISO639Codes(const std::string& code1, const std::string& code2) +{ + if (StringUtils::EqualsNoCase(code1, code2)) + return true; + + std::string expandedLang1; + if (!Lookup(code1, expandedLang1)) + return false; + + std::string expandedLang2; + if (!Lookup(code2, expandedLang2)) + return false; + + return StringUtils::EqualsNoCase(expandedLang1, expandedLang2); +} + +std::string CLangCodeExpander::ConvertToISO6392B(const std::string& lang) +{ + if (lang.empty()) + return lang; + + std::string two, three; + if (ConvertToISO6391(lang, two)) + { + if (ConvertToISO6392B(two, three)) + return three; + } + + return lang; +} + +std::string CLangCodeExpander::ConvertToISO6392T(const std::string& lang) +{ + if (lang.empty()) + return lang; + + std::string two, three; + if (ConvertToISO6391(lang, two)) + { + if (ConvertToISO6392T(two, three)) + return three; + } + + return lang; +} + +std::string CLangCodeExpander::FindLanguageCodeWithSubtag(const std::string& str) +{ + CRegExp regLangCode; + if (regLangCode.RegComp( + "(?:^|\\s|\\()(([A-Za-z]{2,3})-([A-Za-z]{2}|[0-9]{3}|[A-Za-z]{4}))(?:$|\\s|\\))") && + regLangCode.RegFind(str) >= 0) + { + return regLangCode.GetMatch(1); + } + return ""; +} + +// clang-format off +const std::array<struct LCENTRY, 186> g_iso639_1 = {{ + {MAKECODE('\0', '\0', 'a', 'a'), "Afar"}, + {MAKECODE('\0', '\0', 'a', 'b'), "Abkhazian"}, + {MAKECODE('\0', '\0', 'a', 'e'), "Avestan"}, + {MAKECODE('\0', '\0', 'a', 'f'), "Afrikaans"}, + {MAKECODE('\0', '\0', 'a', 'k'), "Akan"}, + {MAKECODE('\0', '\0', 'a', 'm'), "Amharic"}, + {MAKECODE('\0', '\0', 'a', 'n'), "Aragonese"}, + {MAKECODE('\0', '\0', 'a', 'r'), "Arabic"}, + {MAKECODE('\0', '\0', 'a', 's'), "Assamese"}, + {MAKECODE('\0', '\0', 'a', 'v'), "Avaric"}, + {MAKECODE('\0', '\0', 'a', 'y'), "Aymara"}, + {MAKECODE('\0', '\0', 'a', 'z'), "Azerbaijani"}, + {MAKECODE('\0', '\0', 'b', 'a'), "Bashkir"}, + {MAKECODE('\0', '\0', 'b', 'e'), "Belarusian"}, + {MAKECODE('\0', '\0', 'b', 'g'), "Bulgarian"}, + {MAKECODE('\0', '\0', 'b', 'h'), "Bihari"}, + {MAKECODE('\0', '\0', 'b', 'i'), "Bislama"}, + {MAKECODE('\0', '\0', 'b', 'm'), "Bambara"}, + {MAKECODE('\0', '\0', 'b', 'n'), "Bengali; Bangla"}, + {MAKECODE('\0', '\0', 'b', 'o'), "Tibetan"}, + {MAKECODE('\0', '\0', 'b', 'r'), "Breton"}, + {MAKECODE('\0', '\0', 'b', 's'), "Bosnian"}, + {MAKECODE('\0', '\0', 'c', 'a'), "Catalan"}, + {MAKECODE('\0', '\0', 'c', 'e'), "Chechen"}, + {MAKECODE('\0', '\0', 'c', 'h'), "Chamorro"}, + {MAKECODE('\0', '\0', 'c', 'o'), "Corsican"}, + {MAKECODE('\0', '\0', 'c', 'r'), "Cree"}, + {MAKECODE('\0', '\0', 'c', 's'), "Czech"}, + {MAKECODE('\0', '\0', 'c', 'u'), "Church Slavic"}, + {MAKECODE('\0', '\0', 'c', 'v'), "Chuvash"}, + {MAKECODE('\0', '\0', 'c', 'y'), "Welsh"}, + {MAKECODE('\0', '\0', 'd', 'a'), "Danish"}, + {MAKECODE('\0', '\0', 'd', 'e'), "German"}, + {MAKECODE('\0', '\0', 'd', 'v'), "Dhivehi"}, + {MAKECODE('\0', '\0', 'd', 'z'), "Dzongkha"}, + {MAKECODE('\0', '\0', 'e', 'e'), "Ewe"}, + {MAKECODE('\0', '\0', 'e', 'l'), "Greek"}, + {MAKECODE('\0', '\0', 'e', 'n'), "English"}, + {MAKECODE('\0', '\0', 'e', 'o'), "Esperanto"}, + {MAKECODE('\0', '\0', 'e', 's'), "Spanish"}, + {MAKECODE('\0', '\0', 'e', 't'), "Estonian"}, + {MAKECODE('\0', '\0', 'e', 'u'), "Basque"}, + {MAKECODE('\0', '\0', 'f', 'a'), "Persian"}, + {MAKECODE('\0', '\0', 'f', 'f'), "Fulah"}, + {MAKECODE('\0', '\0', 'f', 'i'), "Finnish"}, + {MAKECODE('\0', '\0', 'f', 'j'), "Fijian"}, + {MAKECODE('\0', '\0', 'f', 'o'), "Faroese"}, + {MAKECODE('\0', '\0', 'f', 'r'), "French"}, + {MAKECODE('\0', '\0', 'f', 'y'), "Western Frisian"}, + {MAKECODE('\0', '\0', 'g', 'a'), "Irish"}, + {MAKECODE('\0', '\0', 'g', 'd'), "Scottish Gaelic"}, + {MAKECODE('\0', '\0', 'g', 'l'), "Galician"}, + {MAKECODE('\0', '\0', 'g', 'n'), "Guarani"}, + {MAKECODE('\0', '\0', 'g', 'u'), "Gujarati"}, + {MAKECODE('\0', '\0', 'g', 'v'), "Manx"}, + {MAKECODE('\0', '\0', 'h', 'a'), "Hausa"}, + {MAKECODE('\0', '\0', 'h', 'e'), "Hebrew"}, + {MAKECODE('\0', '\0', 'h', 'i'), "Hindi"}, + {MAKECODE('\0', '\0', 'h', 'o'), "Hiri Motu"}, + {MAKECODE('\0', '\0', 'h', 'r'), "Croatian"}, + {MAKECODE('\0', '\0', 'h', 't'), "Haitian"}, + {MAKECODE('\0', '\0', 'h', 'u'), "Hungarian"}, + {MAKECODE('\0', '\0', 'h', 'y'), "Armenian"}, + {MAKECODE('\0', '\0', 'h', 'z'), "Herero"}, + {MAKECODE('\0', '\0', 'i', 'a'), "Interlingua"}, + {MAKECODE('\0', '\0', 'i', 'd'), "Indonesian"}, + {MAKECODE('\0', '\0', 'i', 'e'), "Interlingue"}, + {MAKECODE('\0', '\0', 'i', 'g'), "Igbo"}, + {MAKECODE('\0', '\0', 'i', 'i'), "Sichuan Yi"}, + {MAKECODE('\0', '\0', 'i', 'k'), "Inupiat"}, + {MAKECODE('\0', '\0', 'i', 'o'), "Ido"}, + {MAKECODE('\0', '\0', 'i', 's'), "Icelandic"}, + {MAKECODE('\0', '\0', 'i', 't'), "Italian"}, + {MAKECODE('\0', '\0', 'i', 'u'), "Inuktitut"}, + {MAKECODE('\0', '\0', 'j', 'a'), "Japanese"}, + {MAKECODE('\0', '\0', 'j', 'v'), "Javanese"}, + {MAKECODE('\0', '\0', 'k', 'a'), "Georgian"}, + {MAKECODE('\0', '\0', 'k', 'g'), "Kongo"}, + {MAKECODE('\0', '\0', 'k', 'i'), "Kikuyu"}, + {MAKECODE('\0', '\0', 'k', 'j'), "Kuanyama"}, + {MAKECODE('\0', '\0', 'k', 'k'), "Kazakh"}, + {MAKECODE('\0', '\0', 'k', 'l'), "Kalaallisut"}, + {MAKECODE('\0', '\0', 'k', 'm'), "Khmer"}, + {MAKECODE('\0', '\0', 'k', 'n'), "Kannada"}, + {MAKECODE('\0', '\0', 'k', 'o'), "Korean"}, + {MAKECODE('\0', '\0', 'k', 'r'), "Kanuri"}, + {MAKECODE('\0', '\0', 'k', 's'), "Kashmiri"}, + {MAKECODE('\0', '\0', 'k', 'u'), "Kurdish"}, + {MAKECODE('\0', '\0', 'k', 'v'), "Komi"}, + {MAKECODE('\0', '\0', 'k', 'w'), "Cornish"}, + {MAKECODE('\0', '\0', 'k', 'y'), "Kirghiz"}, + {MAKECODE('\0', '\0', 'l', 'a'), "Latin"}, + {MAKECODE('\0', '\0', 'l', 'b'), "Luxembourgish"}, + {MAKECODE('\0', '\0', 'l', 'g'), "Ganda"}, + {MAKECODE('\0', '\0', 'l', 'i'), "Limburgan"}, + {MAKECODE('\0', '\0', 'l', 'n'), "Lingala"}, + {MAKECODE('\0', '\0', 'l', 'o'), "Lao"}, + {MAKECODE('\0', '\0', 'l', 't'), "Lithuanian"}, + {MAKECODE('\0', '\0', 'l', 'u'), "Luba-Katanga"}, + {MAKECODE('\0', '\0', 'l', 'v'), "Latvian, Lettish"}, + {MAKECODE('\0', '\0', 'm', 'g'), "Malagasy"}, + {MAKECODE('\0', '\0', 'm', 'h'), "Marshallese"}, + {MAKECODE('\0', '\0', 'm', 'i'), "Maori"}, + {MAKECODE('\0', '\0', 'm', 'k'), "Macedonian"}, + {MAKECODE('\0', '\0', 'm', 'l'), "Malayalam"}, + {MAKECODE('\0', '\0', 'm', 'n'), "Mongolian"}, + {MAKECODE('\0', '\0', 'm', 'r'), "Marathi"}, + {MAKECODE('\0', '\0', 'm', 's'), "Malay"}, + {MAKECODE('\0', '\0', 'm', 't'), "Maltese"}, + {MAKECODE('\0', '\0', 'm', 'y'), "Burmese"}, + {MAKECODE('\0', '\0', 'n', 'a'), "Nauru"}, + {MAKECODE('\0', '\0', 'n', 'b'), "Norwegian Bokm\xC3\xA5l"}, + {MAKECODE('\0', '\0', 'n', 'd'), "Ndebele, North"}, + {MAKECODE('\0', '\0', 'n', 'e'), "Nepali"}, + {MAKECODE('\0', '\0', 'n', 'g'), "Ndonga"}, + {MAKECODE('\0', '\0', 'n', 'l'), "Dutch"}, + {MAKECODE('\0', '\0', 'n', 'n'), "Norwegian Nynorsk"}, + {MAKECODE('\0', '\0', 'n', 'o'), "Norwegian"}, + {MAKECODE('\0', '\0', 'n', 'r'), "Ndebele, South"}, + {MAKECODE('\0', '\0', 'n', 'v'), "Navajo"}, + {MAKECODE('\0', '\0', 'n', 'y'), "Chichewa"}, + {MAKECODE('\0', '\0', 'o', 'c'), "Occitan"}, + {MAKECODE('\0', '\0', 'o', 'j'), "Ojibwa"}, + {MAKECODE('\0', '\0', 'o', 'm'), "Oromo"}, + {MAKECODE('\0', '\0', 'o', 'r'), "Oriya"}, + {MAKECODE('\0', '\0', 'o', 's'), "Ossetic"}, + {MAKECODE('\0', '\0', 'p', 'a'), "Punjabi"}, + {MAKECODE('\0', '\0', 'p', 'i'), "Pali"}, + {MAKECODE('\0', '\0', 'p', 'l'), "Polish"}, + {MAKECODE('\0', '\0', 'p', 's'), "Pashto, Pushto"}, + {MAKECODE('\0', '\0', 'p', 't'), "Portuguese"}, + // pb = unofficial language code for Brazilian Portuguese + {MAKECODE('\0', '\0', 'p', 'b'), "Portuguese (Brazil)"}, + {MAKECODE('\0', '\0', 'q', 'u'), "Quechua"}, + {MAKECODE('\0', '\0', 'r', 'm'), "Romansh"}, + {MAKECODE('\0', '\0', 'r', 'n'), "Kirundi"}, + {MAKECODE('\0', '\0', 'r', 'o'), "Romanian"}, + {MAKECODE('\0', '\0', 'r', 'u'), "Russian"}, + {MAKECODE('\0', '\0', 'r', 'w'), "Kinyarwanda"}, + {MAKECODE('\0', '\0', 's', 'a'), "Sanskrit"}, + {MAKECODE('\0', '\0', 's', 'c'), "Sardinian"}, + {MAKECODE('\0', '\0', 's', 'd'), "Sindhi"}, + {MAKECODE('\0', '\0', 's', 'e'), "Northern Sami"}, + {MAKECODE('\0', '\0', 's', 'g'), "Sangho"}, + {MAKECODE('\0', '\0', 's', 'h'), "Serbo-Croatian"}, + {MAKECODE('\0', '\0', 's', 'i'), "Sinhalese"}, + {MAKECODE('\0', '\0', 's', 'k'), "Slovak"}, + {MAKECODE('\0', '\0', 's', 'l'), "Slovenian"}, + {MAKECODE('\0', '\0', 's', 'm'), "Samoan"}, + {MAKECODE('\0', '\0', 's', 'n'), "Shona"}, + {MAKECODE('\0', '\0', 's', 'o'), "Somali"}, + {MAKECODE('\0', '\0', 's', 'q'), "Albanian"}, + {MAKECODE('\0', '\0', 's', 'r'), "Serbian"}, + {MAKECODE('\0', '\0', 's', 's'), "Swati"}, + {MAKECODE('\0', '\0', 's', 't'), "Sesotho"}, + {MAKECODE('\0', '\0', 's', 'u'), "Sundanese"}, + {MAKECODE('\0', '\0', 's', 'v'), "Swedish"}, + {MAKECODE('\0', '\0', 's', 'w'), "Swahili"}, + {MAKECODE('\0', '\0', 't', 'a'), "Tamil"}, + {MAKECODE('\0', '\0', 't', 'e'), "Telugu"}, + {MAKECODE('\0', '\0', 't', 'g'), "Tajik"}, + {MAKECODE('\0', '\0', 't', 'h'), "Thai"}, + {MAKECODE('\0', '\0', 't', 'i'), "Tigrinya"}, + {MAKECODE('\0', '\0', 't', 'k'), "Turkmen"}, + {MAKECODE('\0', '\0', 't', 'l'), "Tagalog"}, + {MAKECODE('\0', '\0', 't', 'n'), "Tswana"}, + {MAKECODE('\0', '\0', 't', 'o'), "Tonga"}, + {MAKECODE('\0', '\0', 't', 'r'), "Turkish"}, + {MAKECODE('\0', '\0', 't', 's'), "Tsonga"}, + {MAKECODE('\0', '\0', 't', 't'), "Tatar"}, + {MAKECODE('\0', '\0', 't', 'w'), "Twi"}, + {MAKECODE('\0', '\0', 't', 'y'), "Tahitian"}, + {MAKECODE('\0', '\0', 'u', 'g'), "Uighur"}, + {MAKECODE('\0', '\0', 'u', 'k'), "Ukrainian"}, + {MAKECODE('\0', '\0', 'u', 'r'), "Urdu"}, + {MAKECODE('\0', '\0', 'u', 'z'), "Uzbek"}, + {MAKECODE('\0', '\0', 'v', 'e'), "Venda"}, + {MAKECODE('\0', '\0', 'v', 'i'), "Vietnamese"}, + {MAKECODE('\0', '\0', 'v', 'o'), "Volapuk"}, + {MAKECODE('\0', '\0', 'w', 'a'), "Walloon"}, + {MAKECODE('\0', '\0', 'w', 'o'), "Wolof"}, + {MAKECODE('\0', '\0', 'x', 'h'), "Xhosa"}, + {MAKECODE('\0', '\0', 'y', 'i'), "Yiddish"}, + {MAKECODE('\0', '\0', 'y', 'o'), "Yoruba"}, + {MAKECODE('\0', '\0', 'z', 'a'), "Zhuang"}, + {MAKECODE('\0', '\0', 'z', 'h'), "Chinese"}, + {MAKECODE('\0', '\0', 'z', 'u'), "Zulu"}, +}}; +// clang-format on + +// clang-format off +const std::array<struct LCENTRY, 540> g_iso639_2 = {{ + {MAKECODE('\0', 'a', 'b', 'k'), "Abkhaz"}, + {MAKECODE('\0', 'a', 'b', 'k'), "Abkhazian"}, + {MAKECODE('\0', 'a', 'c', 'e'), "Achinese"}, + {MAKECODE('\0', 'a', 'c', 'h'), "Acoli"}, + {MAKECODE('\0', 'a', 'd', 'a'), "Adangme"}, + {MAKECODE('\0', 'a', 'd', 'y'), "Adygei"}, + {MAKECODE('\0', 'a', 'd', 'y'), "Adyghe"}, + {MAKECODE('\0', 'a', 'a', 'r'), "Afar"}, + {MAKECODE('\0', 'a', 'f', 'h'), "Afrihili"}, + {MAKECODE('\0', 'a', 'f', 'r'), "Afrikaans"}, + {MAKECODE('\0', 'a', 'f', 'a'), "Afro-Asiatic (Other)"}, + {MAKECODE('\0', 'a', 'k', 'a'), "Akan"}, + {MAKECODE('\0', 'a', 'k', 'k'), "Akkadian"}, + {MAKECODE('\0', 'a', 'l', 'b'), "Albanian"}, + {MAKECODE('\0', 's', 'q', 'i'), "Albanian"}, + {MAKECODE('\0', 'a', 'l', 'e'), "Aleut"}, + {MAKECODE('\0', 'a', 'l', 'g'), "Algonquian languages"}, + {MAKECODE('\0', 't', 'u', 't'), "Altaic (Other)"}, + {MAKECODE('\0', 'a', 'm', 'h'), "Amharic"}, + {MAKECODE('\0', 'a', 'p', 'a'), "Apache languages"}, + {MAKECODE('\0', 'a', 'r', 'a'), "Arabic"}, + {MAKECODE('\0', 'a', 'r', 'g'), "Aragonese"}, + {MAKECODE('\0', 'a', 'r', 'c'), "Aramaic"}, + {MAKECODE('\0', 'a', 'r', 'p'), "Arapaho"}, + {MAKECODE('\0', 'a', 'r', 'n'), "Araucanian"}, + {MAKECODE('\0', 'a', 'r', 'w'), "Arawak"}, + {MAKECODE('\0', 'a', 'r', 'm'), "Armenian"}, + {MAKECODE('\0', 'h', 'y', 'e'), "Armenian"}, + {MAKECODE('\0', 'a', 'r', 't'), "Artificial (Other)"}, + {MAKECODE('\0', 'a', 's', 'm'), "Assamese"}, + {MAKECODE('\0', 'a', 's', 't'), "Asturian"}, + {MAKECODE('\0', 'a', 't', 'h'), "Athapascan languages"}, + {MAKECODE('\0', 'a', 'u', 's'), "Australian languages"}, + {MAKECODE('\0', 'm', 'a', 'p'), "Austronesian (Other)"}, + {MAKECODE('\0', 'a', 'v', 'a'), "Avaric"}, + {MAKECODE('\0', 'a', 'v', 'e'), "Avestan"}, + {MAKECODE('\0', 'a', 'w', 'a'), "Awadhi"}, + {MAKECODE('\0', 'a', 'y', 'm'), "Aymara"}, + {MAKECODE('\0', 'a', 'z', 'e'), "Azerbaijani"}, + {MAKECODE('\0', 'a', 's', 't'), "Bable"}, + {MAKECODE('\0', 'b', 'a', 'n'), "Balinese"}, + {MAKECODE('\0', 'b', 'a', 't'), "Baltic (Other)"}, + {MAKECODE('\0', 'b', 'a', 'l'), "Baluchi"}, + {MAKECODE('\0', 'b', 'a', 'm'), "Bambara"}, + {MAKECODE('\0', 'b', 'a', 'i'), "Bamileke languages"}, + {MAKECODE('\0', 'b', 'a', 'd'), "Banda"}, + {MAKECODE('\0', 'b', 'n', 't'), "Bantu (Other)"}, + {MAKECODE('\0', 'b', 'a', 's'), "Basa"}, + {MAKECODE('\0', 'b', 'a', 'k'), "Bashkir"}, + {MAKECODE('\0', 'b', 'a', 'q'), "Basque"}, + {MAKECODE('\0', 'e', 'u', 's'), "Basque"}, + {MAKECODE('\0', 'b', 't', 'k'), "Batak (Indonesia)"}, + {MAKECODE('\0', 'b', 'e', 'j'), "Beja"}, + {MAKECODE('\0', 'b', 'e', 'l'), "Belarusian"}, + {MAKECODE('\0', 'b', 'e', 'm'), "Bemba"}, + {MAKECODE('\0', 'b', 'e', 'n'), "Bengali"}, + {MAKECODE('\0', 'b', 'e', 'r'), "Berber (Other)"}, + {MAKECODE('\0', 'b', 'h', 'o'), "Bhojpuri"}, + {MAKECODE('\0', 'b', 'i', 'h'), "Bihari"}, + {MAKECODE('\0', 'b', 'i', 'k'), "Bikol"}, + {MAKECODE('\0', 'b', 'y', 'n'), "Bilin"}, + {MAKECODE('\0', 'b', 'i', 'n'), "Bini"}, + {MAKECODE('\0', 'b', 'i', 's'), "Bislama"}, + {MAKECODE('\0', 'b', 'y', 'n'), "Blin"}, + {MAKECODE('\0', 'n', 'o', 'b'), "Bokm\xC3\xA5l, Norwegian"}, + {MAKECODE('\0', 'b', 'o', 's'), "Bosnian"}, + {MAKECODE('\0', 'b', 'r', 'a'), "Braj"}, + {MAKECODE('\0', 'b', 'r', 'e'), "Breton"}, + {MAKECODE('\0', 'b', 'u', 'g'), "Buginese"}, + {MAKECODE('\0', 'b', 'u', 'l'), "Bulgarian"}, + {MAKECODE('\0', 'b', 'u', 'a'), "Buriat"}, + {MAKECODE('\0', 'b', 'u', 'r'), "Burmese"}, + {MAKECODE('\0', 'm', 'y', 'a'), "Burmese"}, + {MAKECODE('\0', 'c', 'a', 'd'), "Caddo"}, + {MAKECODE('\0', 'c', 'a', 'r'), "Carib"}, + {MAKECODE('\0', 's', 'p', 'a'), "Spanish"}, + {MAKECODE('\0', 'c', 'a', 't'), "Catalan"}, + {MAKECODE('\0', 'c', 'a', 'u'), "Caucasian (Other)"}, + {MAKECODE('\0', 'c', 'e', 'b'), "Cebuano"}, + {MAKECODE('\0', 'c', 'e', 'l'), "Celtic (Other)"}, + {MAKECODE('\0', 'c', 'h', 'g'), "Chagatai"}, + {MAKECODE('\0', 'c', 'm', 'c'), "Chamic languages"}, + {MAKECODE('\0', 'c', 'h', 'a'), "Chamorro"}, + {MAKECODE('\0', 'c', 'h', 'e'), "Chechen"}, + {MAKECODE('\0', 'c', 'h', 'r'), "Cherokee"}, + {MAKECODE('\0', 'n', 'y', 'a'), "Chewa"}, + {MAKECODE('\0', 'c', 'h', 'y'), "Cheyenne"}, + {MAKECODE('\0', 'c', 'h', 'b'), "Chibcha"}, + {MAKECODE('\0', 'n', 'y', 'a'), "Chichewa"}, + {MAKECODE('\0', 'c', 'h', 'i'), "Chinese"}, + {MAKECODE('\0', 'z', 'h', 'o'), "Chinese"}, + {MAKECODE('\0', 'c', 'h', 'n'), "Chinook jargon"}, + {MAKECODE('\0', 'c', 'h', 'p'), "Chipewyan"}, + {MAKECODE('\0', 'c', 'h', 'o'), "Choctaw"}, + {MAKECODE('\0', 'z', 'h', 'a'), "Chuang"}, + {MAKECODE('\0', 'c', 'h', 'u'), "Church Slavonic"}, + {MAKECODE('\0', 'c', 'h', 'k'), "Chuukese"}, + {MAKECODE('\0', 'c', 'h', 'v'), "Chuvash"}, + {MAKECODE('\0', 'n', 'w', 'c'), "Classical Nepal Bhasa"}, + {MAKECODE('\0', 'n', 'w', 'c'), "Classical Newari"}, + {MAKECODE('\0', 'c', 'o', 'p'), "Coptic"}, + {MAKECODE('\0', 'c', 'o', 'r'), "Cornish"}, + {MAKECODE('\0', 'c', 'o', 's'), "Corsican"}, + {MAKECODE('\0', 'c', 'r', 'e'), "Cree"}, + {MAKECODE('\0', 'm', 'u', 's'), "Creek"}, + {MAKECODE('\0', 'c', 'r', 'p'), "Creoles and pidgins (Other)"}, + {MAKECODE('\0', 'c', 'p', 'e'), "English-based (Other)"}, + {MAKECODE('\0', 'c', 'p', 'f'), "French-based (Other)"}, + {MAKECODE('\0', 'c', 'p', 'p'), "Portuguese-based (Other)"}, + {MAKECODE('\0', 'c', 'r', 'h'), "Crimean Tatar"}, + {MAKECODE('\0', 'c', 'r', 'h'), "Crimean Turkish"}, + {MAKECODE('\0', 'h', 'r', 'v'), "Croatian"}, + {MAKECODE('\0', 's', 'c', 'r'), "Croatian"}, + {MAKECODE('\0', 'c', 'u', 's'), "Cushitic (Other)"}, + {MAKECODE('\0', 'c', 'z', 'e'), "Czech"}, + {MAKECODE('\0', 'c', 'e', 's'), "Czech"}, + {MAKECODE('\0', 'd', 'a', 'k'), "Dakota"}, + {MAKECODE('\0', 'd', 'a', 'n'), "Danish"}, + {MAKECODE('\0', 'd', 'a', 'r'), "Dargwa"}, + {MAKECODE('\0', 'd', 'a', 'y'), "Dayak"}, + {MAKECODE('\0', 'd', 'e', 'l'), "Delaware"}, + {MAKECODE('\0', 'd', 'i', 'n'), "Dinka"}, + {MAKECODE('\0', 'd', 'i', 'v'), "Divehi"}, + {MAKECODE('\0', 'd', 'o', 'i'), "Dogri"}, + {MAKECODE('\0', 'd', 'g', 'r'), "Dogrib"}, + {MAKECODE('\0', 'd', 'r', 'a'), "Dravidian (Other)"}, + {MAKECODE('\0', 'd', 'u', 'a'), "Duala"}, + {MAKECODE('\0', 'd', 'u', 't'), "Dutch"}, + {MAKECODE('\0', 'n', 'l', 'd'), "Dutch"}, + {MAKECODE('\0', 'd', 'u', 'm'), "Dutch, Middle (ca. 1050-1350)"}, + {MAKECODE('\0', 'd', 'y', 'u'), "Dyula"}, + {MAKECODE('\0', 'd', 'z', 'o'), "Dzongkha"}, + {MAKECODE('\0', 'e', 'f', 'i'), "Efik"}, + {MAKECODE('\0', 'e', 'g', 'y'), "Egyptian (Ancient)"}, + {MAKECODE('\0', 'e', 'k', 'a'), "Ekajuk"}, + {MAKECODE('\0', 'e', 'l', 'x'), "Elamite"}, + {MAKECODE('\0', 'e', 'n', 'g'), "English"}, + {MAKECODE('\0', 'e', 'n', 'm'), "English, Middle (1100-1500)"}, + {MAKECODE('\0', 'a', 'n', 'g'), "English, Old (ca.450-1100)"}, + {MAKECODE('\0', 'm', 'y', 'v'), "Erzya"}, + {MAKECODE('\0', 'e', 'p', 'o'), "Esperanto"}, + {MAKECODE('\0', 'e', 's', 't'), "Estonian"}, + {MAKECODE('\0', 'e', 'w', 'e'), "Ewe"}, + {MAKECODE('\0', 'e', 'w', 'o'), "Ewondo"}, + {MAKECODE('\0', 'f', 'a', 'n'), "Fang"}, + {MAKECODE('\0', 'f', 'a', 't'), "Fanti"}, + {MAKECODE('\0', 'f', 'a', 'o'), "Faroese"}, + {MAKECODE('\0', 'f', 'i', 'j'), "Fijian"}, + {MAKECODE('\0', 'f', 'i', 'l'), "Filipino"}, + {MAKECODE('\0', 'f', 'i', 'n'), "Finnish"}, + {MAKECODE('\0', 'f', 'i', 'u'), "Finno-Ugrian (Other)"}, + {MAKECODE('\0', 'd', 'u', 't'), "Flemish"}, + {MAKECODE('\0', 'n', 'l', 'd'), "Flemish"}, + {MAKECODE('\0', 'f', 'o', 'n'), "Fon"}, + {MAKECODE('\0', 'f', 'r', 'e'), "French"}, + {MAKECODE('\0', 'f', 'r', 'a'), "French"}, + {MAKECODE('\0', 'f', 'r', 'm'), "French, Middle (ca.1400-1600)"}, + {MAKECODE('\0', 'f', 'r', 'o'), "French, Old (842-ca.1400)"}, + {MAKECODE('\0', 'f', 'r', 'y'), "Frisian"}, + {MAKECODE('\0', 'f', 'u', 'r'), "Friulian"}, + {MAKECODE('\0', 'f', 'u', 'l'), "Fulah"}, + {MAKECODE('\0', 'g', 'a', 'a'), "Ga"}, + {MAKECODE('\0', 'g', 'l', 'a'), "Gaelic"}, + {MAKECODE('\0', 'g', 'l', 'g'), "Gallegan"}, + {MAKECODE('\0', 'l', 'u', 'g'), "Ganda"}, + {MAKECODE('\0', 'g', 'a', 'y'), "Gayo"}, + {MAKECODE('\0', 'g', 'b', 'a'), "Gbaya"}, + {MAKECODE('\0', 'g', 'e', 'z'), "Geez"}, + {MAKECODE('\0', 'g', 'e', 'o'), "Georgian"}, + {MAKECODE('\0', 'k', 'a', 't'), "Georgian"}, + {MAKECODE('\0', 'g', 'e', 'r'), "German"}, + {MAKECODE('\0', 'd', 'e', 'u'), "German"}, + {MAKECODE('\0', 'n', 'd', 's'), "German, Low"}, + {MAKECODE('\0', 'g', 'm', 'h'), "German, Middle High (ca.1050-1500)"}, + {MAKECODE('\0', 'g', 'o', 'h'), "German, Old High (ca.750-1050)"}, + {MAKECODE('\0', 'g', 's', 'w'), "German, Swiss German"}, + {MAKECODE('\0', 'g', 'e', 'm'), "Germanic (Other)"}, + {MAKECODE('\0', 'k', 'i', 'k'), "Gikuyu"}, + {MAKECODE('\0', 'g', 'i', 'l'), "Gilbertese"}, + {MAKECODE('\0', 'g', 'o', 'n'), "Gondi"}, + {MAKECODE('\0', 'g', 'o', 'r'), "Gorontalo"}, + {MAKECODE('\0', 'g', 'o', 't'), "Gothic"}, + {MAKECODE('\0', 'g', 'r', 'b'), "Grebo"}, + {MAKECODE('\0', 'g', 'r', 'c'), "Greek, Ancient (to 1453)"}, + {MAKECODE('\0', 'g', 'r', 'e'), "Greek, Modern (1453-)"}, + {MAKECODE('\0', 'e', 'l', 'l'), "Greek, Modern (1453-)"}, + {MAKECODE('\0', 'k', 'a', 'l'), "Greenlandic"}, + {MAKECODE('\0', 'g', 'r', 'n'), "Guarani"}, + {MAKECODE('\0', 'g', 'u', 'j'), "Gujarati"}, + {MAKECODE('\0', 'g', 'w', 'i'), "Gwich\xC2\xB4in"}, + {MAKECODE('\0', 'h', 'a', 'i'), "Haida"}, + {MAKECODE('\0', 'h', 'a', 't'), "Haitian"}, + {MAKECODE('\0', 'h', 'a', 't'), "Haitian Creole"}, + {MAKECODE('\0', 'h', 'a', 'u'), "Hausa"}, + {MAKECODE('\0', 'h', 'a', 'w'), "Hawaiian"}, + {MAKECODE('\0', 'h', 'e', 'b'), "Hebrew"}, + {MAKECODE('\0', 'h', 'e', 'r'), "Herero"}, + {MAKECODE('\0', 'h', 'i', 'l'), "Hiligaynon"}, + {MAKECODE('\0', 'h', 'i', 'm'), "Himachali"}, + {MAKECODE('\0', 'h', 'i', 'n'), "Hindi"}, + {MAKECODE('\0', 'h', 'm', 'o'), "Hiri Motu"}, + {MAKECODE('\0', 'h', 'i', 't'), "Hittite"}, + {MAKECODE('\0', 'h', 'm', 'n'), "Hmong"}, + {MAKECODE('\0', 'h', 'u', 'n'), "Hungarian"}, + {MAKECODE('\0', 'h', 'u', 'p'), "Hupa"}, + {MAKECODE('\0', 'i', 'b', 'a'), "Iban"}, + {MAKECODE('\0', 'i', 'c', 'e'), "Icelandic"}, + {MAKECODE('\0', 'i', 's', 'l'), "Icelandic"}, + {MAKECODE('\0', 'i', 'd', 'o'), "Ido"}, + {MAKECODE('\0', 'i', 'b', 'o'), "Igbo"}, + {MAKECODE('\0', 'i', 'j', 'o'), "Ijo"}, + {MAKECODE('\0', 'i', 'l', 'o'), "Iloko"}, + {MAKECODE('\0', 's', 'm', 'n'), "Inari Sami"}, + {MAKECODE('\0', 'i', 'n', 'c'), "Indic (Other)"}, + {MAKECODE('\0', 'i', 'n', 'e'), "Indo-European (Other)"}, + {MAKECODE('\0', 'i', 'n', 'd'), "Indonesian"}, + {MAKECODE('\0', 'i', 'n', 'h'), "Ingush"}, + {MAKECODE('\0', 'i', 'n', 'a'), "Auxiliary Language Association)"}, + {MAKECODE('\0', 'i', 'l', 'e'), "Interlingue"}, + {MAKECODE('\0', 'i', 'k', 'u'), "Inuktitut"}, + {MAKECODE('\0', 'i', 'p', 'k'), "Inupiaq"}, + {MAKECODE('\0', 'i', 'r', 'a'), "Iranian (Other)"}, + {MAKECODE('\0', 'g', 'l', 'e'), "Irish"}, + {MAKECODE('\0', 'm', 'g', 'a'), "Irish, Middle (900-1200)"}, + {MAKECODE('\0', 's', 'g', 'a'), "Irish, Old (to 900)"}, + {MAKECODE('\0', 'i', 'r', 'o'), "Iroquoian languages"}, + {MAKECODE('\0', 'i', 't', 'a'), "Italian"}, + {MAKECODE('\0', 'j', 'p', 'n'), "Japanese"}, + {MAKECODE('\0', 'j', 'a', 'v'), "Javanese"}, + {MAKECODE('\0', 'j', 'r', 'b'), "Judeo-Arabic"}, + {MAKECODE('\0', 'j', 'p', 'r'), "Judeo-Persian"}, + {MAKECODE('\0', 'k', 'b', 'd'), "Kabardian"}, + {MAKECODE('\0', 'k', 'a', 'b'), "Kabyle"}, + {MAKECODE('\0', 'k', 'a', 'c'), "Kachin"}, + {MAKECODE('\0', 'k', 'a', 'l'), "Kalaallisut"}, + {MAKECODE('\0', 'x', 'a', 'l'), "Kalmyk"}, + {MAKECODE('\0', 'k', 'a', 'm'), "Kamba"}, + {MAKECODE('\0', 'k', 'a', 'n'), "Kannada"}, + {MAKECODE('\0', 'k', 'a', 'u'), "Kanuri"}, + {MAKECODE('\0', 'k', 'r', 'c'), "Karachay-Balkar"}, + {MAKECODE('\0', 'k', 'a', 'a'), "Kara-Kalpak"}, + {MAKECODE('\0', 'k', 'a', 'r'), "Karen"}, + {MAKECODE('\0', 'k', 'a', 's'), "Kashmiri"}, + {MAKECODE('\0', 'c', 's', 'b'), "Kashubian"}, + {MAKECODE('\0', 'k', 'a', 'w'), "Kawi"}, + {MAKECODE('\0', 'k', 'a', 'z'), "Kazakh"}, + {MAKECODE('\0', 'k', 'h', 'a'), "Khasi"}, + {MAKECODE('\0', 'k', 'h', 'm'), "Khmer"}, + {MAKECODE('\0', 'k', 'h', 'i'), "Khoisan (Other)"}, + {MAKECODE('\0', 'k', 'h', 'o'), "Khotanese"}, + {MAKECODE('\0', 'k', 'i', 'k'), "Kikuyu"}, + {MAKECODE('\0', 'k', 'm', 'b'), "Kimbundu"}, + {MAKECODE('\0', 'k', 'i', 'n'), "Kinyarwanda"}, + {MAKECODE('\0', 'k', 'i', 'r'), "Kirghiz"}, + {MAKECODE('\0', 't', 'l', 'h'), "Klingon"}, + {MAKECODE('\0', 'k', 'o', 'm'), "Komi"}, + {MAKECODE('\0', 'k', 'o', 'n'), "Kongo"}, + {MAKECODE('\0', 'k', 'o', 'k'), "Konkani"}, + {MAKECODE('\0', 'k', 'o', 'r'), "Korean"}, + {MAKECODE('\0', 'k', 'o', 's'), "Kosraean"}, + {MAKECODE('\0', 'k', 'p', 'e'), "Kpelle"}, + {MAKECODE('\0', 'k', 'r', 'o'), "Kru"}, + {MAKECODE('\0', 'k', 'u', 'a'), "Kuanyama"}, + {MAKECODE('\0', 'k', 'u', 'm'), "Kumyk"}, + {MAKECODE('\0', 'k', 'u', 'r'), "Kurdish"}, + {MAKECODE('\0', 'k', 'r', 'u'), "Kurukh"}, + {MAKECODE('\0', 'k', 'u', 't'), "Kutenai"}, + {MAKECODE('\0', 'k', 'u', 'a'), "Kwanyama, Kuanyama"}, + {MAKECODE('\0', 'l', 'a', 'd'), "Ladino"}, + {MAKECODE('\0', 'l', 'a', 'h'), "Lahnda"}, + {MAKECODE('\0', 'l', 'a', 'm'), "Lamba"}, + {MAKECODE('\0', 'l', 'a', 'o'), "Lao"}, + {MAKECODE('\0', 'l', 'a', 't'), "Latin"}, + {MAKECODE('\0', 'l', 'a', 'v'), "Latvian"}, + {MAKECODE('\0', 'l', 't', 'z'), "Letzeburgesch"}, + {MAKECODE('\0', 'l', 'e', 'z'), "Lezghian"}, + {MAKECODE('\0', 'l', 'i', 'm'), "Limburgan"}, + {MAKECODE('\0', 'l', 'i', 'm'), "Limburger"}, + {MAKECODE('\0', 'l', 'i', 'm'), "Limburgish"}, + {MAKECODE('\0', 'l', 'i', 'n'), "Lingala"}, + {MAKECODE('\0', 'l', 'i', 't'), "Lithuanian"}, + {MAKECODE('\0', 'j', 'b', 'o'), "Lojban"}, + {MAKECODE('\0', 'n', 'd', 's'), "Low German"}, + {MAKECODE('\0', 'n', 'd', 's'), "Low Saxon"}, + {MAKECODE('\0', 'd', 's', 'b'), "Lower Sorbian"}, + {MAKECODE('\0', 'l', 'o', 'z'), "Lozi"}, + {MAKECODE('\0', 'l', 'u', 'b'), "Luba-Katanga"}, + {MAKECODE('\0', 'l', 'u', 'a'), "Luba-Lulua"}, + {MAKECODE('\0', 'l', 'u', 'i'), "Luiseno"}, + {MAKECODE('\0', 's', 'm', 'j'), "Lule Sami"}, + {MAKECODE('\0', 'l', 'u', 'n'), "Lunda"}, + {MAKECODE('\0', 'l', 'u', 'o'), "Luo (Kenya and Tanzania)"}, + {MAKECODE('\0', 'l', 'u', 's'), "Lushai"}, + {MAKECODE('\0', 'l', 't', 'z'), "Luxembourgish"}, + {MAKECODE('\0', 'm', 'a', 'c'), "Macedonian"}, + {MAKECODE('\0', 'm', 'k', 'd'), "Macedonian"}, + {MAKECODE('\0', 'm', 'a', 'd'), "Madurese"}, + {MAKECODE('\0', 'm', 'a', 'g'), "Magahi"}, + {MAKECODE('\0', 'm', 'a', 'i'), "Maithili"}, + {MAKECODE('\0', 'm', 'a', 'k'), "Makasar"}, + {MAKECODE('\0', 'm', 'l', 'g'), "Malagasy"}, + {MAKECODE('\0', 'm', 'a', 'y'), "Malay"}, + {MAKECODE('\0', 'm', 's', 'a'), "Malay"}, + {MAKECODE('\0', 'm', 'a', 'l'), "Malayalam"}, + {MAKECODE('\0', 'm', 'l', 't'), "Maltese"}, + {MAKECODE('\0', 'm', 'n', 'c'), "Manchu"}, + {MAKECODE('\0', 'm', 'd', 'r'), "Mandar"}, + {MAKECODE('\0', 'm', 'a', 'n'), "Mandingo"}, + {MAKECODE('\0', 'm', 'n', 'i'), "Manipuri"}, + {MAKECODE('\0', 'm', 'n', 'o'), "Manobo languages"}, + {MAKECODE('\0', 'g', 'l', 'v'), "Manx"}, + {MAKECODE('\0', 'm', 'a', 'o'), "Maori"}, + {MAKECODE('\0', 'm', 'r', 'i'), "Maori"}, + {MAKECODE('\0', 'm', 'a', 'r'), "Marathi"}, + {MAKECODE('\0', 'c', 'h', 'm'), "Mari"}, + {MAKECODE('\0', 'm', 'a', 'h'), "Marshallese"}, + {MAKECODE('\0', 'm', 'w', 'r'), "Marwari"}, + {MAKECODE('\0', 'm', 'a', 's'), "Masai"}, + {MAKECODE('\0', 'm', 'y', 'n'), "Mayan languages"}, + {MAKECODE('\0', 'm', 'e', 'n'), "Mende"}, + {MAKECODE('\0', 'm', 'i', 'c'), "Micmac"}, + {MAKECODE('\0', 'm', 'i', 'c'), "Mi'kmaq"}, + {MAKECODE('\0', 'm', 'i', 'n'), "Minangkabau"}, + {MAKECODE('\0', 'm', 'w', 'l'), "Mirandese"}, + {MAKECODE('\0', 'm', 'i', 's'), "Miscellaneous languages"}, + {MAKECODE('\0', 'm', 'o', 'h'), "Mohawk"}, + {MAKECODE('\0', 'm', 'd', 'f'), "Moksha"}, + {MAKECODE('\0', 'm', 'o', 'l'), "Moldavian"}, + {MAKECODE('\0', 'm', 'k', 'h'), "Mon-Khmer (Other)"}, + {MAKECODE('\0', 'l', 'o', 'l'), "Mongo"}, + {MAKECODE('\0', 'm', 'o', 'n'), "Mongolian"}, + {MAKECODE('\0', 'm', 'o', 's'), "Mossi"}, + {MAKECODE('\0', 'm', 'u', 'l'), "Multiple languages"}, + {MAKECODE('\0', 'm', 'u', 'n'), "Munda languages"}, + {MAKECODE('\0', 'n', 'a', 'h'), "Nahuatl"}, + {MAKECODE('\0', 'n', 'a', 'u'), "Nauru"}, + {MAKECODE('\0', 'n', 'a', 'v'), "Navaho, Navajo"}, + {MAKECODE('\0', 'n', 'a', 'v'), "Navajo"}, + {MAKECODE('\0', 'n', 'd', 'e'), "Ndebele, North"}, + {MAKECODE('\0', 'n', 'b', 'l'), "Ndebele, South"}, + {MAKECODE('\0', 'n', 'd', 'o'), "Ndonga"}, + {MAKECODE('\0', 'n', 'a', 'p'), "Neapolitan"}, + {MAKECODE('\0', 'n', 'e', 'w'), "Nepal Bhasa"}, + {MAKECODE('\0', 'n', 'e', 'p'), "Nepali"}, + {MAKECODE('\0', 'n', 'e', 'w'), "Newari"}, + {MAKECODE('\0', 'n', 'i', 'a'), "Nias"}, + {MAKECODE('\0', 'n', 'i', 'c'), "Niger-Kordofanian (Other)"}, + {MAKECODE('\0', 's', 's', 'a'), "Nilo-Saharan (Other)"}, + {MAKECODE('\0', 'n', 'i', 'u'), "Niuean"}, + {MAKECODE('\0', 'z', 'x', 'x'), "No linguistic content"}, + {MAKECODE('\0', 'n', 'o', 'g'), "Nogai"}, + {MAKECODE('\0', 'n', 'o', 'n'), "Norse, Old"}, + {MAKECODE('\0', 'n', 'a', 'i'), "North American Indian (Other)"}, + {MAKECODE('\0', 's', 'm', 'e'), "Northern Sami"}, + {MAKECODE('\0', 'n', 's', 'o'), "Northern Sotho"}, + {MAKECODE('\0', 'n', 'd', 'e'), "North Ndebele"}, + {MAKECODE('\0', 'n', 'o', 'r'), "Norwegian"}, + {MAKECODE('\0', 'n', 'o', 'b'), "Norwegian Bokm\xC3\xA5l"}, + {MAKECODE('\0', 'n', 'n', 'o'), "Norwegian Nynorsk"}, + {MAKECODE('\0', 'n', 'u', 'b'), "Nubian languages"}, + {MAKECODE('\0', 'n', 'y', 'm'), "Nyamwezi"}, + {MAKECODE('\0', 'n', 'y', 'a'), "Nyanja"}, + {MAKECODE('\0', 'n', 'y', 'n'), "Nyankole"}, + {MAKECODE('\0', 'n', 'n', 'o'), "Nynorsk, Norwegian"}, + {MAKECODE('\0', 'n', 'y', 'o'), "Nyoro"}, + {MAKECODE('\0', 'n', 'z', 'i'), "Nzima"}, + {MAKECODE('\0', 'o', 'c', 'i'), "Occitan (post 1500)"}, + {MAKECODE('\0', 'o', 'j', 'i'), "Ojibwa"}, + {MAKECODE('\0', 'c', 'h', 'u'), "Old Bulgarian"}, + {MAKECODE('\0', 'c', 'h', 'u'), "Old Church Slavonic"}, + {MAKECODE('\0', 'n', 'w', 'c'), "Old Newari"}, + {MAKECODE('\0', 'c', 'h', 'u'), "Old Slavonic"}, + {MAKECODE('\0', 'o', 'r', 'i'), "Oriya"}, + {MAKECODE('\0', 'o', 'r', 'm'), "Oromo"}, + {MAKECODE('\0', 'o', 's', 'a'), "Osage"}, + {MAKECODE('\0', 'o', 's', 's'), "Ossetian"}, + {MAKECODE('\0', 'o', 's', 's'), "Ossetic"}, + {MAKECODE('\0', 'o', 't', 'o'), "Otomian languages"}, + {MAKECODE('\0', 'p', 'a', 'l'), "Pahlavi"}, + {MAKECODE('\0', 'p', 'a', 'u'), "Palauan"}, + {MAKECODE('\0', 'p', 'l', 'i'), "Pali"}, + {MAKECODE('\0', 'p', 'a', 'm'), "Pampanga"}, + {MAKECODE('\0', 'p', 'a', 'g'), "Pangasinan"}, + {MAKECODE('\0', 'p', 'a', 'n'), "Panjabi"}, + {MAKECODE('\0', 'p', 'a', 'p'), "Papiamento"}, + {MAKECODE('\0', 'p', 'a', 'a'), "Papuan (Other)"}, + {MAKECODE('\0', 'n', 's', 'o'), "Pedi"}, + {MAKECODE('\0', 'p', 'e', 'r'), "Persian"}, + {MAKECODE('\0', 'f', 'a', 's'), "Persian"}, + {MAKECODE('\0', 'p', 'e', 'o'), "Persian, Old (ca.600-400 B.C.)"}, + {MAKECODE('\0', 'p', 'h', 'i'), "Philippine (Other)"}, + {MAKECODE('\0', 'p', 'h', 'n'), "Phoenician"}, + {MAKECODE('\0', 'f', 'i', 'l'), "Pilipino"}, + {MAKECODE('\0', 'p', 'o', 'n'), "Pohnpeian"}, + {MAKECODE('\0', 'p', 'o', 'l'), "Polish"}, + {MAKECODE('\0', 'p', 'o', 'r'), "Portuguese"}, + // pob = unofficial language code for Brazilian Portuguese + {MAKECODE('\0', 'p', 'o', 'b'), "Portuguese (Brazil)"}, + {MAKECODE('\0', 'p', 'r', 'a'), "Prakrit languages"}, + {MAKECODE('\0', 'o', 'c', 'i'), "Proven\xC3\xA7" + "al"}, + {MAKECODE('\0', 'p', 'r', 'o'), "Proven\xC3\xA7" + "al, Old (to 1500)"}, + {MAKECODE('\0', 'p', 'a', 'n'), "Punjabi"}, + {MAKECODE('\0', 'p', 'u', 's'), "Pushto"}, + {MAKECODE('\0', 'q', 'u', 'e'), "Quechua"}, + {MAKECODE('\0', 'r', 'o', 'h'), "Raeto-Romance"}, + {MAKECODE('\0', 'r', 'a', 'j'), "Rajasthani"}, + {MAKECODE('\0', 'r', 'a', 'p'), "Rapanui"}, + {MAKECODE('\0', 'r', 'a', 'r'), "Rarotongan"}, + // { "qaa-qtz", "Reserved for local use" }, + {MAKECODE('\0', 'r', 'o', 'a'), "Romance (Other)"}, + {MAKECODE('\0', 'r', 'u', 'm'), "Romanian"}, + {MAKECODE('\0', 'r', 'o', 'n'), "Romanian"}, + {MAKECODE('\0', 'r', 'o', 'm'), "Romany"}, + {MAKECODE('\0', 'r', 'u', 'n'), "Rundi"}, + {MAKECODE('\0', 'r', 'u', 's'), "Russian"}, + {MAKECODE('\0', 's', 'a', 'l'), "Salishan languages"}, + {MAKECODE('\0', 's', 'a', 'm'), "Samaritan Aramaic"}, + {MAKECODE('\0', 's', 'm', 'i'), "Sami languages (Other)"}, + {MAKECODE('\0', 's', 'm', 'o'), "Samoan"}, + {MAKECODE('\0', 's', 'a', 'd'), "Sandawe"}, + {MAKECODE('\0', 's', 'a', 'g'), "Sango"}, + {MAKECODE('\0', 's', 'a', 'n'), "Sanskrit"}, + {MAKECODE('\0', 's', 'a', 't'), "Santali"}, + {MAKECODE('\0', 's', 'r', 'd'), "Sardinian"}, + {MAKECODE('\0', 's', 'a', 's'), "Sasak"}, + {MAKECODE('\0', 'n', 'd', 's'), "Saxon, Low"}, + {MAKECODE('\0', 's', 'c', 'o'), "Scots"}, + {MAKECODE('\0', 'g', 'l', 'a'), "Scottish Gaelic"}, + {MAKECODE('\0', 's', 'e', 'l'), "Selkup"}, + {MAKECODE('\0', 's', 'e', 'm'), "Semitic (Other)"}, + {MAKECODE('\0', 'n', 's', 'o'), "Sepedi"}, + {MAKECODE('\0', 's', 'c', 'c'), "Serbian"}, + {MAKECODE('\0', 's', 'r', 'p'), "Serbian"}, + {MAKECODE('\0', 's', 'r', 'r'), "Serer"}, + {MAKECODE('\0', 's', 'h', 'n'), "Shan"}, + {MAKECODE('\0', 's', 'n', 'a'), "Shona"}, + {MAKECODE('\0', 'i', 'i', 'i'), "Sichuan Yi"}, + {MAKECODE('\0', 's', 'c', 'n'), "Sicilian"}, + {MAKECODE('\0', 's', 'i', 'd'), "Sidamo"}, + {MAKECODE('\0', 's', 'g', 'n'), "Sign languages"}, + {MAKECODE('\0', 'b', 'l', 'a'), "Siksika"}, + {MAKECODE('\0', 's', 'n', 'd'), "Sindhi"}, + {MAKECODE('\0', 's', 'i', 'n'), "Sinhala"}, + {MAKECODE('\0', 's', 'i', 'n'), "Sinhalese"}, + {MAKECODE('\0', 's', 'i', 't'), "Sino-Tibetan (Other)"}, + {MAKECODE('\0', 's', 'i', 'o'), "Siouan languages"}, + {MAKECODE('\0', 's', 'm', 's'), "Skolt Sami"}, + {MAKECODE('\0', 'd', 'e', 'n'), "Slave (Athapascan)"}, + {MAKECODE('\0', 's', 'l', 'a'), "Slavic (Other)"}, + {MAKECODE('\0', 's', 'l', 'o'), "Slovak"}, + {MAKECODE('\0', 's', 'l', 'k'), "Slovak"}, + {MAKECODE('\0', 's', 'l', 'v'), "Slovenian"}, + {MAKECODE('\0', 's', 'o', 'g'), "Sogdian"}, + {MAKECODE('\0', 's', 'o', 'm'), "Somali"}, + {MAKECODE('\0', 's', 'o', 'n'), "Songhai"}, + {MAKECODE('\0', 's', 'n', 'k'), "Soninke"}, + {MAKECODE('\0', 'w', 'e', 'n'), "Sorbian languages"}, + {MAKECODE('\0', 'n', 's', 'o'), "Sotho, Northern"}, + {MAKECODE('\0', 's', 'o', 't'), "Sotho, Southern"}, + {MAKECODE('\0', 's', 'a', 'i'), "South American Indian (Other)"}, + {MAKECODE('\0', 's', 'm', 'a'), "Southern Sami"}, + {MAKECODE('\0', 'n', 'b', 'l'), "South Ndebele"}, + {MAKECODE('\0', 's', 'p', 'a'), "Castilian"}, + {MAKECODE('\0', 's', 'u', 'k'), "Sukuma"}, + {MAKECODE('\0', 's', 'u', 'x'), "Sumerian"}, + {MAKECODE('\0', 's', 'u', 'n'), "Sundanese"}, + {MAKECODE('\0', 's', 'u', 's'), "Susu"}, + {MAKECODE('\0', 's', 'w', 'a'), "Swahili"}, + {MAKECODE('\0', 's', 's', 'w'), "Swati"}, + {MAKECODE('\0', 's', 'w', 'e'), "Swedish"}, + {MAKECODE('\0', 's', 'y', 'r'), "Syriac"}, + {MAKECODE('\0', 't', 'g', 'l'), "Tagalog"}, + {MAKECODE('\0', 't', 'a', 'h'), "Tahitian"}, + {MAKECODE('\0', 't', 'a', 'i'), "Tai (Other)"}, + {MAKECODE('\0', 't', 'g', 'k'), "Tajik"}, + {MAKECODE('\0', 't', 'm', 'h'), "Tamashek"}, + {MAKECODE('\0', 't', 'a', 'm'), "Tamil"}, + {MAKECODE('\0', 't', 'a', 't'), "Tatar"}, + {MAKECODE('\0', 't', 'e', 'l'), "Telugu"}, + {MAKECODE('\0', 't', 'e', 'r'), "Tereno"}, + {MAKECODE('\0', 't', 'e', 't'), "Tetum"}, + {MAKECODE('\0', 't', 'h', 'a'), "Thai"}, + {MAKECODE('\0', 't', 'i', 'b'), "Tibetan"}, + {MAKECODE('\0', 'b', 'o', 'd'), "Tibetan"}, + {MAKECODE('\0', 't', 'i', 'g'), "Tigre"}, + {MAKECODE('\0', 't', 'i', 'r'), "Tigrinya"}, + {MAKECODE('\0', 't', 'e', 'm'), "Timne"}, + {MAKECODE('\0', 't', 'i', 'v'), "Tiv"}, + {MAKECODE('\0', 't', 'l', 'h'), "tlhIngan-Hol"}, + {MAKECODE('\0', 't', 'l', 'i'), "Tlingit"}, + {MAKECODE('\0', 't', 'p', 'i'), "Tok Pisin"}, + {MAKECODE('\0', 't', 'k', 'l'), "Tokelau"}, + {MAKECODE('\0', 't', 'o', 'g'), "Tonga (Nyasa)"}, + {MAKECODE('\0', 't', 'o', 'n'), "Tonga (Tonga Islands)"}, + {MAKECODE('\0', 't', 's', 'i'), "Tsimshian"}, + {MAKECODE('\0', 't', 's', 'o'), "Tsonga"}, + {MAKECODE('\0', 't', 's', 'n'), "Tswana"}, + {MAKECODE('\0', 't', 'u', 'm'), "Tumbuka"}, + {MAKECODE('\0', 't', 'u', 'p'), "Tupi languages"}, + {MAKECODE('\0', 't', 'u', 'r'), "Turkish"}, + {MAKECODE('\0', 'o', 't', 'a'), "Turkish, Ottoman (1500-1928)"}, + {MAKECODE('\0', 't', 'u', 'k'), "Turkmen"}, + {MAKECODE('\0', 't', 'v', 'l'), "Tuvalu"}, + {MAKECODE('\0', 't', 'y', 'v'), "Tuvinian"}, + {MAKECODE('\0', 't', 'w', 'i'), "Twi"}, + {MAKECODE('\0', 'u', 'd', 'm'), "Udmurt"}, + {MAKECODE('\0', 'u', 'g', 'a'), "Ugaritic"}, + {MAKECODE('\0', 'u', 'i', 'g'), "Uighur"}, + {MAKECODE('\0', 'u', 'k', 'r'), "Ukrainian"}, + {MAKECODE('\0', 'u', 'm', 'b'), "Umbundu"}, + {MAKECODE('\0', 'u', 'n', 'd'), "Undetermined"}, + {MAKECODE('\0', 'h', 's', 'b'), "Upper Sorbian"}, + {MAKECODE('\0', 'u', 'r', 'd'), "Urdu"}, + {MAKECODE('\0', 'u', 'i', 'g'), "Uyghur"}, + {MAKECODE('\0', 'u', 'z', 'b'), "Uzbek"}, + {MAKECODE('\0', 'v', 'a', 'i'), "Vai"}, + {MAKECODE('\0', 'c', 'a', 't'), "Valencian"}, + {MAKECODE('\0', 'v', 'e', 'n'), "Venda"}, + {MAKECODE('\0', 'v', 'i', 'e'), "Vietnamese"}, + {MAKECODE('\0', 'v', 'o', 'l'), "Volap\xC3\xBCk"}, + {MAKECODE('\0', 'v', 'o', 't'), "Votic"}, + {MAKECODE('\0', 'w', 'a', 'k'), "Wakashan languages"}, + {MAKECODE('\0', 'w', 'a', 'l'), "Walamo"}, + {MAKECODE('\0', 'w', 'l', 'n'), "Walloon"}, + {MAKECODE('\0', 'w', 'a', 'r'), "Waray"}, + {MAKECODE('\0', 'w', 'a', 's'), "Washo"}, + {MAKECODE('\0', 'w', 'e', 'l'), "Welsh"}, + {MAKECODE('\0', 'c', 'y', 'm'), "Welsh"}, + {MAKECODE('\0', 'w', 'o', 'l'), "Wolof"}, + {MAKECODE('\0', 'x', 'h', 'o'), "Xhosa"}, + {MAKECODE('\0', 's', 'a', 'h'), "Yakut"}, + {MAKECODE('\0', 'y', 'a', 'o'), "Yao"}, + {MAKECODE('\0', 'y', 'a', 'p'), "Yapese"}, + {MAKECODE('\0', 'y', 'i', 'd'), "Yiddish"}, + {MAKECODE('\0', 'y', 'o', 'r'), "Yoruba"}, + {MAKECODE('\0', 'y', 'p', 'k'), "Yupik languages"}, + {MAKECODE('\0', 'z', 'n', 'd'), "Zande"}, + {MAKECODE('\0', 'z', 'a', 'p'), "Zapotec"}, + {MAKECODE('\0', 'z', 'e', 'n'), "Zenaga"}, + {MAKECODE('\0', 'z', 'h', 'a'), "Zhuang"}, + {MAKECODE('\0', 'z', 'u', 'l'), "Zulu"}, + {MAKECODE('\0', 'z', 'u', 'n'), "Zuni"}, +}}; +// clang-format on + +// clang-format off +const std::array<ISO639, 190> LanguageCodes = {{ + {"aa", "aar", NULL, NULL}, + {"ab", "abk", NULL, NULL}, + {"af", "afr", NULL, NULL}, + {"ak", "aka", NULL, NULL}, + {"am", "amh", NULL, NULL}, + {"ar", "ara", NULL, NULL}, + {"an", "arg", NULL, NULL}, + {"as", "asm", NULL, NULL}, + {"av", "ava", NULL, NULL}, + {"ae", "ave", NULL, NULL}, + {"ay", "aym", NULL, NULL}, + {"az", "aze", NULL, NULL}, + {"ba", "bak", NULL, NULL}, + {"bm", "bam", NULL, NULL}, + {"be", "bel", NULL, NULL}, + {"bn", "ben", NULL, NULL}, + {"bh", "bih", NULL, NULL}, + {"bi", "bis", NULL, NULL}, + {"bo", "tib", NULL, "bod"}, + {"bs", "bos", NULL, NULL}, + {"br", "bre", NULL, NULL}, + {"bg", "bul", NULL, NULL}, + {"ca", "cat", NULL, NULL}, + {"cs", "cze", "ces", "ces"}, + {"ch", "cha", NULL, NULL}, + {"ce", "che", NULL, NULL}, + {"cu", "chu", NULL, NULL}, + {"cv", "chv", NULL, NULL}, + {"kw", "cor", NULL, NULL}, + {"co", "cos", NULL, NULL}, + {"cr", "cre", NULL, NULL}, + {"cy", "wel", NULL, "cym"}, + {"da", "dan", NULL, NULL}, + {"de", "ger", "deu", "deu"}, + {"dv", "div", NULL, NULL}, + {"dz", "dzo", NULL, NULL}, + {"el", "gre", "ell", "ell"}, + {"en", "eng", NULL, NULL}, + {"eo", "epo", NULL, NULL}, + {"et", "est", NULL, NULL}, + {"eu", "baq", NULL, "eus"}, + {"ee", "ewe", NULL, NULL}, + {"fo", "fao", NULL, NULL}, + {"fa", "per", NULL, "fas"}, + {"fj", "fij", NULL, NULL}, + {"fi", "fin", NULL, NULL}, + {"fr", "fre", "fra", "fra"}, + {"fy", "fry", NULL, NULL}, + {"ff", "ful", NULL, NULL}, + {"gd", "gla", NULL, NULL}, + {"ga", "gle", NULL, NULL}, + {"gl", "glg", NULL, NULL}, + {"gv", "glv", NULL, NULL}, + {"gn", "grn", NULL, NULL}, + {"gu", "guj", NULL, NULL}, + {"ht", "hat", NULL, NULL}, + {"ha", "hau", NULL, NULL}, + {"he", "heb", NULL, NULL}, + {"hz", "her", NULL, NULL}, + {"hi", "hin", NULL, NULL}, + {"ho", "hmo", NULL, NULL}, + {"hr", "hrv", NULL, NULL}, + {"hu", "hun", NULL, NULL}, + {"hy", "arm", NULL, "hye"}, + {"ig", "ibo", NULL, NULL}, + {"io", "ido", NULL, NULL}, + {"ii", "iii", NULL, NULL}, + {"iu", "iku", NULL, NULL}, + {"ie", "ile", NULL, NULL}, + {"ia", "ina", NULL, NULL}, + {"id", "ind", NULL, NULL}, + {"ik", "ipk", NULL, NULL}, + {"is", "ice", "isl", "isl"}, + {"it", "ita", NULL, NULL}, + {"jv", "jav", NULL, NULL}, + {"ja", "jpn", NULL, NULL}, + {"kl", "kal", NULL, NULL}, + {"kn", "kan", NULL, NULL}, + {"ks", "kas", NULL, NULL}, + {"ka", "geo", NULL, "kat"}, + {"kr", "kau", NULL, NULL}, + {"kk", "kaz", NULL, NULL}, + {"km", "khm", NULL, NULL}, + {"ki", "kik", NULL, NULL}, + {"rw", "kin", NULL, NULL}, + {"ky", "kir", NULL, NULL}, + {"kv", "kom", NULL, NULL}, + {"kg", "kon", NULL, NULL}, + {"ko", "kor", NULL, NULL}, + {"kj", "kua", NULL, NULL}, + {"ku", "kur", NULL, NULL}, + {"lo", "lao", NULL, NULL}, + {"la", "lat", NULL, NULL}, + {"lv", "lav", NULL, NULL}, + {"li", "lim", NULL, NULL}, + {"ln", "lin", NULL, NULL}, + {"lt", "lit", NULL, NULL}, + {"lb", "ltz", NULL, NULL}, + {"lu", "lub", NULL, NULL}, + {"lg", "lug", NULL, NULL}, + {"mk", "mac", NULL, "mdk"}, + {"mh", "mah", NULL, NULL}, + {"ml", "mal", NULL, NULL}, + {"mi", "mao", NULL, "mri"}, + {"mr", "mar", NULL, NULL}, + {"ms", "may", NULL, "msa"}, + {"mg", "mlg", NULL, NULL}, + {"mt", "mlt", NULL, NULL}, + {"mn", "mon", NULL, NULL}, + {"my", "bur", NULL, "mya"}, + {"na", "nau", NULL, NULL}, + {"nv", "nav", NULL, NULL}, + {"nr", "nbl", NULL, NULL}, + {"nd", "nde", NULL, NULL}, + {"ng", "ndo", NULL, NULL}, + {"ne", "nep", NULL, NULL}, + {"nl", "dut", "nld", "nld"}, + {"nn", "nno", NULL, NULL}, + {"nb", "nob", NULL, NULL}, + {"no", "nor", NULL, NULL}, + {"ny", "nya", NULL, NULL}, + {"oc", "oci", NULL, NULL}, + {"oj", "oji", NULL, NULL}, + {"or", "ori", NULL, NULL}, + {"om", "orm", NULL, NULL}, + {"os", "oss", NULL, NULL}, + {"pa", "pan", NULL, NULL}, + // pb / pob = unofficial language code for Brazilian Portuguese + {"pb", "pob", NULL, NULL}, + {"pi", "pli", NULL, NULL}, + {"pl", "pol", "plk", NULL}, + {"pt", "por", "ptg", NULL}, + {"ps", "pus", NULL, NULL}, + {"qu", "que", NULL, NULL}, + {"rm", "roh", NULL, NULL}, + {"ro", "rum", "ron", "ron"}, + {"rn", "run", NULL, NULL}, + {"ru", "rus", NULL, NULL}, + {"sh", "scr", NULL, NULL}, + {"sg", "sag", NULL, NULL}, + {"sa", "san", NULL, NULL}, + {"si", "sin", NULL, NULL}, + {"sk", "slo", "sky", "slk"}, + {"sl", "slv", NULL, NULL}, + {"se", "sme", NULL, NULL}, + {"sm", "smo", NULL, NULL}, + {"sn", "sna", NULL, NULL}, + {"sd", "snd", NULL, NULL}, + {"so", "som", NULL, NULL}, + {"st", "sot", NULL, NULL}, + {"es", "spa", "esp", NULL}, + {"sq", "alb", NULL, "sqi"}, + {"sc", "srd", NULL, NULL}, + {"sr", "srp", NULL, NULL}, + {"ss", "ssw", NULL, NULL}, + {"su", "sun", NULL, NULL}, + {"sw", "swa", NULL, NULL}, + {"sv", "swe", "sve", NULL}, + {"ty", "tah", NULL, NULL}, + {"ta", "tam", NULL, NULL}, + {"tt", "tat", NULL, NULL}, + {"te", "tel", NULL, NULL}, + {"tg", "tgk", NULL, NULL}, + {"tl", "tgl", NULL, NULL}, + {"th", "tha", NULL, NULL}, + {"ti", "tir", NULL, NULL}, + {"to", "ton", NULL, NULL}, + {"tn", "tsn", NULL, NULL}, + {"ts", "tso", NULL, NULL}, + {"tk", "tuk", NULL, NULL}, + {"tr", "tur", "trk", NULL}, + {"tw", "twi", NULL, NULL}, + {"ug", "uig", NULL, NULL}, + {"uk", "ukr", NULL, NULL}, + {"ur", "urd", NULL, NULL}, + {"uz", "uzb", NULL, NULL}, + {"ve", "ven", NULL, NULL}, + {"vi", "vie", NULL, NULL}, + {"vo", "vol", NULL, NULL}, + {"wa", "wln", NULL, NULL}, + {"wo", "wol", NULL, NULL}, + {"xh", "xho", NULL, NULL}, + {"yi", "yid", NULL, NULL}, + {"yo", "yor", NULL, NULL}, + {"za", "zha", NULL, NULL}, + {"zh", "chi", "zho", "zho"}, + {"zu", "zul", NULL, NULL}, + {"zv", "und", NULL, NULL}, // Kodi intern mapping for missing "Undetermined" iso639-1 code + {"zx", "zxx", NULL, + NULL}, // Kodi intern mapping for missing "No linguistic content" iso639-1 code + {"zy", "mis", NULL, + NULL}, // Kodi intern mapping for missing "Miscellaneous languages" iso639-1 code + {"zz", "mul", NULL, NULL} // Kodi intern mapping for missing "Multiple languages" iso639-1 code +}}; +// clang-format on + +// Based on ISO 3166 +// clang-format off +const std::array<ISO3166_1, 245> RegionCodes = {{ + {"af", "afg"}, + {"ax", "ala"}, + {"al", "alb"}, + {"dz", "dza"}, + {"as", "asm"}, + {"ad", "and"}, + {"ao", "ago"}, + {"ai", "aia"}, + {"aq", "ata"}, + {"ag", "atg"}, + {"ar", "arg"}, + {"am", "arm"}, + {"aw", "abw"}, + {"au", "aus"}, + {"at", "aut"}, + {"az", "aze"}, + {"bs", "bhs"}, + {"bh", "bhr"}, + {"bd", "bgd"}, + {"bb", "brb"}, + {"by", "blr"}, + {"be", "bel"}, + {"bz", "blz"}, + {"bj", "ben"}, + {"bm", "bmu"}, + {"bt", "btn"}, + {"bo", "bol"}, + {"ba", "bih"}, + {"bw", "bwa"}, + {"bv", "bvt"}, + {"br", "bra"}, + {"io", "iot"}, + {"bn", "brn"}, + {"bg", "bgr"}, + {"bf", "bfa"}, + {"bi", "bdi"}, + {"kh", "khm"}, + {"cm", "cmr"}, + {"ca", "can"}, + {"cv", "cpv"}, + {"ky", "cym"}, + {"cf", "caf"}, + {"td", "tcd"}, + {"cl", "chl"}, + {"cn", "chn"}, + {"cx", "cxr"}, + {"co", "col"}, + {"km", "com"}, + {"cg", "cog"}, + {"cd", "cod"}, + {"ck", "cok"}, + {"cr", "cri"}, + {"ci", "civ"}, + {"hr", "hrv"}, + {"cu", "cub"}, + {"cy", "cyp"}, + {"cz", "cze"}, + {"dk", "dnk"}, + {"dj", "dji"}, + {"dm", "dma"}, + {"do", "dom"}, + {"ec", "ecu"}, + {"eg", "egy"}, + {"sv", "slv"}, + {"gq", "gnq"}, + {"er", "eri"}, + {"ee", "est"}, + {"et", "eth"}, + {"fk", "flk"}, + {"fo", "fro"}, + {"fj", "fji"}, + {"fi", "fin"}, + {"fr", "fra"}, + {"gf", "guf"}, + {"pf", "pyf"}, + {"tf", "atf"}, + {"ga", "gab"}, + {"gm", "gmb"}, + {"ge", "geo"}, + {"de", "deu"}, + {"gh", "gha"}, + {"gi", "gib"}, + {"gr", "grc"}, + {"gl", "grl"}, + {"gd", "grd"}, + {"gp", "glp"}, + {"gu", "gum"}, + {"gt", "gtm"}, + {"gg", "ggy"}, + {"gn", "gin"}, + {"gw", "gnb"}, + {"gy", "guy"}, + {"ht", "hti"}, + {"hm", "hmd"}, + {"va", "vat"}, + {"hn", "hnd"}, + {"hk", "hkg"}, + {"hu", "hun"}, + {"is", "isl"}, + {"in", "ind"}, + {"id", "idn"}, + {"ir", "irn"}, + {"iq", "irq"}, + {"ie", "irl"}, + {"im", "imn"}, + {"il", "isr"}, + {"it", "ita"}, + {"jm", "jam"}, + {"jp", "jpn"}, + {"je", "jey"}, + {"jo", "jor"}, + {"kz", "kaz"}, + {"ke", "ken"}, + {"ki", "kir"}, + {"kp", "prk"}, + {"kr", "kor"}, + {"kw", "kwt"}, + {"kg", "kgz"}, + {"la", "lao"}, + {"lv", "lva"}, + {"lb", "lbn"}, + {"ls", "lso"}, + {"lr", "lbr"}, + {"ly", "lby"}, + {"li", "lie"}, + {"lt", "ltu"}, + {"lu", "lux"}, + {"mo", "mac"}, + {"mk", "mkd"}, + {"mg", "mdg"}, + {"mw", "mwi"}, + {"my", "mys"}, + {"mv", "mdv"}, + {"ml", "mli"}, + {"mt", "mlt"}, + {"mh", "mhl"}, + {"mq", "mtq"}, + {"mr", "mrt"}, + {"mu", "mus"}, + {"yt", "myt"}, + {"mx", "mex"}, + {"fm", "fsm"}, + {"md", "mda"}, + {"mc", "mco"}, + {"mn", "mng"}, + {"me", "mne"}, + {"ms", "msr"}, + {"ma", "mar"}, + {"mz", "moz"}, + {"mm", "mmr"}, + {"na", "nam"}, + {"nr", "nru"}, + {"np", "npl"}, + {"nl", "nld"}, + {"an", "ant"}, + {"nc", "ncl"}, + {"nz", "nzl"}, + {"ni", "nic"}, + {"ne", "ner"}, + {"ng", "nga"}, + {"nu", "niu"}, + {"nf", "nfk"}, + {"mp", "mnp"}, + {"no", "nor"}, + {"om", "omn"}, + {"pk", "pak"}, + {"pw", "plw"}, + {"ps", "pse"}, + {"pa", "pan"}, + {"pg", "png"}, + {"py", "pry"}, + {"pe", "per"}, + {"ph", "phl"}, + {"pn", "pcn"}, + {"pl", "pol"}, + {"pt", "prt"}, + {"pr", "pri"}, + {"qa", "qat"}, + {"re", "reu"}, + {"ro", "rou"}, + {"ru", "rus"}, + {"rw", "rwa"}, + {"bl", "blm"}, + {"sh", "shn"}, + {"kn", "kna"}, + {"lc", "lca"}, + {"mf", "maf"}, + {"pm", "spm"}, + {"vc", "vct"}, + {"ws", "wsm"}, + {"sm", "smr"}, + {"st", "stp"}, + {"sa", "sau"}, + {"sn", "sen"}, + {"rs", "srb"}, + {"sc", "syc"}, + {"sl", "sle"}, + {"sg", "sgp"}, + {"sk", "svk"}, + {"si", "svn"}, + {"sb", "slb"}, + {"so", "som"}, + {"za", "zaf"}, + {"gs", "sgs"}, + {"es", "esp"}, + {"lk", "lka"}, + {"sd", "sdn"}, + {"sr", "sur"}, + {"sj", "sjm"}, + {"sz", "swz"}, + {"se", "swe"}, + {"ch", "che"}, + {"sy", "syr"}, + {"tw", "twn"}, + {"tj", "tjk"}, + {"tz", "tza"}, + {"th", "tha"}, + {"tl", "tls"}, + {"tg", "tgo"}, + {"tk", "tkl"}, + {"to", "ton"}, + {"tt", "tto"}, + {"tn", "tun"}, + {"tr", "tur"}, + {"tm", "tkm"}, + {"tc", "tca"}, + {"tv", "tuv"}, + {"ug", "uga"}, + {"ua", "ukr"}, + {"ae", "are"}, + {"gb", "gbr"}, + {"us", "usa"}, + {"um", "umi"}, + {"uy", "ury"}, + {"uz", "uzb"}, + {"vu", "vut"}, + {"ve", "ven"}, + {"vn", "vnm"}, + {"vg", "vgb"}, + {"vi", "vir"}, + {"wf", "wlf"}, + {"eh", "esh"}, + {"ye", "yem"}, + {"zm", "zmb"}, + {"zw", "zwe"} +}}; +// clang-format on |