/*
 *  Copyright (C) 2025 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.
 */

#pragma once

#include "utils/StringUtils.h"
#include "utils/i18n/Iso639.h"

#include <algorithm>
#include <array>
#include <cstdint>
#include <string_view>

namespace KODI::UTILS::I18N
{
struct ISO639_2_TB
{
  uint32_t terminological;
  uint32_t bibliographic;
};

// ISO 639-2 table, sorted by name
// Changes history: https://www.loc.gov/standards/iso639-2/php/code_changes.php

// 486 active ISO 639-2 languages (qaa-qtz row is excluded) + 1 Kodi addition
inline constexpr int ISO639_2_COUNT = 487;

// clang-format off
constexpr std::array<struct LCENTRY, ISO639_2_COUNT> TableISO639_2ByCode = {{
    // Active ISO 639-2 entries, terminology code and preferred name only, sorted by code
    {StringToLongCode("aar"), "Afar"},
    {StringToLongCode("abk"), "Abkhazian"},
    {StringToLongCode("ace"), "Achinese"},
    {StringToLongCode("ach"), "Acoli"},
    {StringToLongCode("ada"), "Adangme"},
    {StringToLongCode("ady"), "Adyghe"},
    {StringToLongCode("afa"), "Afro-Asiatic languages"},
    {StringToLongCode("afh"), "Afrihili"},
    {StringToLongCode("afr"), "Afrikaans"},
    {StringToLongCode("ain"), "Ainu"},
    {StringToLongCode("aka"), "Akan"},
    {StringToLongCode("akk"), "Akkadian"},
    {StringToLongCode("ale"), "Aleut"},
    {StringToLongCode("alg"), "Algonquian languages"},
    {StringToLongCode("alt"), "Southern Altai"},
    {StringToLongCode("amh"), "Amharic"},
    {StringToLongCode("ang"), "English, Old (ca.450–1100)"},
    {StringToLongCode("anp"), "Angika"},
    {StringToLongCode("apa"), "Apache languages"},
    {StringToLongCode("ara"), "Arabic"},
    {StringToLongCode("arc"), "Official Aramaic (700–300 BCE)"},
    {StringToLongCode("arg"), "Aragonese"},
    {StringToLongCode("arn"), "Mapudungun"},
    {StringToLongCode("arp"), "Arapaho"},
    {StringToLongCode("art"), "Artificial languages"},
    {StringToLongCode("arw"), "Arawak"},
    {StringToLongCode("asm"), "Assamese"},
    {StringToLongCode("ast"), "Asturian"},
    {StringToLongCode("ath"), "Athapascan languages"},
    {StringToLongCode("aus"), "Australian languages"},
    {StringToLongCode("ava"), "Avaric"},
    {StringToLongCode("ave"), "Avestan"},
    {StringToLongCode("awa"), "Awadhi"},
    {StringToLongCode("aym"), "Aymara"},
    {StringToLongCode("aze"), "Azerbaijani"},
    {StringToLongCode("bad"), "Banda languages"},
    {StringToLongCode("bai"), "Bamileke languages"},
    {StringToLongCode("bak"), "Bashkir"},
    {StringToLongCode("bal"), "Baluchi"},
    {StringToLongCode("bam"), "Bambara"},
    {StringToLongCode("ban"), "Balinese"},
    {StringToLongCode("bas"), "Basa"},
    {StringToLongCode("bat"), "Baltic languages"},
    {StringToLongCode("bej"), "Beja"},
    {StringToLongCode("bel"), "Belarusian"},
    {StringToLongCode("bem"), "Bemba"},
    {StringToLongCode("ben"), "Bengali"},
    {StringToLongCode("ber"), "Berber languages"},
    {StringToLongCode("bho"), "Bhojpuri"},
    {StringToLongCode("bih"), "Bihari languages"},
    {StringToLongCode("bik"), "Bikol"},
    {StringToLongCode("bin"), "Bini"},
    {StringToLongCode("bis"), "Bislama"},
    {StringToLongCode("bla"), "Siksika"},
    {StringToLongCode("bnt"), "Bantu languages"},
    {StringToLongCode("bod"), "Tibetan"},
    {StringToLongCode("bos"), "Bosnian"},
    {StringToLongCode("bra"), "Braj"},
    {StringToLongCode("bre"), "Breton"},
    {StringToLongCode("btk"), "Batak languages"},
    {StringToLongCode("bua"), "Buriat"},
    {StringToLongCode("bug"), "Buginese"},
    {StringToLongCode("bul"), "Bulgarian"},
    {StringToLongCode("byn"), "Blin"},
    {StringToLongCode("cad"), "Caddo"},
    {StringToLongCode("cai"), "Central American Indian languages"},
    {StringToLongCode("car"), "Galibi Carib"},
    {StringToLongCode("cat"), "Catalan"},
    {StringToLongCode("cau"), "Caucasian languages"},
    {StringToLongCode("ceb"), "Cebuano"},
    {StringToLongCode("cel"), "Celtic languages"},
    {StringToLongCode("ces"), "Czech"},
    {StringToLongCode("cha"), "Chamorro"},
    {StringToLongCode("chb"), "Chibcha"},
    {StringToLongCode("che"), "Chechen"},
    {StringToLongCode("chg"), "Chagatai"},
    {StringToLongCode("chk"), "Chuukese"},
    {StringToLongCode("chm"), "Mari"},
    {StringToLongCode("chn"), "Chinook Jargon"},
    {StringToLongCode("cho"), "Choctaw"},
    {StringToLongCode("chp"), "Chipewyan"},
    {StringToLongCode("chr"), "Cherokee"},
    {StringToLongCode("chu"), "Church Slavic"},
    {StringToLongCode("chv"), "Chuvash"},
    {StringToLongCode("chy"), "Cheyenne"},
    {StringToLongCode("cmc"), "Chamic languages"},
    {StringToLongCode("cnr"), "Montenegrin"},
    {StringToLongCode("cop"), "Coptic"},
    {StringToLongCode("cor"), "Cornish"},
    {StringToLongCode("cos"), "Corsican"},
    {StringToLongCode("cpe"), "Creoles and pidgins, English based"},
    {StringToLongCode("cpf"), "Creoles and pidgins, French-based"},
    {StringToLongCode("cpp"), "Creoles and pidgins, Portuguese-based"},
    {StringToLongCode("cre"), "Cree"},
    {StringToLongCode("crh"), "Crimean Tatar"},
    {StringToLongCode("crp"), "Creoles and pidgins"},
    {StringToLongCode("csb"), "Kashubian"},
    {StringToLongCode("cus"), "Cushitic languages"},
    {StringToLongCode("cym"), "Welsh"},
    {StringToLongCode("dak"), "Dakota"},
    {StringToLongCode("dan"), "Danish"},
    {StringToLongCode("dar"), "Dargwa"},
    {StringToLongCode("day"), "Land Dayak languages"},
    {StringToLongCode("del"), "Delaware"},
    {StringToLongCode("den"), "Slave (Athapascan)"},
    {StringToLongCode("deu"), "German"},
    {StringToLongCode("dgr"), "Tlicho"},
    {StringToLongCode("din"), "Dinka"},
    {StringToLongCode("div"), "Divehi"},
    {StringToLongCode("doi"), "Dogri"},
    {StringToLongCode("dra"), "Dravidian languages"},
    {StringToLongCode("dsb"), "Lower Sorbian"},
    {StringToLongCode("dua"), "Duala"},
    {StringToLongCode("dum"), "Dutch, Middle (ca. 1050–1350)"},
    {StringToLongCode("dyu"), "Dyula"},
    {StringToLongCode("dzo"), "Dzongkha"},
    {StringToLongCode("efi"), "Efik"},
    {StringToLongCode("egy"), "Egyptian (Ancient)"},
    {StringToLongCode("eka"), "Ekajuk"},
    {StringToLongCode("ell"), "Greek, Modern (1453–)"},
    {StringToLongCode("elx"), "Elamite"},
    {StringToLongCode("eng"), "English"},
    {StringToLongCode("enm"), "English, Middle (1100–1500)"},
    {StringToLongCode("epo"), "Esperanto"},
    {StringToLongCode("est"), "Estonian"},
    {StringToLongCode("eus"), "Basque"},
    {StringToLongCode("ewe"), "Ewe"},
    {StringToLongCode("ewo"), "Ewondo"},
    {StringToLongCode("fan"), "Fang"},
    {StringToLongCode("fao"), "Faroese"},
    {StringToLongCode("fas"), "Persian"},
    {StringToLongCode("fat"), "Fanti"},
    {StringToLongCode("fij"), "Fijian"},
    {StringToLongCode("fil"), "Filipino"},
    {StringToLongCode("fin"), "Finnish"},
    {StringToLongCode("fiu"), "Finno-Ugrian languages"},
    {StringToLongCode("fon"), "Fon"},
    {StringToLongCode("fra"), "French"},
    {StringToLongCode("frm"), "French, Middle (ca. 1400–1600)"},
    {StringToLongCode("fro"), "French, Old (842–ca. 1400)"},
    {StringToLongCode("frr"), "Northern Frisian"},
    {StringToLongCode("frs"), "Eastern Frisian"},
    {StringToLongCode("fry"), "Western Frisian"},
    {StringToLongCode("ful"), "Fulah"},
    {StringToLongCode("fur"), "Friulian"},
    {StringToLongCode("gaa"), "Ga"},
    {StringToLongCode("gay"), "Gayo"},
    {StringToLongCode("gba"), "Gbaya"},
    {StringToLongCode("gem"), "Germanic languages"},
    {StringToLongCode("gez"), "Geez"},
    {StringToLongCode("gil"), "Gilbertese"},
    {StringToLongCode("gla"), "Gaelic"},
    {StringToLongCode("gle"), "Irish"},
    {StringToLongCode("glg"), "Galician"},
    {StringToLongCode("glv"), "Manx"},
    {StringToLongCode("gmh"), "German, Middle High (ca. 1050–1500)"},
    {StringToLongCode("goh"), "German, Old High (ca. 750–1050)"},
    {StringToLongCode("gon"), "Gondi"},
    {StringToLongCode("gor"), "Gorontalo"},
    {StringToLongCode("got"), "Gothic"},
    {StringToLongCode("grb"), "Grebo"},
    {StringToLongCode("grc"), "Greek, Ancient (to 1453)"},
    {StringToLongCode("grn"), "Guarani"},
    {StringToLongCode("gsw"), "Swiss German"},
    {StringToLongCode("guj"), "Gujarati"},
    {StringToLongCode("gwi"), "Gwich'in"},
    {StringToLongCode("hai"), "Haida"},
    {StringToLongCode("hat"), "Haitian"},
    {StringToLongCode("hau"), "Hausa"},
    {StringToLongCode("haw"), "Hawaiian"},
    {StringToLongCode("heb"), "Hebrew"},
    {StringToLongCode("her"), "Herero"},
    {StringToLongCode("hil"), "Hiligaynon"},
    {StringToLongCode("him"), "Himachali languages"},
    {StringToLongCode("hin"), "Hindi"},
    {StringToLongCode("hit"), "Hittite"},
    {StringToLongCode("hmn"), "Hmong"},
    {StringToLongCode("hmo"), "Hiri Motu"},
    {StringToLongCode("hrv"), "Croatian"},
    {StringToLongCode("hsb"), "Upper Sorbian"},
    {StringToLongCode("hun"), "Hungarian"},
    {StringToLongCode("hup"), "Hupa"},
    {StringToLongCode("hye"), "Armenian"},
    {StringToLongCode("iba"), "Iban"},
    {StringToLongCode("ibo"), "Igbo"},
    {StringToLongCode("ido"), "Ido"},
    {StringToLongCode("iii"), "Sichuan Yi"},
    {StringToLongCode("ijo"), "Ijo languages"},
    {StringToLongCode("iku"), "Inuktitut"},
    {StringToLongCode("ile"), "Interlingue"},
    {StringToLongCode("ilo"), "Iloko"},
    {StringToLongCode("ina"), "Interlingua (International Auxiliary Language Association)"},
    {StringToLongCode("inc"), "Indic languages"},
    {StringToLongCode("ind"), "Indonesian"},
    {StringToLongCode("ine"), "Indo-European languages"},
    {StringToLongCode("inh"), "Ingush"},
    {StringToLongCode("ipk"), "Inupiaq"},
    {StringToLongCode("ira"), "Iranian languages"},
    {StringToLongCode("iro"), "Iroquoian languages"},
    {StringToLongCode("isl"), "Icelandic"},
    {StringToLongCode("ita"), "Italian"},
    {StringToLongCode("jav"), "Javanese"},
    {StringToLongCode("jbo"), "Lojban"},
    {StringToLongCode("jpn"), "Japanese"},
    {StringToLongCode("jpr"), "Judeo-Persian"},
    {StringToLongCode("jrb"), "Judeo-Arabic"},
    {StringToLongCode("kaa"), "Kara-Kalpak"},
    {StringToLongCode("kab"), "Kabyle"},
    {StringToLongCode("kac"), "Kachin"},
    {StringToLongCode("kal"), "Kalaallisut"},
    {StringToLongCode("kam"), "Kamba"},
    {StringToLongCode("kan"), "Kannada"},
    {StringToLongCode("kar"), "Karen languages"},
    {StringToLongCode("kas"), "Kashmiri"},
    {StringToLongCode("kat"), "Georgian"},
    {StringToLongCode("kau"), "Kanuri"},
    {StringToLongCode("kaw"), "Kawi"},
    {StringToLongCode("kaz"), "Kazakh"},
    {StringToLongCode("kbd"), "Kabardian"},
    {StringToLongCode("kha"), "Khasi"},
    {StringToLongCode("khi"), "Khoisan languages"},
    {StringToLongCode("khm"), "Central Khmer"},
    {StringToLongCode("kho"), "Khotanese"},
    {StringToLongCode("kik"), "Kikuyu"},
    {StringToLongCode("kin"), "Kinyarwanda"},
    {StringToLongCode("kir"), "Kirghiz"},
    {StringToLongCode("kmb"), "Kimbundu"},
    {StringToLongCode("kok"), "Konkani"},
    {StringToLongCode("kom"), "Komi"},
    {StringToLongCode("kon"), "Kongo"},
    {StringToLongCode("kor"), "Korean"},
    {StringToLongCode("kos"), "Kosraean"},
    {StringToLongCode("kpe"), "Kpelle"},
    {StringToLongCode("krc"), "Karachay-Balkar"},
    {StringToLongCode("krl"), "Karelian"},
    {StringToLongCode("kro"), "Kru languages"},
    {StringToLongCode("kru"), "Kurukh"},
    {StringToLongCode("kua"), "Kuanyama"},
    {StringToLongCode("kum"), "Kumyk"},
    {StringToLongCode("kur"), "Kurdish"},
    {StringToLongCode("kut"), "Kutenai"},
    {StringToLongCode("lad"), "Ladino"},
    {StringToLongCode("lah"), "Lahnda"},
    {StringToLongCode("lam"), "Lamba"},
    {StringToLongCode("lao"), "Lao"},
    {StringToLongCode("lat"), "Latin"},
    {StringToLongCode("lav"), "Latvian"},
    {StringToLongCode("lez"), "Lezghian"},
    {StringToLongCode("lim"), "Limburgan"},
    {StringToLongCode("lin"), "Lingala"},
    {StringToLongCode("lit"), "Lithuanian"},
    {StringToLongCode("lol"), "Mongo"},
    {StringToLongCode("loz"), "Lozi"},
    {StringToLongCode("ltz"), "Luxembourgish"},
    {StringToLongCode("lua"), "Luba-Lulua"},
    {StringToLongCode("lub"), "Luba-Katanga"},
    {StringToLongCode("lug"), "Ganda"},
    {StringToLongCode("lui"), "Luiseno"},
    {StringToLongCode("lun"), "Lunda"},
    {StringToLongCode("luo"), "Luo (Kenya and Tanzania)"},
    {StringToLongCode("lus"), "Lushai"},
    {StringToLongCode("mad"), "Madurese"},
    {StringToLongCode("mag"), "Magahi"},
    {StringToLongCode("mah"), "Marshallese"},
    {StringToLongCode("mai"), "Maithili"},
    {StringToLongCode("mak"), "Makasar"},
    {StringToLongCode("mal"), "Malayalam"},
    {StringToLongCode("man"), "Mandingo"},
    {StringToLongCode("map"), "Austronesian languages"},
    {StringToLongCode("mar"), "Marathi"},
    {StringToLongCode("mas"), "Masai"},
    {StringToLongCode("mdf"), "Moksha"},
    {StringToLongCode("mdr"), "Mandar"},
    {StringToLongCode("men"), "Mende"},
    {StringToLongCode("mga"), "Irish, Middle (900–1200)"},
    {StringToLongCode("mic"), "Mi'kmaq"},
    {StringToLongCode("min"), "Minangkabau"},
    {StringToLongCode("mis"), "Uncoded languages"},
    {StringToLongCode("mkd"), "Macedonian"},
    {StringToLongCode("mkh"), "Mon-Khmer languages"},
    {StringToLongCode("mlg"), "Malagasy"},
    {StringToLongCode("mlt"), "Maltese"},
    {StringToLongCode("mnc"), "Manchu"},
    {StringToLongCode("mni"), "Manipuri"},
    {StringToLongCode("mno"), "Manobo languages"},
    {StringToLongCode("moh"), "Mohawk"},
    {StringToLongCode("mon"), "Mongolian"},
    {StringToLongCode("mos"), "Mossi"},
    {StringToLongCode("mri"), "Maori"},
    {StringToLongCode("msa"), "Malay"},
    {StringToLongCode("mul"), "Multiple languages"},
    {StringToLongCode("mun"), "Munda languages"},
    {StringToLongCode("mus"), "Creek"},
    {StringToLongCode("mwl"), "Mirandese"},
    {StringToLongCode("mwr"), "Marwari"},
    {StringToLongCode("mya"), "Burmese"},
    {StringToLongCode("myn"), "Mayan languages"},
    {StringToLongCode("myv"), "Erzya"},
    {StringToLongCode("nah"), "Nahuatl languages"},
    {StringToLongCode("nai"), "North American Indian languages"},
    {StringToLongCode("nap"), "Neapolitan"},
    {StringToLongCode("nau"), "Nauru"},
    {StringToLongCode("nav"), "Navajo"},
    {StringToLongCode("nbl"), "Ndebele, South"},
    {StringToLongCode("nde"), "Ndebele, North"},
    {StringToLongCode("ndo"), "Ndonga"},
    {StringToLongCode("nds"), "Low German"},
    {StringToLongCode("nep"), "Nepali"},
    {StringToLongCode("new"), "Nepal Bhasa"},
    {StringToLongCode("nia"), "Nias"},
    {StringToLongCode("nic"), "Niger-Kordofanian languages"},
    {StringToLongCode("niu"), "Niuean"},
    {StringToLongCode("nld"), "Dutch"},
    {StringToLongCode("nno"), "Norwegian Nynorsk"},
    {StringToLongCode("nob"), "Bokmål, Norwegian"},
    {StringToLongCode("nog"), "Nogai"},
    {StringToLongCode("non"), "Norse, Old"},
    {StringToLongCode("nor"), "Norwegian"},
    {StringToLongCode("nqo"), "N'Ko"},
    {StringToLongCode("nso"), "Pedi"},
    {StringToLongCode("nub"), "Nubian languages"},
    {StringToLongCode("nwc"), "Classical Newari"},
    {StringToLongCode("nya"), "Chichewa"},
    {StringToLongCode("nym"), "Nyamwezi"},
    {StringToLongCode("nyn"), "Nyankole"},
    {StringToLongCode("nyo"), "Nyoro"},
    {StringToLongCode("nzi"), "Nzima"},
    {StringToLongCode("oci"), "Occitan (post 1500)"},
    {StringToLongCode("oji"), "Ojibwa"},
    {StringToLongCode("ori"), "Oriya"},
    {StringToLongCode("orm"), "Oromo"},
    {StringToLongCode("osa"), "Osage"},
    {StringToLongCode("oss"), "Ossetian"},
    {StringToLongCode("ota"), "Turkish, Ottoman (1500–1928)"},
    {StringToLongCode("oto"), "Otomian languages"},
    {StringToLongCode("paa"), "Papuan languages"},
    {StringToLongCode("pag"), "Pangasinan"},
    {StringToLongCode("pal"), "Pahlavi"},
    {StringToLongCode("pam"), "Pampanga"},
    {StringToLongCode("pan"), "Panjabi"},
    {StringToLongCode("pap"), "Papiamento"},
    {StringToLongCode("pau"), "Palauan"},
    {StringToLongCode("peo"), "Persian, Old (c. 600–400 B.C.)"},
    {StringToLongCode("phi"), "Philippine languages"},
    {StringToLongCode("phn"), "Phoenician"},
    {StringToLongCode("pli"), "Pali"},
    // Kodi addition, pob unofficial language code for Brazilian Portuguese
    {StringToLongCode("pob"), "Portuguese (Brazil)"},
    {StringToLongCode("pol"), "Polish"},
    {StringToLongCode("pon"), "Pohnpeian"},
    {StringToLongCode("por"), "Portuguese"},
    {StringToLongCode("pra"), "Prakrit languages"},
    {StringToLongCode("pro"), "Provençal, Old (to 1500)"},
    {StringToLongCode("pus"), "Pushto"},
    {StringToLongCode("que"), "Quechua"},
    {StringToLongCode("raj"), "Rajasthani"},
    {StringToLongCode("rap"), "Rapanui"},
    {StringToLongCode("rar"), "Rarotongan"},
    {StringToLongCode("roa"), "Romance languages"},
    {StringToLongCode("roh"), "Romansh"},
    {StringToLongCode("rom"), "Romany"},
    {StringToLongCode("ron"), "Romanian"},
    {StringToLongCode("run"), "Rundi"},
    {StringToLongCode("rup"), "Aromanian"},
    {StringToLongCode("rus"), "Russian"},
    {StringToLongCode("sad"), "Sandawe"},
    {StringToLongCode("sag"), "Sango"},
    {StringToLongCode("sah"), "Yakut"},
    {StringToLongCode("sai"), "South American Indian languages"},
    {StringToLongCode("sal"), "Salishan languages"},
    {StringToLongCode("sam"), "Samaritan Aramaic"},
    {StringToLongCode("san"), "Sanskrit"},
    {StringToLongCode("sas"), "Sasak"},
    {StringToLongCode("sat"), "Santali"},
    {StringToLongCode("scn"), "Sicilian"},
    {StringToLongCode("sco"), "Scots"},
    {StringToLongCode("sel"), "Selkup"},
    {StringToLongCode("sem"), "Semitic languages"},
    {StringToLongCode("sga"), "Irish, Old (to 900)"},
    {StringToLongCode("sgn"), "Sign languages"},
    {StringToLongCode("shn"), "Shan"},
    {StringToLongCode("sid"), "Sidamo"},
    {StringToLongCode("sin"), "Sinhala"},
    {StringToLongCode("sio"), "Siouan languages"},
    {StringToLongCode("sit"), "Sino-Tibetan languages"},
    {StringToLongCode("sla"), "Slavic languages"},
    {StringToLongCode("slk"), "Slovak"},
    {StringToLongCode("slv"), "Slovenian"},
    {StringToLongCode("sma"), "Southern Sami"},
    {StringToLongCode("sme"), "Northern Sami"},
    {StringToLongCode("smi"), "Sami languages"},
    {StringToLongCode("smj"), "Lule Sami"},
    {StringToLongCode("smn"), "Inari Sami"},
    {StringToLongCode("smo"), "Samoan"},
    {StringToLongCode("sms"), "Skolt Sami"},
    {StringToLongCode("sna"), "Shona"},
    {StringToLongCode("snd"), "Sindhi"},
    {StringToLongCode("snk"), "Soninke"},
    {StringToLongCode("sog"), "Sogdian"},
    {StringToLongCode("som"), "Somali"},
    {StringToLongCode("son"), "Songhai languages"},
    {StringToLongCode("sot"), "Sotho, Southern"},
    {StringToLongCode("spa"), "Spanish"},
    {StringToLongCode("sqi"), "Albanian"},
    {StringToLongCode("srd"), "Sardinian"},
    {StringToLongCode("srn"), "Sranan Tongo"},
    {StringToLongCode("srp"), "Serbian"},
    {StringToLongCode("srr"), "Serer"},
    {StringToLongCode("ssa"), "Nilo-Saharan languages"},
    {StringToLongCode("ssw"), "Swati"},
    {StringToLongCode("suk"), "Sukuma"},
    {StringToLongCode("sun"), "Sundanese"},
    {StringToLongCode("sus"), "Susu"},
    {StringToLongCode("sux"), "Sumerian"},
    {StringToLongCode("swa"), "Swahili"},
    {StringToLongCode("swe"), "Swedish"},
    {StringToLongCode("syc"), "Classical Syriac"},
    {StringToLongCode("syr"), "Syriac"},
    {StringToLongCode("tah"), "Tahitian"},
    {StringToLongCode("tai"), "Tai languages"},
    {StringToLongCode("tam"), "Tamil"},
    {StringToLongCode("tat"), "Tatar"},
    {StringToLongCode("tel"), "Telugu"},
    {StringToLongCode("tem"), "Timne"},
    {StringToLongCode("ter"), "Tereno"},
    {StringToLongCode("tet"), "Tetum"},
    {StringToLongCode("tgk"), "Tajik"},
    {StringToLongCode("tgl"), "Tagalog"},
    {StringToLongCode("tha"), "Thai"},
    {StringToLongCode("tig"), "Tigre"},
    {StringToLongCode("tir"), "Tigrinya"},
    {StringToLongCode("tiv"), "Tiv"},
    {StringToLongCode("tkl"), "Tokelau"},
    {StringToLongCode("tlh"), "Klingon"},
    {StringToLongCode("tli"), "Tlingit"},
    {StringToLongCode("tmh"), "Tamashek"},
    {StringToLongCode("tog"), "Tonga (Nyasa)"},
    {StringToLongCode("ton"), "Tonga (Tonga Islands)"},
    {StringToLongCode("tpi"), "Tok Pisin"},
    {StringToLongCode("tsi"), "Tsimshian"},
    {StringToLongCode("tsn"), "Tswana"},
    {StringToLongCode("tso"), "Tsonga"},
    {StringToLongCode("tuk"), "Turkmen"},
    {StringToLongCode("tum"), "Tumbuka"},
    {StringToLongCode("tup"), "Tupi languages"},
    {StringToLongCode("tur"), "Turkish"},
    {StringToLongCode("tut"), "Altaic languages"},
    {StringToLongCode("tvl"), "Tuvalu"},
    {StringToLongCode("twi"), "Twi"},
    {StringToLongCode("tyv"), "Tuvinian"},
    {StringToLongCode("udm"), "Udmurt"},
    {StringToLongCode("uga"), "Ugaritic"},
    {StringToLongCode("uig"), "Uighur"},
    {StringToLongCode("ukr"), "Ukrainian"},
    {StringToLongCode("umb"), "Umbundu"},
    {StringToLongCode("und"), "Undetermined"},
    {StringToLongCode("urd"), "Urdu"},
    {StringToLongCode("uzb"), "Uzbek"},
    {StringToLongCode("vai"), "Vai"},
    {StringToLongCode("ven"), "Venda"},
    {StringToLongCode("vie"), "Vietnamese"},
    {StringToLongCode("vol"), "Volapük"},
    {StringToLongCode("vot"), "Votic"},
    {StringToLongCode("wak"), "Wakashan languages"},
    {StringToLongCode("wal"), "Wolaitta"},
    {StringToLongCode("war"), "Waray"},
    {StringToLongCode("was"), "Washo"},
    {StringToLongCode("wen"), "Sorbian languages"},
    {StringToLongCode("wln"), "Walloon"},
    {StringToLongCode("wol"), "Wolof"},
    {StringToLongCode("xal"), "Kalmyk"},
    {StringToLongCode("xho"), "Xhosa"},
    {StringToLongCode("yao"), "Yao"},
    {StringToLongCode("yap"), "Yapese"},
    {StringToLongCode("yid"), "Yiddish"},
    {StringToLongCode("yor"), "Yoruba"},
    {StringToLongCode("ypk"), "Yupik languages"},
    {StringToLongCode("zap"), "Zapotec"},
    {StringToLongCode("zbl"), "Blissymbols"},
    {StringToLongCode("zen"), "Zenaga"},
    {StringToLongCode("zgh"), "Standard Moroccan Tamazight"},
    {StringToLongCode("zha"), "Zhuang"},
    {StringToLongCode("zho"), "Chinese"},
    {StringToLongCode("znd"), "Zande languages"},
    {StringToLongCode("zul"), "Zulu"},
    {StringToLongCode("zun"), "Zuni"},
    {StringToLongCode("zxx"), "No linguistic content"},
    {StringToLongCode("zza"), "Zaza"},
}};
// clang-format on

//! @todo handle deprecated codes with names overlapping active codes?
// 2001-08-13 jaw Javanese deprecated, replaced with jav.
// 2008-11-03 mol Moldavian deprecated, no replacement - but is additional name of ron

static_assert(std::ranges::is_sorted(TableISO639_2ByCode, {}, &LCENTRY::code));

static_assert(std::ranges::all_of(
    TableISO639_2ByCode,
    [](std::string_view name) { return StringUtils::IsAsciiTrimmed(name); },
    &LCENTRY::name));

// Additional names for ISO 639-2 codes that have multiple names
// 79 from the standard, 3 Kodi additions
static constexpr int ISO639_2_ADDL_NAMES_COUNT = 79 + 3;

// clang-format off
constexpr std::array<struct LCENTRY, ISO639_2_ADDL_NAMES_COUNT> TableISO639_2_Names = {{
    {StringToLongCode("abk"), "Abkhaz"}, // Kodi addition
    {StringToLongCode("ady"), "Adygei"},
    {StringToLongCode("arc"), "Imperial Aramaic (700–300 BCE)"},
    {StringToLongCode("arn"), "Mapuche"},
    {StringToLongCode("ast"), "Bable"},
    {StringToLongCode("ast"), "Leonese"},
    {StringToLongCode("ast"), "Asturleonese"},
    {StringToLongCode("bej"), "Bedawiyet"},
    {StringToLongCode("bin"), "Edo"},
    {StringToLongCode("byn"), "Bilin"},
    {StringToLongCode("cat"), "Valencian"},
    {StringToLongCode("chp"), "Dene Suline"},
    {StringToLongCode("chu"), "Old Slavonic"},
    {StringToLongCode("chu"), "Church Slavonic"},
    {StringToLongCode("chu"), "Old Bulgarian"},
    {StringToLongCode("chu"), "Old Church Slavonic"},
    {StringToLongCode("crh"), "Crimean Turkish"},
    {StringToLongCode("dgr"), "Dogrib"},
    {StringToLongCode("div"), "Dhivehi"},
    {StringToLongCode("div"), "Maldivian"},
    {StringToLongCode("fil"), "Pilipino"},
    {StringToLongCode("gla"), "Scottish Gaelic"},
    {StringToLongCode("gsw"), "Alemannic"},
    {StringToLongCode("gsw"), "Alsatian"},
    {StringToLongCode("hat"), "Haitian Creole"},
    {StringToLongCode("him"), "Pahari languages"},
    {StringToLongCode("hmn"), "Mong"},
    {StringToLongCode("iii"), "Nuosu"},
    {StringToLongCode("ile"), "Occidental"},
    {StringToLongCode("kac"), "Jingpho"},
    {StringToLongCode("kal"), "Greenlandic"},
    {StringToLongCode("kho"), "Sakan"},
    {StringToLongCode("kik"), "Gikuyu"},
    {StringToLongCode("kir"), "Kyrgyz"},
    {StringToLongCode("kua"), "Kwanyama"},
    {StringToLongCode("lim"), "Limburger"},
    {StringToLongCode("lim"), "Limburgish"},
    {StringToLongCode("ltz"), "Letzeburgesch"},
    {StringToLongCode("mic"), "Micmac"},
    {StringToLongCode("nav"), "Navaho"},
    {StringToLongCode("nbl"), "South Ndebele"},
    {StringToLongCode("nde"), "North Ndebele"},
    {StringToLongCode("nds"), "Low Saxon"},
    {StringToLongCode("nds"), "German, Low"},
    {StringToLongCode("nds"), "Saxon Low"},
    {StringToLongCode("new"), "Newari"},
    {StringToLongCode("nld"), "Flemish"},
    {StringToLongCode("nno"), "Nynorsk, Norwegian"},
    {StringToLongCode("nob"), "Norwegian Bokmål"},
    {StringToLongCode("nso"), "Sepedi"},
    {StringToLongCode("nso"), "Northern Sotho"},
    {StringToLongCode("nso"), "Sotho, Northern"}, // Kodi addition - consistency with code 'sot'
    {StringToLongCode("nwc"), "Old Newari"},
    {StringToLongCode("nwc"), "Classical Nepal Bhasa"},
    {StringToLongCode("nya"), "Chewa"},
    {StringToLongCode("nya"), "Nyanja"},
    {StringToLongCode("oci"), "Provençal"}, // Kodi addition
    {StringToLongCode("oss"), "Ossetic"},
    {StringToLongCode("pam"), "Kapampangan"},
    {StringToLongCode("pan"), "Punjabi"},
    {StringToLongCode("pro"), "Old Occitan (to 1500)"},
    {StringToLongCode("pus"), "Pashto"},
    {StringToLongCode("rar"), "Cook Islands Maori"},
    {StringToLongCode("ron"), "Moldavian"},
    {StringToLongCode("ron"), "Moldovan"},
    {StringToLongCode("rup"), "Arumanian"},
    {StringToLongCode("rup"), "Macedo-Romanian"},
    {StringToLongCode("sin"), "Sinhalese"},
    {StringToLongCode("spa"), "Castilian"},
    {StringToLongCode("tlh"), "tlhIngan-Hol"},
    {StringToLongCode("uig"), "Uyghur"},
    {StringToLongCode("wal"), "Wolaytta"},
    {StringToLongCode("xal"), "Oirat"},
    {StringToLongCode("zbl"), "Blissymbolics"},
    {StringToLongCode("zbl"), "Bliss"},
    {StringToLongCode("zha"), "Chuang"},
    {StringToLongCode("zxx"), "Not applicable"},
    {StringToLongCode("zza"), "Dimili"},
    {StringToLongCode("zza"), "Dimli"},
    {StringToLongCode("zza"), "Kirdki"},
    {StringToLongCode("zza"), "Kirmanjki"},
    {StringToLongCode("zza"), "Zazaki"},
}};
// clang-format on

static_assert(std::ranges::is_sorted(TableISO639_2_Names, {}, &LCENTRY::code));

static_assert(std::ranges::all_of(
    TableISO639_2_Names,
    [](std::string_view name) { return StringUtils::IsAsciiTrimmed(name); },
    &LCENTRY::name));

// 20 pairs of active ISO 639-2/T and /B codes and 2 inactive pairs (deprecated B codes)
inline static constexpr int ISO639_2_TB_COUNT = 22;

// clang-format off
inline constexpr std::array<ISO639_2_TB, ISO639_2_TB_COUNT> ISO639_2_TB_Mappings = {{
    {StringToLongCode("bod"), StringToLongCode("tib")},
    {StringToLongCode("ces"), StringToLongCode("cze")},
    {StringToLongCode("cym"), StringToLongCode("wel")},
    {StringToLongCode("deu"), StringToLongCode("ger")},
    {StringToLongCode("ell"), StringToLongCode("gre")},
    {StringToLongCode("eus"), StringToLongCode("baq")},
    {StringToLongCode("fas"), StringToLongCode("per")},
    {StringToLongCode("fra"), StringToLongCode("fre")},
    {StringToLongCode("hrv"), StringToLongCode("scr")}, // 2008-06-28 scr was deprecated. The T code remains.
    {StringToLongCode("hye"), StringToLongCode("arm")},
    {StringToLongCode("isl"), StringToLongCode("ice")},
    {StringToLongCode("kat"), StringToLongCode("geo")},
    {StringToLongCode("mkd"), StringToLongCode("mac")},
    {StringToLongCode("mri"), StringToLongCode("mao")},
    {StringToLongCode("msa"), StringToLongCode("may")},
    {StringToLongCode("mya"), StringToLongCode("bur")},
    {StringToLongCode("nld"), StringToLongCode("dut")},
    {StringToLongCode("ron"), StringToLongCode("rum")},
    {StringToLongCode("slk"), StringToLongCode("slo")},
    {StringToLongCode("sqi"), StringToLongCode("alb")},
    {StringToLongCode("srp"), StringToLongCode("scc")}, // 2008-06-28 scc was deprecated. The T code remains.
    {StringToLongCode("zho"), StringToLongCode("chi")},
}};
// clang-format on

static_assert(std::ranges::is_sorted(ISO639_2_TB_Mappings, {}, &ISO639_2_TB::terminological));

constexpr auto CreateTBMappingsByB()
{
  auto codes{ISO639_2_TB_Mappings};
  std::ranges::sort(codes, {}, &ISO639_2_TB::bibliographic);
  return codes;
}

inline constexpr auto ISO639_2_TB_MappingsByB = CreateTBMappingsByB();

//-------------------------------------------------------------------------------------------------
// Data integrity validations
//

static_assert(std::ranges::adjacent_find(TableISO639_2ByCode, {}, &LCENTRY::code) ==
              TableISO639_2ByCode.end());

static_assert(std::ranges::adjacent_find(ISO639_2_TB_Mappings, {}, &ISO639_2_TB::terminological) ==
              ISO639_2_TB_Mappings.end());

static_assert(std::ranges::adjacent_find(ISO639_2_TB_MappingsByB,
                                         {},
                                         &ISO639_2_TB::bibliographic) ==
              ISO639_2_TB_MappingsByB.end());

// All of the codes of the additional English names must exist in the main table
static_assert(std::ranges::all_of(
    TableISO639_2_Names,
    [](auto tCode)
    { return std::ranges::binary_search(TableISO639_2ByCode, tCode, {}, &LCENTRY::code); },
    &LCENTRY::code));

// Not possible to check at compile time the existence of duplicate names in the main table
// or names of the main table duplicated as additional names - exceeds typical constexpr step limits
// Checked at runtime instead.

// All T codes of tb mapping must exist in the main ISO 639-2 table
static_assert(std::ranges::all_of(
    ISO639_2_TB_Mappings,
    [](auto tCode)
    { return std::ranges::binary_search(TableISO639_2ByCode, tCode, {}, &LCENTRY::code); },
    &ISO639_2_TB::terminological));

// None of the B codes can exist as T code of the main ISO 639-2 table
static_assert(std::ranges::none_of(
    ISO639_2_TB_Mappings,
    [](auto bCode)
    { return std::ranges::binary_search(TableISO639_2ByCode, bCode, {}, &LCENTRY::code); },
    &ISO639_2_TB::bibliographic));

// None of the B codes are mapped T codes
static_assert(std::ranges::none_of(
    ISO639_2_TB_Mappings,
    [](auto bCode)
    {
      return std::ranges::binary_search(ISO639_2_TB_Mappings, bCode, {},
                                        &ISO639_2_TB::terminological);
    },
    &ISO639_2_TB::bibliographic));

// The T codes of all additional name entries exist in the main ISO 639-2 table
static_assert(std::ranges::all_of(
    TableISO639_2_Names,
    [](auto tCode)
    { return std::ranges::binary_search(TableISO639_2ByCode, tCode, {}, &LCENTRY::code); },
    &LCENTRY::code));

} // namespace KODI::UTILS::I18N
