summaryrefslogtreecommitdiffstats
path: root/xbmc/utils/LangCodeExpander.cpp
diff options
context:
space:
mode:
authormanuel <manuel@mausz.at>2020-10-19 00:52:24 +0200
committermanuel <manuel@mausz.at>2020-10-19 00:52:24 +0200
commitbe933ef2241d79558f91796cc5b3a161f72ebf9c (patch)
treefe3ab2f130e20c99001f2d7a81d610c78c96a3f4 /xbmc/utils/LangCodeExpander.cpp
parent5f8335c1e49ce108ef3481863833c98efa00411b (diff)
downloadkodi-pvr-build-be933ef2241d79558f91796cc5b3a161f72ebf9c.tar.gz
kodi-pvr-build-be933ef2241d79558f91796cc5b3a161f72ebf9c.tar.bz2
kodi-pvr-build-be933ef2241d79558f91796cc5b3a161f72ebf9c.zip
sync with upstream
Diffstat (limited to 'xbmc/utils/LangCodeExpander.cpp')
-rw-r--r--xbmc/utils/LangCodeExpander.cpp1738
1 files changed, 1738 insertions, 0 deletions
diff --git a/xbmc/utils/LangCodeExpander.cpp b/xbmc/utils/LangCodeExpander.cpp
new file mode 100644
index 0000000..bc1e06b
--- /dev/null
+++ b/xbmc/utils/LangCodeExpander.cpp
@@ -0,0 +1,1738 @@
1/*
2 * Copyright (C) 2005-2020 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
8
9#include "LangCodeExpander.h"
10
11#include "utils/StringUtils.h"
12#include "utils/XBMCTinyXML.h"
13
14#include <algorithm>
15#include <array>
16
17#define MAKECODE(a, b, c, d) \
18 ((((long)(a)) << 24) | (((long)(b)) << 16) | (((long)(c)) << 8) | (long)(d))
19#define MAKETWOCHARCODE(a, b) ((((long)(a)) << 8) | (long)(b))
20
21typedef struct LCENTRY
22{
23 long code;
24 const char* name;
25} LCENTRY;
26
27extern const std::array<struct LCENTRY, 186> g_iso639_1;
28extern const std::array<struct LCENTRY, 540> g_iso639_2;
29
30struct ISO639
31{
32 const char* iso639_1;
33 const char* iso639_2b;
34 const char* iso639_2t;
35 const char* win_id;
36};
37
38struct ISO3166_1
39{
40 const char* alpha2;
41 const char* alpha3;
42};
43
44// declared as extern to allow forward declaration
45extern const std::array<ISO639, 190> LanguageCodes;
46extern const std::array<ISO3166_1, 245> RegionCodes;
47
48CLangCodeExpander::CLangCodeExpander() = default;
49
50CLangCodeExpander::~CLangCodeExpander() = default;
51
52void CLangCodeExpander::Clear()
53{
54 m_mapUser.clear();
55}
56
57void CLangCodeExpander::LoadUserCodes(const TiXmlElement* pRootElement)
58{
59 if (pRootElement != NULL)
60 {
61 m_mapUser.clear();
62
63 std::string sShort, sLong;
64
65 const TiXmlNode* pLangCode = pRootElement->FirstChild("code");
66 while (pLangCode != NULL)
67 {
68 const TiXmlNode* pShort = pLangCode->FirstChildElement("short");
69 const TiXmlNode* pLong = pLangCode->FirstChildElement("long");
70 if (pShort != NULL && pLong != NULL)
71 {
72 sShort = pShort->FirstChild()->Value();
73 sLong = pLong->FirstChild()->Value();
74 StringUtils::ToLower(sShort);
75
76 m_mapUser[sShort] = sLong;
77 }
78
79 pLangCode = pLangCode->NextSibling();
80 }
81 }
82}
83
84bool CLangCodeExpander::Lookup(const std::string& code, std::string& desc)
85{
86 int iSplit = code.find("-");
87 if (iSplit > 0)
88 {
89 std::string strLeft, strRight;
90 const bool bLeft = Lookup(code.substr(0, iSplit), strLeft);
91 const bool bRight = Lookup(code.substr(iSplit + 1), strRight);
92 if (bLeft || bRight)
93 {
94 desc = "";
95 if (strLeft.length() > 0)
96 desc = strLeft;
97 else
98 desc = code.substr(0, iSplit);
99
100 if (strRight.length() > 0)
101 {
102 desc += " - ";
103 desc += strRight;
104 }
105 else
106 {
107 desc += " - ";
108 desc += code.substr(iSplit + 1);
109 }
110
111 return true;
112 }
113
114 return false;
115 }
116
117 if (LookupInUserMap(code, desc))
118 return true;
119
120 if (LookupInISO639Tables(code, desc))
121 return true;
122
123 return false;
124}
125
126bool CLangCodeExpander::Lookup(const int code, std::string& desc)
127{
128 char lang[3];
129 lang[2] = 0;
130 lang[1] = (code & 0xFF);
131 lang[0] = (code >> 8) & 0xFF;
132
133 return Lookup(lang, desc);
134}
135
136bool CLangCodeExpander::ConvertISO6391ToISO6392B(const std::string& strISO6391,
137 std::string& strISO6392B,
138 bool checkWin32Locales /*= false*/)
139{
140 // not a 2 char code
141 if (strISO6391.length() != 2)
142 return false;
143
144 std::string strISO6391Lower(strISO6391);
145 StringUtils::ToLower(strISO6391Lower);
146 StringUtils::Trim(strISO6391Lower);
147
148 for (const auto& codes : LanguageCodes)
149 {
150 if (strISO6391Lower == codes.iso639_1)
151 {
152 if (checkWin32Locales && codes.win_id)
153 {
154 strISO6392B = codes.win_id;
155 return true;
156 }
157
158 strISO6392B = codes.iso639_2b;
159 return true;
160 }
161 }
162
163 return false;
164}
165
166bool CLangCodeExpander::ConvertToISO6392B(const std::string& strCharCode,
167 std::string& strISO6392B,
168 bool checkWin32Locales /* = false */)
169{
170
171 //first search in the user defined map
172 if (LookupUserCode(strCharCode, strISO6392B))
173 return true;
174
175 if (strCharCode.size() == 2)
176 return g_LangCodeExpander.ConvertISO6391ToISO6392B(strCharCode, strISO6392B, checkWin32Locales);
177
178 if (strCharCode.size() == 3)
179 {
180 std::string charCode(strCharCode);
181 StringUtils::ToLower(charCode);
182 for (const auto& codes : LanguageCodes)
183 {
184 if (charCode == codes.iso639_2b ||
185 (checkWin32Locales && codes.win_id != NULL && charCode == codes.win_id))
186 {
187 strISO6392B = charCode;
188 return true;
189 }
190 }
191
192 for (const auto& codes : RegionCodes)
193 {
194 if (charCode == codes.alpha3)
195 {
196 strISO6392B = charCode;
197 return true;
198 }
199 }
200 }
201 else if (strCharCode.size() > 3)
202 {
203 for (const auto& codes : g_iso639_2)
204 {
205 if (StringUtils::EqualsNoCase(strCharCode, codes.name))
206 {
207 CodeToString(codes.code, strISO6392B);
208 return true;
209 }
210 }
211 }
212 return false;
213}
214
215bool CLangCodeExpander::ConvertToISO6392T(const std::string& strCharCode,
216 std::string& strISO6392T,
217 bool checkWin32Locales /* = false */)
218{
219 if (!ConvertToISO6392B(strCharCode, strISO6392T, checkWin32Locales))
220 return false;
221
222 for (const auto& codes : LanguageCodes)
223 {
224 if (strISO6392T == codes.iso639_2b ||
225 (checkWin32Locales && codes.win_id != NULL && strISO6392T == codes.win_id))
226 {
227 if (codes.iso639_2t != nullptr)
228 strISO6392T = codes.iso639_2t;
229 return true;
230 }
231 }
232 return false;
233}
234
235
236bool CLangCodeExpander::LookupUserCode(const std::string& desc, std::string& userCode)
237{
238 for (STRINGLOOKUPTABLE::const_iterator it = m_mapUser.begin(); it != m_mapUser.end(); ++it)
239 {
240 if (StringUtils::EqualsNoCase(desc, it->first) || StringUtils::EqualsNoCase(desc, it->second))
241 {
242 userCode = it->first;
243 return true;
244 }
245 }
246 return false;
247}
248
249#ifdef TARGET_WINDOWS
250bool CLangCodeExpander::ConvertISO31661Alpha2ToISO31661Alpha3(const std::string& strISO31661Alpha2,
251 std::string& strISO31661Alpha3)
252{
253 if (strISO31661Alpha2.length() != 2)
254 return false;
255
256 std::string strLower(strISO31661Alpha2);
257 StringUtils::ToLower(strLower);
258 StringUtils::Trim(strLower);
259 for (const auto& codes : RegionCodes)
260 {
261 if (strLower == codes.alpha2)
262 {
263 strISO31661Alpha3 = codes.alpha3;
264 return true;
265 }
266 }
267
268 return true;
269}
270
271bool CLangCodeExpander::ConvertWindowsLanguageCodeToISO6392B(
272 const std::string& strWindowsLanguageCode, std::string& strISO6392B)
273{
274 if (strWindowsLanguageCode.length() != 3)
275 return false;
276
277 std::string strLower(strWindowsLanguageCode);
278 StringUtils::ToLower(strLower);
279 for (const auto& codes : LanguageCodes)
280 {
281 if ((codes.win_id && strLower == codes.win_id) || strLower == codes.iso639_2b)
282 {
283 strISO6392B = codes.iso639_2b;
284 return true;
285 }
286 }
287
288 return false;
289}
290#endif
291
292bool CLangCodeExpander::ConvertToISO6391(const std::string& lang, std::string& code)
293{
294 if (lang.empty())
295 return false;
296
297 //first search in the user defined map
298 if (LookupUserCode(lang, code))
299 return true;
300
301 if (lang.length() == 2)
302 {
303 std::string tmp;
304 if (Lookup(lang, tmp))
305 {
306 code = lang;
307 return true;
308 }
309 }
310 else if (lang.length() == 3)
311 {
312 std::string lower(lang);
313 StringUtils::ToLower(lower);
314 for (const auto& codes : LanguageCodes)
315 {
316 if (lower == codes.iso639_2b || (codes.win_id && lower == codes.win_id))
317 {
318 code = codes.iso639_1;
319 return true;
320 }
321 }
322
323 for (const auto& codes : RegionCodes)
324 {
325 if (lower == codes.alpha3)
326 {
327 code = codes.alpha2;
328 return true;
329 }
330 }
331 }
332
333 // check if lang is full language name
334 std::string tmp;
335 if (ReverseLookup(lang, tmp))
336 {
337 if (tmp.length() == 2)
338 {
339 code = tmp;
340 return true;
341 }
342
343 if (tmp.length() == 3)
344 {
345 // there's only an iso639-2 code that is identical to the language name, e.g. Yao
346 if (StringUtils::EqualsNoCase(tmp, lang))
347 return false;
348
349 return ConvertToISO6391(tmp, code);
350 }
351 }
352
353 return false;
354}
355
356bool CLangCodeExpander::ReverseLookup(const std::string& desc, std::string& code)
357{
358 if (desc.empty())
359 return false;
360
361 std::string descTmp(desc);
362 StringUtils::Trim(descTmp);
363 for (STRINGLOOKUPTABLE::const_iterator it = m_mapUser.begin(); it != m_mapUser.end(); ++it)
364 {
365 if (StringUtils::EqualsNoCase(descTmp, it->second))
366 {
367 code = it->first;
368 return true;
369 }
370 }
371
372 for (const auto& codes : g_iso639_1)
373 {
374 if (StringUtils::EqualsNoCase(descTmp, codes.name))
375 {
376 CodeToString(codes.code, code);
377 return true;
378 }
379 }
380
381 for (const auto& codes : g_iso639_2)
382 {
383 if (StringUtils::EqualsNoCase(descTmp, codes.name))
384 {
385 CodeToString(codes.code, code);
386 return true;
387 }
388 }
389
390 return false;
391}
392
393bool CLangCodeExpander::LookupInUserMap(const std::string& code, std::string& desc)
394{
395 if (code.empty())
396 return false;
397
398 // make sure we convert to lowercase before trying to find it
399 std::string sCode(code);
400 StringUtils::ToLower(sCode);
401 StringUtils::Trim(sCode);
402
403 STRINGLOOKUPTABLE::iterator it = m_mapUser.find(sCode);
404 if (it != m_mapUser.end())
405 {
406 desc = it->second;
407 return true;
408 }
409
410 return false;
411}
412
413bool CLangCodeExpander::LookupInISO639Tables(const std::string& code, std::string& desc)
414{
415 if (code.empty())
416 return false;
417
418 long longcode;
419 std::string sCode(code);
420 StringUtils::ToLower(sCode);
421 StringUtils::Trim(sCode);
422
423 if (sCode.length() == 2)
424 {
425 longcode = MAKECODE('\0', '\0', sCode[0], sCode[1]);
426 for (const auto& codes : g_iso639_1)
427 {
428 if (codes.code == longcode)
429 {
430 desc = codes.name;
431 return true;
432 }
433 }
434 }
435 else if (sCode.length() == 3)
436 {
437 longcode = MAKECODE('\0', sCode[0], sCode[1], sCode[2]);
438 for (const auto& codes : g_iso639_2)
439 {
440 if (codes.code == longcode)
441 {
442 desc = codes.name;
443 return true;
444 }
445 }
446 }
447 return false;
448}
449
450void CLangCodeExpander::CodeToString(long code, std::string& ret)
451{
452 ret.clear();
453 for (unsigned int j = 0; j < 4; j++)
454 {
455 char c = (char)code & 0xFF;
456 if (c == '\0')
457 return;
458
459 ret.insert(0, 1, c);
460 code >>= 8;
461 }
462}
463
464bool CLangCodeExpander::CompareFullLanguageNames(const std::string& lang1, const std::string& lang2)
465{
466 if (StringUtils::EqualsNoCase(lang1, lang2))
467 return true;
468
469 std::string expandedLang1, expandedLang2, code1, code2;
470
471 if (!ReverseLookup(lang1, code1))
472 return false;
473
474 code1 = lang1;
475 if (!ReverseLookup(lang2, code2))
476 return false;
477
478 code2 = lang2;
479 Lookup(expandedLang1, code1);
480 Lookup(expandedLang2, code2);
481
482 return StringUtils::EqualsNoCase(expandedLang1, expandedLang2);
483}
484
485std::vector<std::string> CLangCodeExpander::GetLanguageNames(
486 LANGFORMATS format /* = CLangCodeExpander::ISO_639_1 */, bool customNames /* = false */)
487{
488 std::vector<std::string> languages;
489
490 if (format == CLangCodeExpander::ISO_639_2)
491 std::transform(g_iso639_2.begin(), g_iso639_2.end(), std::back_inserter(languages),
492 [](const LCENTRY& e) { return e.name; });
493 else
494 std::transform(g_iso639_1.begin(), g_iso639_1.end(), std::back_inserter(languages),
495 [](const LCENTRY& e) { return e.name; });
496
497 if (customNames)
498 std::transform(m_mapUser.begin(), m_mapUser.end(), std::back_inserter(languages),
499 [](const STRINGLOOKUPTABLE::value_type& e) { return e.second; });
500
501 return languages;
502}
503
504bool CLangCodeExpander::CompareISO639Codes(const std::string& code1, const std::string& code2)
505{
506 if (StringUtils::EqualsNoCase(code1, code2))
507 return true;
508
509 std::string expandedLang1;
510 if (!Lookup(code1, expandedLang1))
511 return false;
512
513 std::string expandedLang2;
514 if (!Lookup(code2, expandedLang2))
515 return false;
516
517 return StringUtils::EqualsNoCase(expandedLang1, expandedLang2);
518}
519
520std::string CLangCodeExpander::ConvertToISO6392B(const std::string& lang)
521{
522 if (lang.empty())
523 return lang;
524
525 std::string two, three;
526 if (ConvertToISO6391(lang, two))
527 {
528 if (ConvertToISO6392B(two, three))
529 return three;
530 }
531
532 return lang;
533}
534
535std::string CLangCodeExpander::ConvertToISO6392T(const std::string& lang)
536{
537 if (lang.empty())
538 return lang;
539
540 std::string two, three;
541 if (ConvertToISO6391(lang, two))
542 {
543 if (ConvertToISO6392T(two, three))
544 return three;
545 }
546
547 return lang;
548}
549
550// clang-format off
551const std::array<struct LCENTRY, 186> g_iso639_1 = {{
552 {MAKECODE('\0', '\0', 'a', 'a'), "Afar"},
553 {MAKECODE('\0', '\0', 'a', 'b'), "Abkhazian"},
554 {MAKECODE('\0', '\0', 'a', 'e'), "Avestan"},
555 {MAKECODE('\0', '\0', 'a', 'f'), "Afrikaans"},
556 {MAKECODE('\0', '\0', 'a', 'k'), "Akan"},
557 {MAKECODE('\0', '\0', 'a', 'm'), "Amharic"},
558 {MAKECODE('\0', '\0', 'a', 'n'), "Aragonese"},
559 {MAKECODE('\0', '\0', 'a', 'r'), "Arabic"},
560 {MAKECODE('\0', '\0', 'a', 's'), "Assamese"},
561 {MAKECODE('\0', '\0', 'a', 'v'), "Avaric"},
562 {MAKECODE('\0', '\0', 'a', 'y'), "Aymara"},
563 {MAKECODE('\0', '\0', 'a', 'z'), "Azerbaijani"},
564 {MAKECODE('\0', '\0', 'b', 'a'), "Bashkir"},
565 {MAKECODE('\0', '\0', 'b', 'e'), "Belarusian"},
566 {MAKECODE('\0', '\0', 'b', 'g'), "Bulgarian"},
567 {MAKECODE('\0', '\0', 'b', 'h'), "Bihari"},
568 {MAKECODE('\0', '\0', 'b', 'i'), "Bislama"},
569 {MAKECODE('\0', '\0', 'b', 'm'), "Bambara"},
570 {MAKECODE('\0', '\0', 'b', 'n'), "Bengali; Bangla"},
571 {MAKECODE('\0', '\0', 'b', 'o'), "Tibetan"},
572 {MAKECODE('\0', '\0', 'b', 'r'), "Breton"},
573 {MAKECODE('\0', '\0', 'b', 's'), "Bosnian"},
574 {MAKECODE('\0', '\0', 'c', 'a'), "Catalan"},
575 {MAKECODE('\0', '\0', 'c', 'e'), "Chechen"},
576 {MAKECODE('\0', '\0', 'c', 'h'), "Chamorro"},
577 {MAKECODE('\0', '\0', 'c', 'o'), "Corsican"},
578 {MAKECODE('\0', '\0', 'c', 'r'), "Cree"},
579 {MAKECODE('\0', '\0', 'c', 's'), "Czech"},
580 {MAKECODE('\0', '\0', 'c', 'u'), "Church Slavic"},
581 {MAKECODE('\0', '\0', 'c', 'v'), "Chuvash"},
582 {MAKECODE('\0', '\0', 'c', 'y'), "Welsh"},
583 {MAKECODE('\0', '\0', 'd', 'a'), "Danish"},
584 {MAKECODE('\0', '\0', 'd', 'e'), "German"},
585 {MAKECODE('\0', '\0', 'd', 'v'), "Dhivehi"},
586 {MAKECODE('\0', '\0', 'd', 'z'), "Dzongkha"},
587 {MAKECODE('\0', '\0', 'e', 'e'), "Ewe"},
588 {MAKECODE('\0', '\0', 'e', 'l'), "Greek"},
589 {MAKECODE('\0', '\0', 'e', 'n'), "English"},
590 {MAKECODE('\0', '\0', 'e', 'o'), "Esperanto"},
591 {MAKECODE('\0', '\0', 'e', 's'), "Spanish"},
592 {MAKECODE('\0', '\0', 'e', 't'), "Estonian"},
593 {MAKECODE('\0', '\0', 'e', 'u'), "Basque"},
594 {MAKECODE('\0', '\0', 'f', 'a'), "Persian"},
595 {MAKECODE('\0', '\0', 'f', 'f'), "Fulah"},
596 {MAKECODE('\0', '\0', 'f', 'i'), "Finnish"},
597 {MAKECODE('\0', '\0', 'f', 'j'), "Fijian"},
598 {MAKECODE('\0', '\0', 'f', 'o'), "Faroese"},
599 {MAKECODE('\0', '\0', 'f', 'r'), "French"},
600 {MAKECODE('\0', '\0', 'f', 'y'), "Western Frisian"},
601 {MAKECODE('\0', '\0', 'g', 'a'), "Irish"},
602 {MAKECODE('\0', '\0', 'g', 'd'), "Scottish Gaelic"},
603 {MAKECODE('\0', '\0', 'g', 'l'), "Galician"},
604 {MAKECODE('\0', '\0', 'g', 'n'), "Guarani"},
605 {MAKECODE('\0', '\0', 'g', 'u'), "Gujarati"},
606 {MAKECODE('\0', '\0', 'g', 'v'), "Manx"},
607 {MAKECODE('\0', '\0', 'h', 'a'), "Hausa"},
608 {MAKECODE('\0', '\0', 'h', 'e'), "Hebrew"},
609 {MAKECODE('\0', '\0', 'h', 'i'), "Hindi"},
610 {MAKECODE('\0', '\0', 'h', 'o'), "Hiri Motu"},
611 {MAKECODE('\0', '\0', 'h', 'r'), "Croatian"},
612 {MAKECODE('\0', '\0', 'h', 't'), "Haitian"},
613 {MAKECODE('\0', '\0', 'h', 'u'), "Hungarian"},
614 {MAKECODE('\0', '\0', 'h', 'y'), "Armenian"},
615 {MAKECODE('\0', '\0', 'h', 'z'), "Herero"},
616 {MAKECODE('\0', '\0', 'i', 'a'), "Interlingua"},
617 {MAKECODE('\0', '\0', 'i', 'd'), "Indonesian"},
618 {MAKECODE('\0', '\0', 'i', 'e'), "Interlingue"},
619 {MAKECODE('\0', '\0', 'i', 'g'), "Igbo"},
620 {MAKECODE('\0', '\0', 'i', 'i'), "Sichuan Yi"},
621 {MAKECODE('\0', '\0', 'i', 'k'), "Inupiat"},
622 {MAKECODE('\0', '\0', 'i', 'o'), "Ido"},
623 {MAKECODE('\0', '\0', 'i', 's'), "Icelandic"},
624 {MAKECODE('\0', '\0', 'i', 't'), "Italian"},
625 {MAKECODE('\0', '\0', 'i', 'u'), "Inuktitut"},
626 {MAKECODE('\0', '\0', 'j', 'a'), "Japanese"},
627 {MAKECODE('\0', '\0', 'j', 'v'), "Javanese"},
628 {MAKECODE('\0', '\0', 'k', 'a'), "Georgian"},
629 {MAKECODE('\0', '\0', 'k', 'g'), "Kongo"},
630 {MAKECODE('\0', '\0', 'k', 'i'), "Kikuyu"},
631 {MAKECODE('\0', '\0', 'k', 'j'), "Kuanyama"},
632 {MAKECODE('\0', '\0', 'k', 'k'), "Kazakh"},
633 {MAKECODE('\0', '\0', 'k', 'l'), "Kalaallisut"},
634 {MAKECODE('\0', '\0', 'k', 'm'), "Khmer"},
635 {MAKECODE('\0', '\0', 'k', 'n'), "Kannada"},
636 {MAKECODE('\0', '\0', 'k', 'o'), "Korean"},
637 {MAKECODE('\0', '\0', 'k', 'r'), "Kanuri"},
638 {MAKECODE('\0', '\0', 'k', 's'), "Kashmiri"},
639 {MAKECODE('\0', '\0', 'k', 'u'), "Kurdish"},
640 {MAKECODE('\0', '\0', 'k', 'v'), "Komi"},
641 {MAKECODE('\0', '\0', 'k', 'w'), "Cornish"},
642 {MAKECODE('\0', '\0', 'k', 'y'), "Kirghiz"},
643 {MAKECODE('\0', '\0', 'l', 'a'), "Latin"},
644 {MAKECODE('\0', '\0', 'l', 'b'), "Luxembourgish"},
645 {MAKECODE('\0', '\0', 'l', 'g'), "Ganda"},
646 {MAKECODE('\0', '\0', 'l', 'i'), "Limburgan"},
647 {MAKECODE('\0', '\0', 'l', 'n'), "Lingala"},
648 {MAKECODE('\0', '\0', 'l', 'o'), "Lao"},
649 {MAKECODE('\0', '\0', 'l', 't'), "Lithuanian"},
650 {MAKECODE('\0', '\0', 'l', 'u'), "Luba-Katanga"},
651 {MAKECODE('\0', '\0', 'l', 'v'), "Latvian, Lettish"},
652 {MAKECODE('\0', '\0', 'm', 'g'), "Malagasy"},
653 {MAKECODE('\0', '\0', 'm', 'h'), "Marshallese"},
654 {MAKECODE('\0', '\0', 'm', 'i'), "Maori"},
655 {MAKECODE('\0', '\0', 'm', 'k'), "Macedonian"},
656 {MAKECODE('\0', '\0', 'm', 'l'), "Malayalam"},
657 {MAKECODE('\0', '\0', 'm', 'n'), "Mongolian"},
658 {MAKECODE('\0', '\0', 'm', 'r'), "Marathi"},
659 {MAKECODE('\0', '\0', 'm', 's'), "Malay"},
660 {MAKECODE('\0', '\0', 'm', 't'), "Maltese"},
661 {MAKECODE('\0', '\0', 'm', 'y'), "Burmese"},
662 {MAKECODE('\0', '\0', 'n', 'a'), "Nauru"},
663 {MAKECODE('\0', '\0', 'n', 'b'), "Norwegian Bokm\xC3\xA5l"},
664 {MAKECODE('\0', '\0', 'n', 'd'), "Ndebele, North"},
665 {MAKECODE('\0', '\0', 'n', 'e'), "Nepali"},
666 {MAKECODE('\0', '\0', 'n', 'g'), "Ndonga"},
667 {MAKECODE('\0', '\0', 'n', 'l'), "Dutch"},
668 {MAKECODE('\0', '\0', 'n', 'n'), "Norwegian Nynorsk"},
669 {MAKECODE('\0', '\0', 'n', 'o'), "Norwegian"},
670 {MAKECODE('\0', '\0', 'n', 'r'), "Ndebele, South"},
671 {MAKECODE('\0', '\0', 'n', 'v'), "Navajo"},
672 {MAKECODE('\0', '\0', 'n', 'y'), "Chichewa"},
673 {MAKECODE('\0', '\0', 'o', 'c'), "Occitan"},
674 {MAKECODE('\0', '\0', 'o', 'j'), "Ojibwa"},
675 {MAKECODE('\0', '\0', 'o', 'm'), "Oromo"},
676 {MAKECODE('\0', '\0', 'o', 'r'), "Oriya"},
677 {MAKECODE('\0', '\0', 'o', 's'), "Ossetic"},
678 {MAKECODE('\0', '\0', 'p', 'a'), "Punjabi"},
679 {MAKECODE('\0', '\0', 'p', 'i'), "Pali"},
680 {MAKECODE('\0', '\0', 'p', 'l'), "Polish"},
681 {MAKECODE('\0', '\0', 'p', 's'), "Pashto, Pushto"},
682 {MAKECODE('\0', '\0', 'p', 't'), "Portuguese"},
683 // pb = unofficial language code for Brazilian Portuguese
684 {MAKECODE('\0', '\0', 'p', 'b'), "Portuguese (Brazil)"},
685 {MAKECODE('\0', '\0', 'q', 'u'), "Quechua"},
686 {MAKECODE('\0', '\0', 'r', 'm'), "Romansh"},
687 {MAKECODE('\0', '\0', 'r', 'n'), "Kirundi"},
688 {MAKECODE('\0', '\0', 'r', 'o'), "Romanian"},
689 {MAKECODE('\0', '\0', 'r', 'u'), "Russian"},
690 {MAKECODE('\0', '\0', 'r', 'w'), "Kinyarwanda"},
691 {MAKECODE('\0', '\0', 's', 'a'), "Sanskrit"},
692 {MAKECODE('\0', '\0', 's', 'c'), "Sardinian"},
693 {MAKECODE('\0', '\0', 's', 'd'), "Sindhi"},
694 {MAKECODE('\0', '\0', 's', 'e'), "Northern Sami"},
695 {MAKECODE('\0', '\0', 's', 'g'), "Sangho"},
696 {MAKECODE('\0', '\0', 's', 'h'), "Serbo-Croatian"},
697 {MAKECODE('\0', '\0', 's', 'i'), "Sinhalese"},
698 {MAKECODE('\0', '\0', 's', 'k'), "Slovak"},
699 {MAKECODE('\0', '\0', 's', 'l'), "Slovenian"},
700 {MAKECODE('\0', '\0', 's', 'm'), "Samoan"},
701 {MAKECODE('\0', '\0', 's', 'n'), "Shona"},
702 {MAKECODE('\0', '\0', 's', 'o'), "Somali"},
703 {MAKECODE('\0', '\0', 's', 'q'), "Albanian"},
704 {MAKECODE('\0', '\0', 's', 'r'), "Serbian"},
705 {MAKECODE('\0', '\0', 's', 's'), "Swati"},
706 {MAKECODE('\0', '\0', 's', 't'), "Sesotho"},
707 {MAKECODE('\0', '\0', 's', 'u'), "Sundanese"},
708 {MAKECODE('\0', '\0', 's', 'v'), "Swedish"},
709 {MAKECODE('\0', '\0', 's', 'w'), "Swahili"},
710 {MAKECODE('\0', '\0', 't', 'a'), "Tamil"},
711 {MAKECODE('\0', '\0', 't', 'e'), "Telugu"},
712 {MAKECODE('\0', '\0', 't', 'g'), "Tajik"},
713 {MAKECODE('\0', '\0', 't', 'h'), "Thai"},
714 {MAKECODE('\0', '\0', 't', 'i'), "Tigrinya"},
715 {MAKECODE('\0', '\0', 't', 'k'), "Turkmen"},
716 {MAKECODE('\0', '\0', 't', 'l'), "Tagalog"},
717 {MAKECODE('\0', '\0', 't', 'n'), "Tswana"},
718 {MAKECODE('\0', '\0', 't', 'o'), "Tonga"},
719 {MAKECODE('\0', '\0', 't', 'r'), "Turkish"},
720 {MAKECODE('\0', '\0', 't', 's'), "Tsonga"},
721 {MAKECODE('\0', '\0', 't', 't'), "Tatar"},
722 {MAKECODE('\0', '\0', 't', 'w'), "Twi"},
723 {MAKECODE('\0', '\0', 't', 'y'), "Tahitian"},
724 {MAKECODE('\0', '\0', 'u', 'g'), "Uighur"},
725 {MAKECODE('\0', '\0', 'u', 'k'), "Ukrainian"},
726 {MAKECODE('\0', '\0', 'u', 'r'), "Urdu"},
727 {MAKECODE('\0', '\0', 'u', 'z'), "Uzbek"},
728 {MAKECODE('\0', '\0', 'v', 'e'), "Venda"},
729 {MAKECODE('\0', '\0', 'v', 'i'), "Vietnamese"},
730 {MAKECODE('\0', '\0', 'v', 'o'), "Volapuk"},
731 {MAKECODE('\0', '\0', 'w', 'a'), "Walloon"},
732 {MAKECODE('\0', '\0', 'w', 'o'), "Wolof"},
733 {MAKECODE('\0', '\0', 'x', 'h'), "Xhosa"},
734 {MAKECODE('\0', '\0', 'y', 'i'), "Yiddish"},
735 {MAKECODE('\0', '\0', 'y', 'o'), "Yoruba"},
736 {MAKECODE('\0', '\0', 'z', 'a'), "Zhuang"},
737 {MAKECODE('\0', '\0', 'z', 'h'), "Chinese"},
738 {MAKECODE('\0', '\0', 'z', 'u'), "Zulu"},
739}};
740// clang-format on
741
742// clang-format off
743const std::array<struct LCENTRY, 540> g_iso639_2 = {{
744 {MAKECODE('\0', 'a', 'b', 'k'), "Abkhaz"},
745 {MAKECODE('\0', 'a', 'b', 'k'), "Abkhazian"},
746 {MAKECODE('\0', 'a', 'c', 'e'), "Achinese"},
747 {MAKECODE('\0', 'a', 'c', 'h'), "Acoli"},
748 {MAKECODE('\0', 'a', 'd', 'a'), "Adangme"},
749 {MAKECODE('\0', 'a', 'd', 'y'), "Adygei"},
750 {MAKECODE('\0', 'a', 'd', 'y'), "Adyghe"},
751 {MAKECODE('\0', 'a', 'a', 'r'), "Afar"},
752 {MAKECODE('\0', 'a', 'f', 'h'), "Afrihili"},
753 {MAKECODE('\0', 'a', 'f', 'r'), "Afrikaans"},
754 {MAKECODE('\0', 'a', 'f', 'a'), "Afro-Asiatic (Other)"},
755 {MAKECODE('\0', 'a', 'k', 'a'), "Akan"},
756 {MAKECODE('\0', 'a', 'k', 'k'), "Akkadian"},
757 {MAKECODE('\0', 'a', 'l', 'b'), "Albanian"},
758 {MAKECODE('\0', 's', 'q', 'i'), "Albanian"},
759 {MAKECODE('\0', 'a', 'l', 'e'), "Aleut"},
760 {MAKECODE('\0', 'a', 'l', 'g'), "Algonquian languages"},
761 {MAKECODE('\0', 't', 'u', 't'), "Altaic (Other)"},
762 {MAKECODE('\0', 'a', 'm', 'h'), "Amharic"},
763 {MAKECODE('\0', 'a', 'p', 'a'), "Apache languages"},
764 {MAKECODE('\0', 'a', 'r', 'a'), "Arabic"},
765 {MAKECODE('\0', 'a', 'r', 'g'), "Aragonese"},
766 {MAKECODE('\0', 'a', 'r', 'c'), "Aramaic"},
767 {MAKECODE('\0', 'a', 'r', 'p'), "Arapaho"},
768 {MAKECODE('\0', 'a', 'r', 'n'), "Araucanian"},
769 {MAKECODE('\0', 'a', 'r', 'w'), "Arawak"},
770 {MAKECODE('\0', 'a', 'r', 'm'), "Armenian"},
771 {MAKECODE('\0', 'h', 'y', 'e'), "Armenian"},
772 {MAKECODE('\0', 'a', 'r', 't'), "Artificial (Other)"},
773 {MAKECODE('\0', 'a', 's', 'm'), "Assamese"},
774 {MAKECODE('\0', 'a', 's', 't'), "Asturian"},
775 {MAKECODE('\0', 'a', 't', 'h'), "Athapascan languages"},
776 {MAKECODE('\0', 'a', 'u', 's'), "Australian languages"},
777 {MAKECODE('\0', 'm', 'a', 'p'), "Austronesian (Other)"},
778 {MAKECODE('\0', 'a', 'v', 'a'), "Avaric"},
779 {MAKECODE('\0', 'a', 'v', 'e'), "Avestan"},
780 {MAKECODE('\0', 'a', 'w', 'a'), "Awadhi"},
781 {MAKECODE('\0', 'a', 'y', 'm'), "Aymara"},
782 {MAKECODE('\0', 'a', 'z', 'e'), "Azerbaijani"},
783 {MAKECODE('\0', 'a', 's', 't'), "Bable"},
784 {MAKECODE('\0', 'b', 'a', 'n'), "Balinese"},
785 {MAKECODE('\0', 'b', 'a', 't'), "Baltic (Other)"},
786 {MAKECODE('\0', 'b', 'a', 'l'), "Baluchi"},
787 {MAKECODE('\0', 'b', 'a', 'm'), "Bambara"},
788 {MAKECODE('\0', 'b', 'a', 'i'), "Bamileke languages"},
789 {MAKECODE('\0', 'b', 'a', 'd'), "Banda"},
790 {MAKECODE('\0', 'b', 'n', 't'), "Bantu (Other)"},
791 {MAKECODE('\0', 'b', 'a', 's'), "Basa"},
792 {MAKECODE('\0', 'b', 'a', 'k'), "Bashkir"},
793 {MAKECODE('\0', 'b', 'a', 'q'), "Basque"},
794 {MAKECODE('\0', 'e', 'u', 's'), "Basque"},
795 {MAKECODE('\0', 'b', 't', 'k'), "Batak (Indonesia)"},
796 {MAKECODE('\0', 'b', 'e', 'j'), "Beja"},
797 {MAKECODE('\0', 'b', 'e', 'l'), "Belarusian"},
798 {MAKECODE('\0', 'b', 'e', 'm'), "Bemba"},
799 {MAKECODE('\0', 'b', 'e', 'n'), "Bengali"},
800 {MAKECODE('\0', 'b', 'e', 'r'), "Berber (Other)"},
801 {MAKECODE('\0', 'b', 'h', 'o'), "Bhojpuri"},
802 {MAKECODE('\0', 'b', 'i', 'h'), "Bihari"},
803 {MAKECODE('\0', 'b', 'i', 'k'), "Bikol"},
804 {MAKECODE('\0', 'b', 'y', 'n'), "Bilin"},
805 {MAKECODE('\0', 'b', 'i', 'n'), "Bini"},
806 {MAKECODE('\0', 'b', 'i', 's'), "Bislama"},
807 {MAKECODE('\0', 'b', 'y', 'n'), "Blin"},
808 {MAKECODE('\0', 'n', 'o', 'b'), "Bokm\xC3\xA5l, Norwegian"},
809 {MAKECODE('\0', 'b', 'o', 's'), "Bosnian"},
810 {MAKECODE('\0', 'b', 'r', 'a'), "Braj"},
811 {MAKECODE('\0', 'b', 'r', 'e'), "Breton"},
812 {MAKECODE('\0', 'b', 'u', 'g'), "Buginese"},
813 {MAKECODE('\0', 'b', 'u', 'l'), "Bulgarian"},
814 {MAKECODE('\0', 'b', 'u', 'a'), "Buriat"},
815 {MAKECODE('\0', 'b', 'u', 'r'), "Burmese"},
816 {MAKECODE('\0', 'm', 'y', 'a'), "Burmese"},
817 {MAKECODE('\0', 'c', 'a', 'd'), "Caddo"},
818 {MAKECODE('\0', 'c', 'a', 'r'), "Carib"},
819 {MAKECODE('\0', 's', 'p', 'a'), "Spanish"},
820 {MAKECODE('\0', 'c', 'a', 't'), "Catalan"},
821 {MAKECODE('\0', 'c', 'a', 'u'), "Caucasian (Other)"},
822 {MAKECODE('\0', 'c', 'e', 'b'), "Cebuano"},
823 {MAKECODE('\0', 'c', 'e', 'l'), "Celtic (Other)"},
824 {MAKECODE('\0', 'c', 'h', 'g'), "Chagatai"},
825 {MAKECODE('\0', 'c', 'm', 'c'), "Chamic languages"},
826 {MAKECODE('\0', 'c', 'h', 'a'), "Chamorro"},
827 {MAKECODE('\0', 'c', 'h', 'e'), "Chechen"},
828 {MAKECODE('\0', 'c', 'h', 'r'), "Cherokee"},
829 {MAKECODE('\0', 'n', 'y', 'a'), "Chewa"},
830 {MAKECODE('\0', 'c', 'h', 'y'), "Cheyenne"},
831 {MAKECODE('\0', 'c', 'h', 'b'), "Chibcha"},
832 {MAKECODE('\0', 'n', 'y', 'a'), "Chichewa"},
833 {MAKECODE('\0', 'c', 'h', 'i'), "Chinese"},
834 {MAKECODE('\0', 'z', 'h', 'o'), "Chinese"},
835 {MAKECODE('\0', 'c', 'h', 'n'), "Chinook jargon"},
836 {MAKECODE('\0', 'c', 'h', 'p'), "Chipewyan"},
837 {MAKECODE('\0', 'c', 'h', 'o'), "Choctaw"},
838 {MAKECODE('\0', 'z', 'h', 'a'), "Chuang"},
839 {MAKECODE('\0', 'c', 'h', 'u'), "Church Slavonic"},
840 {MAKECODE('\0', 'c', 'h', 'k'), "Chuukese"},
841 {MAKECODE('\0', 'c', 'h', 'v'), "Chuvash"},
842 {MAKECODE('\0', 'n', 'w', 'c'), "Classical Nepal Bhasa"},
843 {MAKECODE('\0', 'n', 'w', 'c'), "Classical Newari"},
844 {MAKECODE('\0', 'c', 'o', 'p'), "Coptic"},
845 {MAKECODE('\0', 'c', 'o', 'r'), "Cornish"},
846 {MAKECODE('\0', 'c', 'o', 's'), "Corsican"},
847 {MAKECODE('\0', 'c', 'r', 'e'), "Cree"},
848 {MAKECODE('\0', 'm', 'u', 's'), "Creek"},
849 {MAKECODE('\0', 'c', 'r', 'p'), "Creoles and pidgins (Other)"},
850 {MAKECODE('\0', 'c', 'p', 'e'), "English-based (Other)"},
851 {MAKECODE('\0', 'c', 'p', 'f'), "French-based (Other)"},
852 {MAKECODE('\0', 'c', 'p', 'p'), "Portuguese-based (Other)"},
853 {MAKECODE('\0', 'c', 'r', 'h'), "Crimean Tatar"},
854 {MAKECODE('\0', 'c', 'r', 'h'), "Crimean Turkish"},
855 {MAKECODE('\0', 'h', 'r', 'v'), "Croatian"},
856 {MAKECODE('\0', 's', 'c', 'r'), "Croatian"},
857 {MAKECODE('\0', 'c', 'u', 's'), "Cushitic (Other)"},
858 {MAKECODE('\0', 'c', 'z', 'e'), "Czech"},
859 {MAKECODE('\0', 'c', 'e', 's'), "Czech"},
860 {MAKECODE('\0', 'd', 'a', 'k'), "Dakota"},
861 {MAKECODE('\0', 'd', 'a', 'n'), "Danish"},
862 {MAKECODE('\0', 'd', 'a', 'r'), "Dargwa"},
863 {MAKECODE('\0', 'd', 'a', 'y'), "Dayak"},
864 {MAKECODE('\0', 'd', 'e', 'l'), "Delaware"},
865 {MAKECODE('\0', 'd', 'i', 'n'), "Dinka"},
866 {MAKECODE('\0', 'd', 'i', 'v'), "Divehi"},
867 {MAKECODE('\0', 'd', 'o', 'i'), "Dogri"},
868 {MAKECODE('\0', 'd', 'g', 'r'), "Dogrib"},
869 {MAKECODE('\0', 'd', 'r', 'a'), "Dravidian (Other)"},
870 {MAKECODE('\0', 'd', 'u', 'a'), "Duala"},
871 {MAKECODE('\0', 'd', 'u', 't'), "Dutch"},
872 {MAKECODE('\0', 'n', 'l', 'd'), "Dutch"},
873 {MAKECODE('\0', 'd', 'u', 'm'), "Dutch, Middle (ca. 1050-1350)"},
874 {MAKECODE('\0', 'd', 'y', 'u'), "Dyula"},
875 {MAKECODE('\0', 'd', 'z', 'o'), "Dzongkha"},
876 {MAKECODE('\0', 'e', 'f', 'i'), "Efik"},
877 {MAKECODE('\0', 'e', 'g', 'y'), "Egyptian (Ancient)"},
878 {MAKECODE('\0', 'e', 'k', 'a'), "Ekajuk"},
879 {MAKECODE('\0', 'e', 'l', 'x'), "Elamite"},
880 {MAKECODE('\0', 'e', 'n', 'g'), "English"},
881 {MAKECODE('\0', 'e', 'n', 'm'), "English, Middle (1100-1500)"},
882 {MAKECODE('\0', 'a', 'n', 'g'), "English, Old (ca.450-1100)"},
883 {MAKECODE('\0', 'm', 'y', 'v'), "Erzya"},
884 {MAKECODE('\0', 'e', 'p', 'o'), "Esperanto"},
885 {MAKECODE('\0', 'e', 's', 't'), "Estonian"},
886 {MAKECODE('\0', 'e', 'w', 'e'), "Ewe"},
887 {MAKECODE('\0', 'e', 'w', 'o'), "Ewondo"},
888 {MAKECODE('\0', 'f', 'a', 'n'), "Fang"},
889 {MAKECODE('\0', 'f', 'a', 't'), "Fanti"},
890 {MAKECODE('\0', 'f', 'a', 'o'), "Faroese"},
891 {MAKECODE('\0', 'f', 'i', 'j'), "Fijian"},
892 {MAKECODE('\0', 'f', 'i', 'l'), "Filipino"},
893 {MAKECODE('\0', 'f', 'i', 'n'), "Finnish"},
894 {MAKECODE('\0', 'f', 'i', 'u'), "Finno-Ugrian (Other)"},
895 {MAKECODE('\0', 'd', 'u', 't'), "Flemish"},
896 {MAKECODE('\0', 'n', 'l', 'd'), "Flemish"},
897 {MAKECODE('\0', 'f', 'o', 'n'), "Fon"},
898 {MAKECODE('\0', 'f', 'r', 'e'), "French"},
899 {MAKECODE('\0', 'f', 'r', 'a'), "French"},
900 {MAKECODE('\0', 'f', 'r', 'm'), "French, Middle (ca.1400-1600)"},
901 {MAKECODE('\0', 'f', 'r', 'o'), "French, Old (842-ca.1400)"},
902 {MAKECODE('\0', 'f', 'r', 'y'), "Frisian"},
903 {MAKECODE('\0', 'f', 'u', 'r'), "Friulian"},
904 {MAKECODE('\0', 'f', 'u', 'l'), "Fulah"},
905 {MAKECODE('\0', 'g', 'a', 'a'), "Ga"},
906 {MAKECODE('\0', 'g', 'l', 'a'), "Gaelic"},
907 {MAKECODE('\0', 'g', 'l', 'g'), "Gallegan"},
908 {MAKECODE('\0', 'l', 'u', 'g'), "Ganda"},
909 {MAKECODE('\0', 'g', 'a', 'y'), "Gayo"},
910 {MAKECODE('\0', 'g', 'b', 'a'), "Gbaya"},
911 {MAKECODE('\0', 'g', 'e', 'z'), "Geez"},
912 {MAKECODE('\0', 'g', 'e', 'o'), "Georgian"},
913 {MAKECODE('\0', 'k', 'a', 't'), "Georgian"},
914 {MAKECODE('\0', 'g', 'e', 'r'), "German"},
915 {MAKECODE('\0', 'd', 'e', 'u'), "German"},
916 {MAKECODE('\0', 'n', 'd', 's'), "German, Low"},
917 {MAKECODE('\0', 'g', 'm', 'h'), "German, Middle High (ca.1050-1500)"},
918 {MAKECODE('\0', 'g', 'o', 'h'), "German, Old High (ca.750-1050)"},
919 {MAKECODE('\0', 'g', 's', 'w'), "German, Swiss German"},
920 {MAKECODE('\0', 'g', 'e', 'm'), "Germanic (Other)"},
921 {MAKECODE('\0', 'k', 'i', 'k'), "Gikuyu"},
922 {MAKECODE('\0', 'g', 'i', 'l'), "Gilbertese"},
923 {MAKECODE('\0', 'g', 'o', 'n'), "Gondi"},
924 {MAKECODE('\0', 'g', 'o', 'r'), "Gorontalo"},
925 {MAKECODE('\0', 'g', 'o', 't'), "Gothic"},
926 {MAKECODE('\0', 'g', 'r', 'b'), "Grebo"},
927 {MAKECODE('\0', 'g', 'r', 'c'), "Greek, Ancient (to 1453)"},
928 {MAKECODE('\0', 'g', 'r', 'e'), "Greek, Modern (1453-)"},
929 {MAKECODE('\0', 'e', 'l', 'l'), "Greek, Modern (1453-)"},
930 {MAKECODE('\0', 'k', 'a', 'l'), "Greenlandic"},
931 {MAKECODE('\0', 'g', 'r', 'n'), "Guarani"},
932 {MAKECODE('\0', 'g', 'u', 'j'), "Gujarati"},
933 {MAKECODE('\0', 'g', 'w', 'i'), "Gwich\xC2\xB4in"},
934 {MAKECODE('\0', 'h', 'a', 'i'), "Haida"},
935 {MAKECODE('\0', 'h', 'a', 't'), "Haitian"},
936 {MAKECODE('\0', 'h', 'a', 't'), "Haitian Creole"},
937 {MAKECODE('\0', 'h', 'a', 'u'), "Hausa"},
938 {MAKECODE('\0', 'h', 'a', 'w'), "Hawaiian"},
939 {MAKECODE('\0', 'h', 'e', 'b'), "Hebrew"},
940 {MAKECODE('\0', 'h', 'e', 'r'), "Herero"},
941 {MAKECODE('\0', 'h', 'i', 'l'), "Hiligaynon"},
942 {MAKECODE('\0', 'h', 'i', 'm'), "Himachali"},
943 {MAKECODE('\0', 'h', 'i', 'n'), "Hindi"},
944 {MAKECODE('\0', 'h', 'm', 'o'), "Hiri Motu"},
945 {MAKECODE('\0', 'h', 'i', 't'), "Hittite"},
946 {MAKECODE('\0', 'h', 'm', 'n'), "Hmong"},
947 {MAKECODE('\0', 'h', 'u', 'n'), "Hungarian"},
948 {MAKECODE('\0', 'h', 'u', 'p'), "Hupa"},
949 {MAKECODE('\0', 'i', 'b', 'a'), "Iban"},
950 {MAKECODE('\0', 'i', 'c', 'e'), "Icelandic"},
951 {MAKECODE('\0', 'i', 's', 'l'), "Icelandic"},
952 {MAKECODE('\0', 'i', 'd', 'o'), "Ido"},
953 {MAKECODE('\0', 'i', 'b', 'o'), "Igbo"},
954 {MAKECODE('\0', 'i', 'j', 'o'), "Ijo"},
955 {MAKECODE('\0', 'i', 'l', 'o'), "Iloko"},
956 {MAKECODE('\0', 's', 'm', 'n'), "Inari Sami"},
957 {MAKECODE('\0', 'i', 'n', 'c'), "Indic (Other)"},
958 {MAKECODE('\0', 'i', 'n', 'e'), "Indo-European (Other)"},
959 {MAKECODE('\0', 'i', 'n', 'd'), "Indonesian"},
960 {MAKECODE('\0', 'i', 'n', 'h'), "Ingush"},
961 {MAKECODE('\0', 'i', 'n', 'a'), "Auxiliary Language Association)"},
962 {MAKECODE('\0', 'i', 'l', 'e'), "Interlingue"},
963 {MAKECODE('\0', 'i', 'k', 'u'), "Inuktitut"},
964 {MAKECODE('\0', 'i', 'p', 'k'), "Inupiaq"},
965 {MAKECODE('\0', 'i', 'r', 'a'), "Iranian (Other)"},
966 {MAKECODE('\0', 'g', 'l', 'e'), "Irish"},
967 {MAKECODE('\0', 'm', 'g', 'a'), "Irish, Middle (900-1200)"},
968 {MAKECODE('\0', 's', 'g', 'a'), "Irish, Old (to 900)"},
969 {MAKECODE('\0', 'i', 'r', 'o'), "Iroquoian languages"},
970 {MAKECODE('\0', 'i', 't', 'a'), "Italian"},
971 {MAKECODE('\0', 'j', 'p', 'n'), "Japanese"},
972 {MAKECODE('\0', 'j', 'a', 'v'), "Javanese"},
973 {MAKECODE('\0', 'j', 'r', 'b'), "Judeo-Arabic"},
974 {MAKECODE('\0', 'j', 'p', 'r'), "Judeo-Persian"},
975 {MAKECODE('\0', 'k', 'b', 'd'), "Kabardian"},
976 {MAKECODE('\0', 'k', 'a', 'b'), "Kabyle"},
977 {MAKECODE('\0', 'k', 'a', 'c'), "Kachin"},
978 {MAKECODE('\0', 'k', 'a', 'l'), "Kalaallisut"},
979 {MAKECODE('\0', 'x', 'a', 'l'), "Kalmyk"},
980 {MAKECODE('\0', 'k', 'a', 'm'), "Kamba"},
981 {MAKECODE('\0', 'k', 'a', 'n'), "Kannada"},
982 {MAKECODE('\0', 'k', 'a', 'u'), "Kanuri"},
983 {MAKECODE('\0', 'k', 'r', 'c'), "Karachay-Balkar"},
984 {MAKECODE('\0', 'k', 'a', 'a'), "Kara-Kalpak"},
985 {MAKECODE('\0', 'k', 'a', 'r'), "Karen"},
986 {MAKECODE('\0', 'k', 'a', 's'), "Kashmiri"},
987 {MAKECODE('\0', 'c', 's', 'b'), "Kashubian"},
988 {MAKECODE('\0', 'k', 'a', 'w'), "Kawi"},
989 {MAKECODE('\0', 'k', 'a', 'z'), "Kazakh"},
990 {MAKECODE('\0', 'k', 'h', 'a'), "Khasi"},
991 {MAKECODE('\0', 'k', 'h', 'm'), "Khmer"},
992 {MAKECODE('\0', 'k', 'h', 'i'), "Khoisan (Other)"},
993 {MAKECODE('\0', 'k', 'h', 'o'), "Khotanese"},
994 {MAKECODE('\0', 'k', 'i', 'k'), "Kikuyu"},
995 {MAKECODE('\0', 'k', 'm', 'b'), "Kimbundu"},
996 {MAKECODE('\0', 'k', 'i', 'n'), "Kinyarwanda"},
997 {MAKECODE('\0', 'k', 'i', 'r'), "Kirghiz"},
998 {MAKECODE('\0', 't', 'l', 'h'), "Klingon"},
999 {MAKECODE('\0', 'k', 'o', 'm'), "Komi"},
1000 {MAKECODE('\0', 'k', 'o', 'n'), "Kongo"},
1001 {MAKECODE('\0', 'k', 'o', 'k'), "Konkani"},
1002 {MAKECODE('\0', 'k', 'o', 'r'), "Korean"},
1003 {MAKECODE('\0', 'k', 'o', 's'), "Kosraean"},
1004 {MAKECODE('\0', 'k', 'p', 'e'), "Kpelle"},
1005 {MAKECODE('\0', 'k', 'r', 'o'), "Kru"},
1006 {MAKECODE('\0', 'k', 'u', 'a'), "Kuanyama"},
1007 {MAKECODE('\0', 'k', 'u', 'm'), "Kumyk"},
1008 {MAKECODE('\0', 'k', 'u', 'r'), "Kurdish"},
1009 {MAKECODE('\0', 'k', 'r', 'u'), "Kurukh"},
1010 {MAKECODE('\0', 'k', 'u', 't'), "Kutenai"},
1011 {MAKECODE('\0', 'k', 'u', 'a'), "Kwanyama, Kuanyama"},
1012 {MAKECODE('\0', 'l', 'a', 'd'), "Ladino"},
1013 {MAKECODE('\0', 'l', 'a', 'h'), "Lahnda"},
1014 {MAKECODE('\0', 'l', 'a', 'm'), "Lamba"},
1015 {MAKECODE('\0', 'l', 'a', 'o'), "Lao"},
1016 {MAKECODE('\0', 'l', 'a', 't'), "Latin"},
1017 {MAKECODE('\0', 'l', 'a', 'v'), "Latvian"},
1018 {MAKECODE('\0', 'l', 't', 'z'), "Letzeburgesch"},
1019 {MAKECODE('\0', 'l', 'e', 'z'), "Lezghian"},
1020 {MAKECODE('\0', 'l', 'i', 'm'), "Limburgan"},
1021 {MAKECODE('\0', 'l', 'i', 'm'), "Limburger"},
1022 {MAKECODE('\0', 'l', 'i', 'm'), "Limburgish"},
1023 {MAKECODE('\0', 'l', 'i', 'n'), "Lingala"},
1024 {MAKECODE('\0', 'l', 'i', 't'), "Lithuanian"},
1025 {MAKECODE('\0', 'j', 'b', 'o'), "Lojban"},
1026 {MAKECODE('\0', 'n', 'd', 's'), "Low German"},
1027 {MAKECODE('\0', 'n', 'd', 's'), "Low Saxon"},
1028 {MAKECODE('\0', 'd', 's', 'b'), "Lower Sorbian"},
1029 {MAKECODE('\0', 'l', 'o', 'z'), "Lozi"},
1030 {MAKECODE('\0', 'l', 'u', 'b'), "Luba-Katanga"},
1031 {MAKECODE('\0', 'l', 'u', 'a'), "Luba-Lulua"},
1032 {MAKECODE('\0', 'l', 'u', 'i'), "Luiseno"},
1033 {MAKECODE('\0', 's', 'm', 'j'), "Lule Sami"},
1034 {MAKECODE('\0', 'l', 'u', 'n'), "Lunda"},
1035 {MAKECODE('\0', 'l', 'u', 'o'), "Luo (Kenya and Tanzania)"},
1036 {MAKECODE('\0', 'l', 'u', 's'), "Lushai"},
1037 {MAKECODE('\0', 'l', 't', 'z'), "Luxembourgish"},
1038 {MAKECODE('\0', 'm', 'a', 'c'), "Macedonian"},
1039 {MAKECODE('\0', 'm', 'k', 'd'), "Macedonian"},
1040 {MAKECODE('\0', 'm', 'a', 'd'), "Madurese"},
1041 {MAKECODE('\0', 'm', 'a', 'g'), "Magahi"},
1042 {MAKECODE('\0', 'm', 'a', 'i'), "Maithili"},
1043 {MAKECODE('\0', 'm', 'a', 'k'), "Makasar"},
1044 {MAKECODE('\0', 'm', 'l', 'g'), "Malagasy"},
1045 {MAKECODE('\0', 'm', 'a', 'y'), "Malay"},
1046 {MAKECODE('\0', 'm', 's', 'a'), "Malay"},
1047 {MAKECODE('\0', 'm', 'a', 'l'), "Malayalam"},
1048 {MAKECODE('\0', 'm', 'l', 't'), "Maltese"},
1049 {MAKECODE('\0', 'm', 'n', 'c'), "Manchu"},
1050 {MAKECODE('\0', 'm', 'd', 'r'), "Mandar"},
1051 {MAKECODE('\0', 'm', 'a', 'n'), "Mandingo"},
1052 {MAKECODE('\0', 'm', 'n', 'i'), "Manipuri"},
1053 {MAKECODE('\0', 'm', 'n', 'o'), "Manobo languages"},
1054 {MAKECODE('\0', 'g', 'l', 'v'), "Manx"},
1055 {MAKECODE('\0', 'm', 'a', 'o'), "Maori"},
1056 {MAKECODE('\0', 'm', 'r', 'i'), "Maori"},
1057 {MAKECODE('\0', 'm', 'a', 'r'), "Marathi"},
1058 {MAKECODE('\0', 'c', 'h', 'm'), "Mari"},
1059 {MAKECODE('\0', 'm', 'a', 'h'), "Marshallese"},
1060 {MAKECODE('\0', 'm', 'w', 'r'), "Marwari"},
1061 {MAKECODE('\0', 'm', 'a', 's'), "Masai"},
1062 {MAKECODE('\0', 'm', 'y', 'n'), "Mayan languages"},
1063 {MAKECODE('\0', 'm', 'e', 'n'), "Mende"},
1064 {MAKECODE('\0', 'm', 'i', 'c'), "Micmac"},
1065 {MAKECODE('\0', 'm', 'i', 'c'), "Mi'kmaq"},
1066 {MAKECODE('\0', 'm', 'i', 'n'), "Minangkabau"},
1067 {MAKECODE('\0', 'm', 'w', 'l'), "Mirandese"},
1068 {MAKECODE('\0', 'm', 'i', 's'), "Miscellaneous languages"},
1069 {MAKECODE('\0', 'm', 'o', 'h'), "Mohawk"},
1070 {MAKECODE('\0', 'm', 'd', 'f'), "Moksha"},
1071 {MAKECODE('\0', 'm', 'o', 'l'), "Moldavian"},
1072 {MAKECODE('\0', 'm', 'k', 'h'), "Mon-Khmer (Other)"},
1073 {MAKECODE('\0', 'l', 'o', 'l'), "Mongo"},
1074 {MAKECODE('\0', 'm', 'o', 'n'), "Mongolian"},
1075 {MAKECODE('\0', 'm', 'o', 's'), "Mossi"},
1076 {MAKECODE('\0', 'm', 'u', 'l'), "Multiple languages"},
1077 {MAKECODE('\0', 'm', 'u', 'n'), "Munda languages"},
1078 {MAKECODE('\0', 'n', 'a', 'h'), "Nahuatl"},
1079 {MAKECODE('\0', 'n', 'a', 'u'), "Nauru"},
1080 {MAKECODE('\0', 'n', 'a', 'v'), "Navaho, Navajo"},
1081 {MAKECODE('\0', 'n', 'a', 'v'), "Navajo"},
1082 {MAKECODE('\0', 'n', 'd', 'e'), "Ndebele, North"},
1083 {MAKECODE('\0', 'n', 'b', 'l'), "Ndebele, South"},
1084 {MAKECODE('\0', 'n', 'd', 'o'), "Ndonga"},
1085 {MAKECODE('\0', 'n', 'a', 'p'), "Neapolitan"},
1086 {MAKECODE('\0', 'n', 'e', 'w'), "Nepal Bhasa"},
1087 {MAKECODE('\0', 'n', 'e', 'p'), "Nepali"},
1088 {MAKECODE('\0', 'n', 'e', 'w'), "Newari"},
1089 {MAKECODE('\0', 'n', 'i', 'a'), "Nias"},
1090 {MAKECODE('\0', 'n', 'i', 'c'), "Niger-Kordofanian (Other)"},
1091 {MAKECODE('\0', 's', 's', 'a'), "Nilo-Saharan (Other)"},
1092 {MAKECODE('\0', 'n', 'i', 'u'), "Niuean"},
1093 {MAKECODE('\0', 'z', 'x', 'x'), "No linguistic content"},
1094 {MAKECODE('\0', 'n', 'o', 'g'), "Nogai"},
1095 {MAKECODE('\0', 'n', 'o', 'n'), "Norse, Old"},
1096 {MAKECODE('\0', 'n', 'a', 'i'), "North American Indian (Other)"},
1097 {MAKECODE('\0', 's', 'm', 'e'), "Northern Sami"},
1098 {MAKECODE('\0', 'n', 's', 'o'), "Northern Sotho"},
1099 {MAKECODE('\0', 'n', 'd', 'e'), "North Ndebele"},
1100 {MAKECODE('\0', 'n', 'o', 'r'), "Norwegian"},
1101 {MAKECODE('\0', 'n', 'o', 'b'), "Norwegian Bokm\xC3\xA5l"},
1102 {MAKECODE('\0', 'n', 'n', 'o'), "Norwegian Nynorsk"},
1103 {MAKECODE('\0', 'n', 'u', 'b'), "Nubian languages"},
1104 {MAKECODE('\0', 'n', 'y', 'm'), "Nyamwezi"},
1105 {MAKECODE('\0', 'n', 'y', 'a'), "Nyanja"},
1106 {MAKECODE('\0', 'n', 'y', 'n'), "Nyankole"},
1107 {MAKECODE('\0', 'n', 'n', 'o'), "Nynorsk, Norwegian"},
1108 {MAKECODE('\0', 'n', 'y', 'o'), "Nyoro"},
1109 {MAKECODE('\0', 'n', 'z', 'i'), "Nzima"},
1110 {MAKECODE('\0', 'o', 'c', 'i'), "Occitan (post 1500)"},
1111 {MAKECODE('\0', 'o', 'j', 'i'), "Ojibwa"},
1112 {MAKECODE('\0', 'c', 'h', 'u'), "Old Bulgarian"},
1113 {MAKECODE('\0', 'c', 'h', 'u'), "Old Church Slavonic"},
1114 {MAKECODE('\0', 'n', 'w', 'c'), "Old Newari"},
1115 {MAKECODE('\0', 'c', 'h', 'u'), "Old Slavonic"},
1116 {MAKECODE('\0', 'o', 'r', 'i'), "Oriya"},
1117 {MAKECODE('\0', 'o', 'r', 'm'), "Oromo"},
1118 {MAKECODE('\0', 'o', 's', 'a'), "Osage"},
1119 {MAKECODE('\0', 'o', 's', 's'), "Ossetian"},
1120 {MAKECODE('\0', 'o', 's', 's'), "Ossetic"},
1121 {MAKECODE('\0', 'o', 't', 'o'), "Otomian languages"},
1122 {MAKECODE('\0', 'p', 'a', 'l'), "Pahlavi"},
1123 {MAKECODE('\0', 'p', 'a', 'u'), "Palauan"},
1124 {MAKECODE('\0', 'p', 'l', 'i'), "Pali"},
1125 {MAKECODE('\0', 'p', 'a', 'm'), "Pampanga"},
1126 {MAKECODE('\0', 'p', 'a', 'g'), "Pangasinan"},
1127 {MAKECODE('\0', 'p', 'a', 'n'), "Panjabi"},
1128 {MAKECODE('\0', 'p', 'a', 'p'), "Papiamento"},
1129 {MAKECODE('\0', 'p', 'a', 'a'), "Papuan (Other)"},
1130 {MAKECODE('\0', 'n', 's', 'o'), "Pedi"},
1131 {MAKECODE('\0', 'p', 'e', 'r'), "Persian"},
1132 {MAKECODE('\0', 'f', 'a', 's'), "Persian"},
1133 {MAKECODE('\0', 'p', 'e', 'o'), "Persian, Old (ca.600-400 B.C.)"},
1134 {MAKECODE('\0', 'p', 'h', 'i'), "Philippine (Other)"},
1135 {MAKECODE('\0', 'p', 'h', 'n'), "Phoenician"},
1136 {MAKECODE('\0', 'f', 'i', 'l'), "Pilipino"},
1137 {MAKECODE('\0', 'p', 'o', 'n'), "Pohnpeian"},
1138 {MAKECODE('\0', 'p', 'o', 'l'), "Polish"},
1139 {MAKECODE('\0', 'p', 'o', 'r'), "Portuguese"},
1140 // pob = unofficial language code for Brazilian Portuguese
1141 {MAKECODE('\0', 'p', 'o', 'b'), "Portuguese (Brazil)"},
1142 {MAKECODE('\0', 'p', 'r', 'a'), "Prakrit languages"},
1143 {MAKECODE('\0', 'o', 'c', 'i'), "Proven\xC3\xA7"
1144 "al"},
1145 {MAKECODE('\0', 'p', 'r', 'o'), "Proven\xC3\xA7"
1146 "al, Old (to 1500)"},
1147 {MAKECODE('\0', 'p', 'a', 'n'), "Punjabi"},
1148 {MAKECODE('\0', 'p', 'u', 's'), "Pushto"},
1149 {MAKECODE('\0', 'q', 'u', 'e'), "Quechua"},
1150 {MAKECODE('\0', 'r', 'o', 'h'), "Raeto-Romance"},
1151 {MAKECODE('\0', 'r', 'a', 'j'), "Rajasthani"},
1152 {MAKECODE('\0', 'r', 'a', 'p'), "Rapanui"},
1153 {MAKECODE('\0', 'r', 'a', 'r'), "Rarotongan"},
1154 // { "qaa-qtz", "Reserved for local use" },
1155 {MAKECODE('\0', 'r', 'o', 'a'), "Romance (Other)"},
1156 {MAKECODE('\0', 'r', 'u', 'm'), "Romanian"},
1157 {MAKECODE('\0', 'r', 'o', 'n'), "Romanian"},
1158 {MAKECODE('\0', 'r', 'o', 'm'), "Romany"},
1159 {MAKECODE('\0', 'r', 'u', 'n'), "Rundi"},
1160 {MAKECODE('\0', 'r', 'u', 's'), "Russian"},
1161 {MAKECODE('\0', 's', 'a', 'l'), "Salishan languages"},
1162 {MAKECODE('\0', 's', 'a', 'm'), "Samaritan Aramaic"},
1163 {MAKECODE('\0', 's', 'm', 'i'), "Sami languages (Other)"},
1164 {MAKECODE('\0', 's', 'm', 'o'), "Samoan"},
1165 {MAKECODE('\0', 's', 'a', 'd'), "Sandawe"},
1166 {MAKECODE('\0', 's', 'a', 'g'), "Sango"},
1167 {MAKECODE('\0', 's', 'a', 'n'), "Sanskrit"},
1168 {MAKECODE('\0', 's', 'a', 't'), "Santali"},
1169 {MAKECODE('\0', 's', 'r', 'd'), "Sardinian"},
1170 {MAKECODE('\0', 's', 'a', 's'), "Sasak"},
1171 {MAKECODE('\0', 'n', 'd', 's'), "Saxon, Low"},
1172 {MAKECODE('\0', 's', 'c', 'o'), "Scots"},
1173 {MAKECODE('\0', 'g', 'l', 'a'), "Scottish Gaelic"},
1174 {MAKECODE('\0', 's', 'e', 'l'), "Selkup"},
1175 {MAKECODE('\0', 's', 'e', 'm'), "Semitic (Other)"},
1176 {MAKECODE('\0', 'n', 's', 'o'), "Sepedi"},
1177 {MAKECODE('\0', 's', 'c', 'c'), "Serbian"},
1178 {MAKECODE('\0', 's', 'r', 'p'), "Serbian"},
1179 {MAKECODE('\0', 's', 'r', 'r'), "Serer"},
1180 {MAKECODE('\0', 's', 'h', 'n'), "Shan"},
1181 {MAKECODE('\0', 's', 'n', 'a'), "Shona"},
1182 {MAKECODE('\0', 'i', 'i', 'i'), "Sichuan Yi"},
1183 {MAKECODE('\0', 's', 'c', 'n'), "Sicilian"},
1184 {MAKECODE('\0', 's', 'i', 'd'), "Sidamo"},
1185 {MAKECODE('\0', 's', 'g', 'n'), "Sign languages"},
1186 {MAKECODE('\0', 'b', 'l', 'a'), "Siksika"},
1187 {MAKECODE('\0', 's', 'n', 'd'), "Sindhi"},
1188 {MAKECODE('\0', 's', 'i', 'n'), "Sinhala"},
1189 {MAKECODE('\0', 's', 'i', 'n'), "Sinhalese"},
1190 {MAKECODE('\0', 's', 'i', 't'), "Sino-Tibetan (Other)"},
1191 {MAKECODE('\0', 's', 'i', 'o'), "Siouan languages"},
1192 {MAKECODE('\0', 's', 'm', 's'), "Skolt Sami"},
1193 {MAKECODE('\0', 'd', 'e', 'n'), "Slave (Athapascan)"},
1194 {MAKECODE('\0', 's', 'l', 'a'), "Slavic (Other)"},
1195 {MAKECODE('\0', 's', 'l', 'o'), "Slovak"},
1196 {MAKECODE('\0', 's', 'l', 'k'), "Slovak"},
1197 {MAKECODE('\0', 's', 'l', 'v'), "Slovenian"},
1198 {MAKECODE('\0', 's', 'o', 'g'), "Sogdian"},
1199 {MAKECODE('\0', 's', 'o', 'm'), "Somali"},
1200 {MAKECODE('\0', 's', 'o', 'n'), "Songhai"},
1201 {MAKECODE('\0', 's', 'n', 'k'), "Soninke"},
1202 {MAKECODE('\0', 'w', 'e', 'n'), "Sorbian languages"},
1203 {MAKECODE('\0', 'n', 's', 'o'), "Sotho, Northern"},
1204 {MAKECODE('\0', 's', 'o', 't'), "Sotho, Southern"},
1205 {MAKECODE('\0', 's', 'a', 'i'), "South American Indian (Other)"},
1206 {MAKECODE('\0', 's', 'm', 'a'), "Southern Sami"},
1207 {MAKECODE('\0', 'n', 'b', 'l'), "South Ndebele"},
1208 {MAKECODE('\0', 's', 'p', 'a'), "Castilian"},
1209 {MAKECODE('\0', 's', 'u', 'k'), "Sukuma"},
1210 {MAKECODE('\0', 's', 'u', 'x'), "Sumerian"},
1211 {MAKECODE('\0', 's', 'u', 'n'), "Sundanese"},
1212 {MAKECODE('\0', 's', 'u', 's'), "Susu"},
1213 {MAKECODE('\0', 's', 'w', 'a'), "Swahili"},
1214 {MAKECODE('\0', 's', 's', 'w'), "Swati"},
1215 {MAKECODE('\0', 's', 'w', 'e'), "Swedish"},
1216 {MAKECODE('\0', 's', 'y', 'r'), "Syriac"},
1217 {MAKECODE('\0', 't', 'g', 'l'), "Tagalog"},
1218 {MAKECODE('\0', 't', 'a', 'h'), "Tahitian"},
1219 {MAKECODE('\0', 't', 'a', 'i'), "Tai (Other)"},
1220 {MAKECODE('\0', 't', 'g', 'k'), "Tajik"},
1221 {MAKECODE('\0', 't', 'm', 'h'), "Tamashek"},
1222 {MAKECODE('\0', 't', 'a', 'm'), "Tamil"},
1223 {MAKECODE('\0', 't', 'a', 't'), "Tatar"},
1224 {MAKECODE('\0', 't', 'e', 'l'), "Telugu"},
1225 {MAKECODE('\0', 't', 'e', 'r'), "Tereno"},
1226 {MAKECODE('\0', 't', 'e', 't'), "Tetum"},
1227 {MAKECODE('\0', 't', 'h', 'a'), "Thai"},
1228 {MAKECODE('\0', 't', 'i', 'b'), "Tibetan"},
1229 {MAKECODE('\0', 'b', 'o', 'd'), "Tibetan"},
1230 {MAKECODE('\0', 't', 'i', 'g'), "Tigre"},
1231 {MAKECODE('\0', 't', 'i', 'r'), "Tigrinya"},
1232 {MAKECODE('\0', 't', 'e', 'm'), "Timne"},
1233 {MAKECODE('\0', 't', 'i', 'v'), "Tiv"},
1234 {MAKECODE('\0', 't', 'l', 'h'), "tlhIngan-Hol"},
1235 {MAKECODE('\0', 't', 'l', 'i'), "Tlingit"},
1236 {MAKECODE('\0', 't', 'p', 'i'), "Tok Pisin"},
1237 {MAKECODE('\0', 't', 'k', 'l'), "Tokelau"},
1238 {MAKECODE('\0', 't', 'o', 'g'), "Tonga (Nyasa)"},
1239 {MAKECODE('\0', 't', 'o', 'n'), "Tonga (Tonga Islands)"},
1240 {MAKECODE('\0', 't', 's', 'i'), "Tsimshian"},
1241 {MAKECODE('\0', 't', 's', 'o'), "Tsonga"},
1242 {MAKECODE('\0', 't', 's', 'n'), "Tswana"},
1243 {MAKECODE('\0', 't', 'u', 'm'), "Tumbuka"},
1244 {MAKECODE('\0', 't', 'u', 'p'), "Tupi languages"},
1245 {MAKECODE('\0', 't', 'u', 'r'), "Turkish"},
1246 {MAKECODE('\0', 'o', 't', 'a'), "Turkish, Ottoman (1500-1928)"},
1247 {MAKECODE('\0', 't', 'u', 'k'), "Turkmen"},
1248 {MAKECODE('\0', 't', 'v', 'l'), "Tuvalu"},
1249 {MAKECODE('\0', 't', 'y', 'v'), "Tuvinian"},
1250 {MAKECODE('\0', 't', 'w', 'i'), "Twi"},
1251 {MAKECODE('\0', 'u', 'd', 'm'), "Udmurt"},
1252 {MAKECODE('\0', 'u', 'g', 'a'), "Ugaritic"},
1253 {MAKECODE('\0', 'u', 'i', 'g'), "Uighur"},
1254 {MAKECODE('\0', 'u', 'k', 'r'), "Ukrainian"},
1255 {MAKECODE('\0', 'u', 'm', 'b'), "Umbundu"},
1256 {MAKECODE('\0', 'u', 'n', 'd'), "Undetermined"},
1257 {MAKECODE('\0', 'h', 's', 'b'), "Upper Sorbian"},
1258 {MAKECODE('\0', 'u', 'r', 'd'), "Urdu"},
1259 {MAKECODE('\0', 'u', 'i', 'g'), "Uyghur"},
1260 {MAKECODE('\0', 'u', 'z', 'b'), "Uzbek"},
1261 {MAKECODE('\0', 'v', 'a', 'i'), "Vai"},
1262 {MAKECODE('\0', 'c', 'a', 't'), "Valencian"},
1263 {MAKECODE('\0', 'v', 'e', 'n'), "Venda"},
1264 {MAKECODE('\0', 'v', 'i', 'e'), "Vietnamese"},
1265 {MAKECODE('\0', 'v', 'o', 'l'), "Volap\xC3\xBCk"},
1266 {MAKECODE('\0', 'v', 'o', 't'), "Votic"},
1267 {MAKECODE('\0', 'w', 'a', 'k'), "Wakashan languages"},
1268 {MAKECODE('\0', 'w', 'a', 'l'), "Walamo"},
1269 {MAKECODE('\0', 'w', 'l', 'n'), "Walloon"},
1270 {MAKECODE('\0', 'w', 'a', 'r'), "Waray"},
1271 {MAKECODE('\0', 'w', 'a', 's'), "Washo"},
1272 {MAKECODE('\0', 'w', 'e', 'l'), "Welsh"},
1273 {MAKECODE('\0', 'c', 'y', 'm'), "Welsh"},
1274 {MAKECODE('\0', 'w', 'o', 'l'), "Wolof"},
1275 {MAKECODE('\0', 'x', 'h', 'o'), "Xhosa"},
1276 {MAKECODE('\0', 's', 'a', 'h'), "Yakut"},
1277 {MAKECODE('\0', 'y', 'a', 'o'), "Yao"},
1278 {MAKECODE('\0', 'y', 'a', 'p'), "Yapese"},
1279 {MAKECODE('\0', 'y', 'i', 'd'), "Yiddish"},
1280 {MAKECODE('\0', 'y', 'o', 'r'), "Yoruba"},
1281 {MAKECODE('\0', 'y', 'p', 'k'), "Yupik languages"},
1282 {MAKECODE('\0', 'z', 'n', 'd'), "Zande"},
1283 {MAKECODE('\0', 'z', 'a', 'p'), "Zapotec"},
1284 {MAKECODE('\0', 'z', 'e', 'n'), "Zenaga"},
1285 {MAKECODE('\0', 'z', 'h', 'a'), "Zhuang"},
1286 {MAKECODE('\0', 'z', 'u', 'l'), "Zulu"},
1287 {MAKECODE('\0', 'z', 'u', 'n'), "Zuni"},
1288}};
1289// clang-format on
1290
1291// clang-format off
1292const std::array<ISO639, 190> LanguageCodes = {{
1293 {"aa", "aar", NULL, NULL},
1294 {"ab", "abk", NULL, NULL},
1295 {"af", "afr", NULL, NULL},
1296 {"ak", "aka", NULL, NULL},
1297 {"am", "amh", NULL, NULL},
1298 {"ar", "ara", NULL, NULL},
1299 {"an", "arg", NULL, NULL},
1300 {"as", "asm", NULL, NULL},
1301 {"av", "ava", NULL, NULL},
1302 {"ae", "ave", NULL, NULL},
1303 {"ay", "aym", NULL, NULL},
1304 {"az", "aze", NULL, NULL},
1305 {"ba", "bak", NULL, NULL},
1306 {"bm", "bam", NULL, NULL},
1307 {"be", "bel", NULL, NULL},
1308 {"bn", "ben", NULL, NULL},
1309 {"bh", "bih", NULL, NULL},
1310 {"bi", "bis", NULL, NULL},
1311 {"bo", "tib", NULL, "bod"},
1312 {"bs", "bos", NULL, NULL},
1313 {"br", "bre", NULL, NULL},
1314 {"bg", "bul", NULL, NULL},
1315 {"ca", "cat", NULL, NULL},
1316 {"cs", "cze", "ces", "ces"},
1317 {"ch", "cha", NULL, NULL},
1318 {"ce", "che", NULL, NULL},
1319 {"cu", "chu", NULL, NULL},
1320 {"cv", "chv", NULL, NULL},
1321 {"kw", "cor", NULL, NULL},
1322 {"co", "cos", NULL, NULL},
1323 {"cr", "cre", NULL, NULL},
1324 {"cy", "wel", NULL, "cym"},
1325 {"da", "dan", NULL, NULL},
1326 {"de", "ger", "deu", "deu"},
1327 {"dv", "div", NULL, NULL},
1328 {"dz", "dzo", NULL, NULL},
1329 {"el", "gre", "ell", "ell"},
1330 {"en", "eng", NULL, NULL},
1331 {"eo", "epo", NULL, NULL},
1332 {"et", "est", NULL, NULL},
1333 {"eu", "baq", NULL, "eus"},
1334 {"ee", "ewe", NULL, NULL},
1335 {"fo", "fao", NULL, NULL},
1336 {"fa", "per", NULL, "fas"},
1337 {"fj", "fij", NULL, NULL},
1338 {"fi", "fin", NULL, NULL},
1339 {"fr", "fre", "fra", "fra"},
1340 {"fy", "fry", NULL, NULL},
1341 {"ff", "ful", NULL, NULL},
1342 {"gd", "gla", NULL, NULL},
1343 {"ga", "gle", NULL, NULL},
1344 {"gl", "glg", NULL, NULL},
1345 {"gv", "glv", NULL, NULL},
1346 {"gn", "grn", NULL, NULL},
1347 {"gu", "guj", NULL, NULL},
1348 {"ht", "hat", NULL, NULL},
1349 {"ha", "hau", NULL, NULL},
1350 {"he", "heb", NULL, NULL},
1351 {"hz", "her", NULL, NULL},
1352 {"hi", "hin", NULL, NULL},
1353 {"ho", "hmo", NULL, NULL},
1354 {"hr", "hrv", NULL, NULL},
1355 {"hu", "hun", NULL, NULL},
1356 {"hy", "arm", NULL, "hye"},
1357 {"ig", "ibo", NULL, NULL},
1358 {"io", "ido", NULL, NULL},
1359 {"ii", "iii", NULL, NULL},
1360 {"iu", "iku", NULL, NULL},
1361 {"ie", "ile", NULL, NULL},
1362 {"ia", "ina", NULL, NULL},
1363 {"id", "ind", NULL, NULL},
1364 {"ik", "ipk", NULL, NULL},
1365 {"is", "ice", "isl", "isl"},
1366 {"it", "ita", NULL, NULL},
1367 {"jv", "jav", NULL, NULL},
1368 {"ja", "jpn", NULL, NULL},
1369 {"kl", "kal", NULL, NULL},
1370 {"kn", "kan", NULL, NULL},
1371 {"ks", "kas", NULL, NULL},
1372 {"ka", "geo", NULL, "kat"},
1373 {"kr", "kau", NULL, NULL},
1374 {"kk", "kaz", NULL, NULL},
1375 {"km", "khm", NULL, NULL},
1376 {"ki", "kik", NULL, NULL},
1377 {"rw", "kin", NULL, NULL},
1378 {"ky", "kir", NULL, NULL},
1379 {"kv", "kom", NULL, NULL},
1380 {"kg", "kon", NULL, NULL},
1381 {"ko", "kor", NULL, NULL},
1382 {"kj", "kua", NULL, NULL},
1383 {"ku", "kur", NULL, NULL},
1384 {"lo", "lao", NULL, NULL},
1385 {"la", "lat", NULL, NULL},
1386 {"lv", "lav", NULL, NULL},
1387 {"li", "lim", NULL, NULL},
1388 {"ln", "lin", NULL, NULL},
1389 {"lt", "lit", NULL, NULL},
1390 {"lb", "ltz", NULL, NULL},
1391 {"lu", "lub", NULL, NULL},
1392 {"lg", "lug", NULL, NULL},
1393 {"mk", "mac", NULL, "mdk"},
1394 {"mh", "mah", NULL, NULL},
1395 {"ml", "mal", NULL, NULL},
1396 {"mi", "mao", NULL, "mri"},
1397 {"mr", "mar", NULL, NULL},
1398 {"ms", "may", NULL, "msa"},
1399 {"mg", "mlg", NULL, NULL},
1400 {"mt", "mlt", NULL, NULL},
1401 {"mn", "mon", NULL, NULL},
1402 {"my", "bur", NULL, "mya"},
1403 {"na", "nau", NULL, NULL},
1404 {"nv", "nav", NULL, NULL},
1405 {"nr", "nbl", NULL, NULL},
1406 {"nd", "nde", NULL, NULL},
1407 {"ng", "ndo", NULL, NULL},
1408 {"ne", "nep", NULL, NULL},
1409 {"nl", "dut", "nld", "nld"},
1410 {"nn", "nno", NULL, NULL},
1411 {"nb", "nob", NULL, NULL},
1412 {"no", "nor", NULL, NULL},
1413 {"ny", "nya", NULL, NULL},
1414 {"oc", "oci", NULL, NULL},
1415 {"oj", "oji", NULL, NULL},
1416 {"or", "ori", NULL, NULL},
1417 {"om", "orm", NULL, NULL},
1418 {"os", "oss", NULL, NULL},
1419 {"pa", "pan", NULL, NULL},
1420 // pb / pob = unofficial language code for Brazilian Portuguese
1421 {"pb", "pob", NULL, NULL},
1422 {"pi", "pli", NULL, NULL},
1423 {"pl", "pol", "plk", NULL},
1424 {"pt", "por", "ptg", NULL},
1425 {"ps", "pus", NULL, NULL},
1426 {"qu", "que", NULL, NULL},
1427 {"rm", "roh", NULL, NULL},
1428 {"ro", "rum", "ron", "ron"},
1429 {"rn", "run", NULL, NULL},
1430 {"ru", "rus", NULL, NULL},
1431 {"sh", "scr", NULL, NULL},
1432 {"sg", "sag", NULL, NULL},
1433 {"sa", "san", NULL, NULL},
1434 {"si", "sin", NULL, NULL},
1435 {"sk", "slo", "sky", "slk"},
1436 {"sl", "slv", NULL, NULL},
1437 {"se", "sme", NULL, NULL},
1438 {"sm", "smo", NULL, NULL},
1439 {"sn", "sna", NULL, NULL},
1440 {"sd", "snd", NULL, NULL},
1441 {"so", "som", NULL, NULL},
1442 {"st", "sot", NULL, NULL},
1443 {"es", "spa", "esp", NULL},
1444 {"sq", "alb", NULL, "sqi"},
1445 {"sc", "srd", NULL, NULL},
1446 {"sr", "srp", NULL, NULL},
1447 {"ss", "ssw", NULL, NULL},
1448 {"su", "sun", NULL, NULL},
1449 {"sw", "swa", NULL, NULL},
1450 {"sv", "swe", "sve", NULL},
1451 {"ty", "tah", NULL, NULL},
1452 {"ta", "tam", NULL, NULL},
1453 {"tt", "tat", NULL, NULL},
1454 {"te", "tel", NULL, NULL},
1455 {"tg", "tgk", NULL, NULL},
1456 {"tl", "tgl", NULL, NULL},
1457 {"th", "tha", NULL, NULL},
1458 {"ti", "tir", NULL, NULL},
1459 {"to", "ton", NULL, NULL},
1460 {"tn", "tsn", NULL, NULL},
1461 {"ts", "tso", NULL, NULL},
1462 {"tk", "tuk", NULL, NULL},
1463 {"tr", "tur", "trk", NULL},
1464 {"tw", "twi", NULL, NULL},
1465 {"ug", "uig", NULL, NULL},
1466 {"uk", "ukr", NULL, NULL},
1467 {"ur", "urd", NULL, NULL},
1468 {"uz", "uzb", NULL, NULL},
1469 {"ve", "ven", NULL, NULL},
1470 {"vi", "vie", NULL, NULL},
1471 {"vo", "vol", NULL, NULL},
1472 {"wa", "wln", NULL, NULL},
1473 {"wo", "wol", NULL, NULL},
1474 {"xh", "xho", NULL, NULL},
1475 {"yi", "yid", NULL, NULL},
1476 {"yo", "yor", NULL, NULL},
1477 {"za", "zha", NULL, NULL},
1478 {"zh", "chi", "zho", "zho"},
1479 {"zu", "zul", NULL, NULL},
1480 {"zv", "und", NULL, NULL}, // Kodi intern mapping for missing "Undetermined" iso639-1 code
1481 {"zx", "zxx", NULL,
1482 NULL}, // Kodi intern mapping for missing "No linguistic content" iso639-1 code
1483 {"zy", "mis", NULL,
1484 NULL}, // Kodi intern mapping for missing "Miscellaneous languages" iso639-1 code
1485 {"zz", "mul", NULL, NULL} // Kodi intern mapping for missing "Multiple languages" iso639-1 code
1486}};
1487// clang-format on
1488
1489// Based on ISO 3166
1490// clang-format off
1491const std::array<ISO3166_1, 245> RegionCodes = {{
1492 {"af", "afg"},
1493 {"ax", "ala"},
1494 {"al", "alb"},
1495 {"dz", "dza"},
1496 {"as", "asm"},
1497 {"ad", "and"},
1498 {"ao", "ago"},
1499 {"ai", "aia"},
1500 {"aq", "ata"},
1501 {"ag", "atg"},
1502 {"ar", "arg"},
1503 {"am", "arm"},
1504 {"aw", "abw"},
1505 {"au", "aus"},
1506 {"at", "aut"},
1507 {"az", "aze"},
1508 {"bs", "bhs"},
1509 {"bh", "bhr"},
1510 {"bd", "bgd"},
1511 {"bb", "brb"},
1512 {"by", "blr"},
1513 {"be", "bel"},
1514 {"bz", "blz"},
1515 {"bj", "ben"},
1516 {"bm", "bmu"},
1517 {"bt", "btn"},
1518 {"bo", "bol"},
1519 {"ba", "bih"},
1520 {"bw", "bwa"},
1521 {"bv", "bvt"},
1522 {"br", "bra"},
1523 {"io", "iot"},
1524 {"bn", "brn"},
1525 {"bg", "bgr"},
1526 {"bf", "bfa"},
1527 {"bi", "bdi"},
1528 {"kh", "khm"},
1529 {"cm", "cmr"},
1530 {"ca", "can"},
1531 {"cv", "cpv"},
1532 {"ky", "cym"},
1533 {"cf", "caf"},
1534 {"td", "tcd"},
1535 {"cl", "chl"},
1536 {"cn", "chn"},
1537 {"cx", "cxr"},
1538 {"co", "col"},
1539 {"km", "com"},
1540 {"cg", "cog"},
1541 {"cd", "cod"},
1542 {"ck", "cok"},
1543 {"cr", "cri"},
1544 {"ci", "civ"},
1545 {"hr", "hrv"},
1546 {"cu", "cub"},
1547 {"cy", "cyp"},
1548 {"cz", "cze"},
1549 {"dk", "dnk"},
1550 {"dj", "dji"},
1551 {"dm", "dma"},
1552 {"do", "dom"},
1553 {"ec", "ecu"},
1554 {"eg", "egy"},
1555 {"sv", "slv"},
1556 {"gq", "gnq"},
1557 {"er", "eri"},
1558 {"ee", "est"},
1559 {"et", "eth"},
1560 {"fk", "flk"},
1561 {"fo", "fro"},
1562 {"fj", "fji"},
1563 {"fi", "fin"},
1564 {"fr", "fra"},
1565 {"gf", "guf"},
1566 {"pf", "pyf"},
1567 {"tf", "atf"},
1568 {"ga", "gab"},
1569 {"gm", "gmb"},
1570 {"ge", "geo"},
1571 {"de", "deu"},
1572 {"gh", "gha"},
1573 {"gi", "gib"},
1574 {"gr", "grc"},
1575 {"gl", "grl"},
1576 {"gd", "grd"},
1577 {"gp", "glp"},
1578 {"gu", "gum"},
1579 {"gt", "gtm"},
1580 {"gg", "ggy"},
1581 {"gn", "gin"},
1582 {"gw", "gnb"},
1583 {"gy", "guy"},
1584 {"ht", "hti"},
1585 {"hm", "hmd"},
1586 {"va", "vat"},
1587 {"hn", "hnd"},
1588 {"hk", "hkg"},
1589 {"hu", "hun"},
1590 {"is", "isl"},
1591 {"in", "ind"},
1592 {"id", "idn"},
1593 {"ir", "irn"},
1594 {"iq", "irq"},
1595 {"ie", "irl"},
1596 {"im", "imn"},
1597 {"il", "isr"},
1598 {"it", "ita"},
1599 {"jm", "jam"},
1600 {"jp", "jpn"},
1601 {"je", "jey"},
1602 {"jo", "jor"},
1603 {"kz", "kaz"},
1604 {"ke", "ken"},
1605 {"ki", "kir"},
1606 {"kp", "prk"},
1607 {"kr", "kor"},
1608 {"kw", "kwt"},
1609 {"kg", "kgz"},
1610 {"la", "lao"},
1611 {"lv", "lva"},
1612 {"lb", "lbn"},
1613 {"ls", "lso"},
1614 {"lr", "lbr"},
1615 {"ly", "lby"},
1616 {"li", "lie"},
1617 {"lt", "ltu"},
1618 {"lu", "lux"},
1619 {"mo", "mac"},
1620 {"mk", "mkd"},
1621 {"mg", "mdg"},
1622 {"mw", "mwi"},
1623 {"my", "mys"},
1624 {"mv", "mdv"},
1625 {"ml", "mli"},
1626 {"mt", "mlt"},
1627 {"mh", "mhl"},
1628 {"mq", "mtq"},
1629 {"mr", "mrt"},
1630 {"mu", "mus"},
1631 {"yt", "myt"},
1632 {"mx", "mex"},
1633 {"fm", "fsm"},
1634 {"md", "mda"},
1635 {"mc", "mco"},
1636 {"mn", "mng"},
1637 {"me", "mne"},
1638 {"ms", "msr"},
1639 {"ma", "mar"},
1640 {"mz", "moz"},
1641 {"mm", "mmr"},
1642 {"na", "nam"},
1643 {"nr", "nru"},
1644 {"np", "npl"},
1645 {"nl", "nld"},
1646 {"an", "ant"},
1647 {"nc", "ncl"},
1648 {"nz", "nzl"},
1649 {"ni", "nic"},
1650 {"ne", "ner"},
1651 {"ng", "nga"},
1652 {"nu", "niu"},
1653 {"nf", "nfk"},
1654 {"mp", "mnp"},
1655 {"no", "nor"},
1656 {"om", "omn"},
1657 {"pk", "pak"},
1658 {"pw", "plw"},
1659 {"ps", "pse"},
1660 {"pa", "pan"},
1661 {"pg", "png"},
1662 {"py", "pry"},
1663 {"pe", "per"},
1664 {"ph", "phl"},
1665 {"pn", "pcn"},
1666 {"pl", "pol"},
1667 {"pt", "prt"},
1668 {"pr", "pri"},
1669 {"qa", "qat"},
1670 {"re", "reu"},
1671 {"ro", "rou"},
1672 {"ru", "rus"},
1673 {"rw", "rwa"},
1674 {"bl", "blm"},
1675 {"sh", "shn"},
1676 {"kn", "kna"},
1677 {"lc", "lca"},
1678 {"mf", "maf"},
1679 {"pm", "spm"},
1680 {"vc", "vct"},
1681 {"ws", "wsm"},
1682 {"sm", "smr"},
1683 {"st", "stp"},
1684 {"sa", "sau"},
1685 {"sn", "sen"},
1686 {"rs", "srb"},
1687 {"sc", "syc"},
1688 {"sl", "sle"},
1689 {"sg", "sgp"},
1690 {"sk", "svk"},
1691 {"si", "svn"},
1692 {"sb", "slb"},
1693 {"so", "som"},
1694 {"za", "zaf"},
1695 {"gs", "sgs"},
1696 {"es", "esp"},
1697 {"lk", "lka"},
1698 {"sd", "sdn"},
1699 {"sr", "sur"},
1700 {"sj", "sjm"},
1701 {"sz", "swz"},
1702 {"se", "swe"},
1703 {"ch", "che"},
1704 {"sy", "syr"},
1705 {"tw", "twn"},
1706 {"tj", "tjk"},
1707 {"tz", "tza"},
1708 {"th", "tha"},
1709 {"tl", "tls"},
1710 {"tg", "tgo"},
1711 {"tk", "tkl"},
1712 {"to", "ton"},
1713 {"tt", "tto"},
1714 {"tn", "tun"},
1715 {"tr", "tur"},
1716 {"tm", "tkm"},
1717 {"tc", "tca"},
1718 {"tv", "tuv"},
1719 {"ug", "uga"},
1720 {"ua", "ukr"},
1721 {"ae", "are"},
1722 {"gb", "gbr"},
1723 {"us", "usa"},
1724 {"um", "umi"},
1725 {"uy", "ury"},
1726 {"uz", "uzb"},
1727 {"vu", "vut"},
1728 {"ve", "ven"},
1729 {"vn", "vnm"},
1730 {"vg", "vgb"},
1731 {"vi", "vir"},
1732 {"wf", "wlf"},
1733 {"eh", "esh"},
1734 {"ye", "yem"},
1735 {"zm", "zmb"},
1736 {"zw", "zwe"}
1737}};
1738// clang-format on