stdex
Additional custom or not Standard C++ covered algorithms
Loading...
Searching...
No Matches
langid.hpp
1/*
2 SPDX-License-Identifier: MIT
3 Copyright © 2024 Amebis
4*/
5
6#pragma once
7
8#include "compat.hpp"
9#include "string.hpp"
10#include "unicode.hpp"
11#ifdef _WIN32
12#include "windows.h"
13#endif
14#include <stddef.h>
15#include <stdint.h>
16#include <map>
17#include <string>
18
19#if defined(__GNUC__)
20#pragma GCC diagnostic push
21#pragma GCC diagnostic ignored "-Wexit-time-destructors"
22#endif
23
24namespace stdex
25{
26#ifdef _WIN32
27 using langid = LANGID;
28#else
29 using langid = uint16_t;
30#endif
31
32 constexpr langid langid_unknown = 127;
33 constexpr langid langid_system = 2048;
34
35 constexpr langid sublangid_neutral = 0<<10;
36 constexpr langid sublangid_default = 1<<10;
37 constexpr langid sublangid_sys_default = 2<<10;
38 constexpr langid sublangid_custom_default = 3<<10;
39 constexpr langid sublangid_custom_unspecified = 4<<10;
40 constexpr langid sublangid_ui_custom_default = 5<<10;
41
49 inline constexpr langid primary_langid(_In_ langid lang)
50 {
51 return lang & 0x3ff;
52 }
53
61 inline constexpr langid sub_langid(_In_ langid lang)
62 {
63 return lang & 0xfc00;
64 }
65
73 inline langid langid_from_rfc1766(_In_z_ const char* rfc1766)
74 {
75 struct stricmp_less
76 {
77 bool operator()(_In_z_ const char* str1, _In_z_ const char* str2) const
78 {
79 stdex_assert(str1);
80 stdex_assert(str2);
81 size_t i;
82 for (i = 0; ; ++i) {
83 auto a = stdex::tolower(str1[i]);
84 auto b = stdex::tolower(str2[i]);
85 auto a_end = !a || stdex::ispunct(a);
86 auto b_end = !b || stdex::ispunct(b);
87 if (a_end && b_end) return false;
88 if (b_end || a > b) return false;
89 if (a_end || a < b) return true;
90 }
91 }
92 };
93 struct language_mapping
94 {
95 langid id;
96 std::map<const char*, langid, stricmp_less> sublanguages;
97 };
98 static const std::map<const char*, language_mapping, stricmp_less> languages = {
99 {"af", {1078, {}}}, // Afrikaans
100 {"ar", {0x01, // Arabic
101 {
102 {"ae", static_cast<langid>(14337)}, // Arabic(U.A.E.)
103 {"bh", static_cast<langid>(15361)}, // Arabic(Bahrain)
104 {"dz", static_cast<langid>(5121)}, // Arabic(Algeria)
105 {"eg", static_cast<langid>(3073)}, // Arabic(Egypt)
106 {"iq", static_cast<langid>(2049)}, // Arabic(Iraq)
107 {"jo", static_cast<langid>(11265)}, // Arabic(Jordan)
108 {"kw", static_cast<langid>(13313)}, // Arabic(Kuwait)
109 {"lb", static_cast<langid>(12289)}, // Arabic(Lebanon)
110 {"ly", static_cast<langid>(4097)}, // Arabic(Libya)
111 {"ma", static_cast<langid>(6145)}, // Arabic(Morocco)
112 {"om", static_cast<langid>(8193)}, // Arabic(Oman)
113 {"qa", static_cast<langid>(16385)}, // Arabic(Qatar)
114 {"sa", static_cast<langid>(1025)}, // Arabic(Saudi Arabia)
115 {"sy", static_cast<langid>(10241)}, // Arabic(Syria)
116 {"tn", static_cast<langid>(7169)}, // Arabic(Tunisia)
117 {"ye", static_cast<langid>(9217)}, // Arabic(Yemen)
118 }}},
119 {"be", {1059, {}}}, // Belarusian
120 {"bg", {1026, {}}}, // Bulgarian
121 {"ca", {1027, {}}}, // Catalan
122 {"cs", {1029, {}}}, // Czech
123 {"da", {1030, {}}}, // Danish
124 {"de", {0x07, // German
125 {
126 {"at", static_cast<langid>(3079)}, // German(Austrian)
127 {"ch", static_cast<langid>(2055)}, // German(Swiss)
128 {"de", static_cast<langid>(1031)}, // German(Germany)
129 {"li", static_cast<langid>(5127)}, // German(Liechtenstein)
130 {"lu", static_cast<langid>(4103)}, // German(Luxembourg)
131 }}},
132 {"el", {1032, {}}}, // Greek
133 {"en", {0x09, // English
134 {
135 {"au", static_cast<langid>(3081)}, // English(Australian)
136 {"bz", static_cast<langid>(10249)}, // English(Belize)
137 {"ca", static_cast<langid>(4105)}, // English(Canadian)
138 {"ca", static_cast<langid>(9225)}, // English(Caribbean)
139 {"gb", static_cast<langid>(2057)}, // English(British)
140 {"ie", static_cast<langid>(6153)}, // English(Ireland)
141 {"jm", static_cast<langid>(8201)}, // English(Jamaica)
142 {"nz", static_cast<langid>(5129)}, // English(New Zealand)
143 {"tt", static_cast<langid>(11273)}, // English(Trinidad)
144 {"us", static_cast<langid>(1033)}, // English(United States)
145 {"za", static_cast<langid>(7177)}, // English(South Africa)
146 }}},
147 {"es", {0x0a, // Spanish
148 {
149 {"ar", static_cast<langid>(11274)}, // Spanish(Argentina)
150 {"bo", static_cast<langid>(16394)}, // Spanish(Bolivia)
151 {"cl", static_cast<langid>(13322)}, // Spanish(Chile)
152 {"co", static_cast<langid>(9226)}, // Spanish(Colombia)
153 {"cr", static_cast<langid>(5130)}, // Spanish(Costa Rica)
154 {"do", static_cast<langid>(7178)}, // Spanish(Dominican Republic)
155 {"ec", static_cast<langid>(12298)}, // Spanish(Ecuador)
156 {"es", static_cast<langid>(1034)}, // Spanish(Spain)
157 {"gt", static_cast<langid>(4106)}, // Spanish(Guatemala)
158 {"hn", static_cast<langid>(18442)}, // Spanish(Honduras)
159 {"mx", static_cast<langid>(2058)}, // Spanish(Mexican)
160 {"ni", static_cast<langid>(19466)}, // Spanish(Nicaragua)
161 {"pa", static_cast<langid>(6154)}, // Spanish(Panama)
162 {"pe", static_cast<langid>(10250)}, // Spanish(Peru)
163 {"pr", static_cast<langid>(20490)}, // Spanish(Puerto Rico)
164 {"py", static_cast<langid>(15370)}, // Spanish(Paraguay)
165 {"sv", static_cast<langid>(17418)}, // Spanish(El Salvador)
166 {"uy", static_cast<langid>(14346)}, // Spanish(Uruguay)
167 {"ve", static_cast<langid>(8202)}, // Spanish(Venezuela)
168 }}},
169 {"et", {1061, {}}}, // Estonian
170 {"eu", {1069, {}}}, // Basque
171 {"fa", {1065, {}}}, // Farsi
172 {"fi", {1035, {}}}, // Finnish
173 {"fo", {1080, {}}}, // Faeroese
174 {"fr", {0x0c, // French
175 {
176 {"be", static_cast<langid>(2060)}, // French(Belgian)
177 {"ca", static_cast<langid>(3084)}, // French(Canadian)
178 {"ch", static_cast<langid>(4108)}, // French(Swiss)
179 {"fr", static_cast<langid>(1036)}, // French(Luxembourg)
180 {"lu", static_cast<langid>(5132)}, // French(Luxembourg)
181 }}},
182 {"gd", {1084, {}}}, // Gaelic(Scots)
183 {"he", {1037, {}}}, // Hebrew
184 {"hi", {1081, {}}}, // Hindi
185 {"hr", {1050, {}}}, // Croatian
186 {"hu", {1038, {}}}, // Hungarian
187 {"in", {1057, {}}}, // Indonesian
188 {"is", {1039, {}}}, // Icelandic
189 {"it", {0x10, // Italian
190 {
191 {"ch", static_cast<langid>(2064)}, // Italian(Swiss)
192 {"it", static_cast<langid>(1040)}, // Italian(Italy)
193 }}},
194 {"ja", {1041, {}}}, // Japanese
195 {"ji", {1085, {}}}, // Yiddish
196 {"ko", {0x12, // Korean
197 {
198 {"johab", static_cast<langid>(2066)}, // Korean(Johab)
199 {"kr", static_cast<langid>(1042)}, // Korean(Korea)
200 }}},
201 {"lt", {1063, {}}}, // Lithuanian
202 {"lv", {1062, {}}}, // Latvian
203 {"mk", {1071, {}}}, // Macedonian (FYROM)
204 {"ms", {1086, {}}}, // Malaysian
205 {"mt", {1082, {}}}, // Maltese
206 {"nl", {0x13, // Dutch
207 {
208 {"be", static_cast<langid>(2067)}, // Dutch(Belgian)
209 {"nl", static_cast<langid>(1043)}, // Dutch(Netherland)
210 }}},
211 {"no", {0x14, // Norwegian
212 {
213 {"bokmaal", static_cast<langid>(1044)}, // Norwegian(Bokmaal)
214 {"nynorsk", static_cast<langid>(2068)}, // Norwegian(Nynorsk)
215 }}},
216 {"pl", {1045, {}}}, // Polish
217 {"pt", {0x16, // Portuguese
218 {
219 {"br", static_cast<langid>(1046)}, // Portuguese(Brazil)
220 {"pt", static_cast<langid>(2070)}, // Portuguese(Portugal)
221 }}},
222 {"rm", {1047, {}}}, // Rhaeto-Romanic
223 {"ro", {0x18, // Romanian
224 {
225 {"mo", static_cast<langid>(2072)}, // Romanian(Moldavia)
226 {"ro", static_cast<langid>(1048)}, // Romanian(Romania)
227 }}},
228 {"ru", {0x19, // Russian
229 {
230 {"mo", static_cast<langid>(2073)}, // Russian(Moldavia)
231 {"ru", static_cast<langid>(1049)}, // Russian(Russia)
232 }}},
233 {"sb", {1070, {}}}, // Sorbian
234 {"sk", {1051, {}}}, // Slovak
235 {"sl", {1060, {}}}, // Slovenian
236 {"sq", {1052, {}}}, // Albanian
237 {"sr", {0x1a, // Serbian
238 {
239 {"cyrillic", static_cast<langid>(3098)}, // Serbian(Cyrillic)
240 {"latin", static_cast<langid>(2074)}, // Serbian(Latin)
241 }}},
242 {"sv", {0x1d, // Swedish
243 {
244 {"fi", static_cast<langid>(2077)}, // Swedish(Finland)
245 {"se", static_cast<langid>(1053)}, // Swedish(Sweden)
246 }}},
247 {"sx", {1072, {}}}, // Sutu
248 {"sz", {1083, {}}}, // Sami(Lappish)
249 {"th", {1054, {}}}, // Thai
250 {"tn", {1074, {}}}, // Tswana
251 {"tr", {1055, {}}}, // Turkish
252 {"ts", {1073, {}}}, // Tsonga
253 {"uk", {1058, {}}}, // Ukrainian
254 {"ur", {1056, {}}}, // Urdu
255 {"ve", {1075, {}}}, // Venda
256 {"vi", {1066, {}}}, // Vietnamese
257 {"xh", {1076, {}}}, // Xhosa
258 {"zh", {0x04, // Chinese
259 {
260 {"cn", static_cast<langid>(2052)}, // Chinese(PRC)
261 {"hk", static_cast<langid>(3076)}, // Chinese(Hong Kong)
262 {"sg", static_cast<langid>(4100)}, // Chinese(Singapore)
263 {"tw", static_cast<langid>(1028)}, // Chinese(Taiwan)
264 }}},
265 {"zu", {1077, {}}}, // Zulu
266 };
267
268 if (auto el = languages.find(rfc1766); el != languages.end()) {
269 if (!el->second.sublanguages.empty()) {
270 if (auto n = stdex::strlen(el->first); ispunct(rfc1766[n])) {
271 n++;
272 if (auto el_sub = el->second.sublanguages.find(&rfc1766[n]); el_sub != el->second.sublanguages.end())
273 return el_sub->second;
274 }
275 }
276 return el->second.id;
277 }
278 return langid_unknown;
279 }
280
289 inline _Ret_maybenull_z_ const char *rfc1766_from_langid(_In_ langid lang, _In_opt_z_ const char* fallback = nullptr)
290 {
291 static const std::map<langid, const char *> languages = {
292 {1, "ar"},
293 {2, "bg-bg"},
294 {3, "ca-es"},
295 {4, "zh"},
296 {5, "cs-cz"},
297 {6, "da-dk"},
298 {7, "de-de"},
299 {8, "el-gr"},
300 {9, "en"},
301 {10, "es-es"},
302 {11, "fi-fi"},
303 {12, "fr-fr"},
304 {13, "he-il"},
305 {14, "hu-hu"},
306 {15, "is-is"},
307 {16, "it-it"},
308 {17, "ja-jp"},
309 {18, "ko-kr"},
310 {19, "nl-nl"},
311 {20, "nb-no"},
312 {21, "pl-pl"},
313 {22, "pt-br"},
314 {23, "rm-ch"},
315 {24, "ro-ro"},
316 {25, "ru-ru"},
317 {26, "hr-hr"},
318 {27, "sk-sk"},
319 {28, "sq-al"},
320 {29, "sv-se"},
321 {30, "th-th"},
322 {31, "tr-tr"},
323 {32, "ur-pk"},
324 {33, "id-id"},
325 {34, "uk-ua"},
326 {35, "be-by"},
327 {36, "sl-si"},
328 {37, "et-ee"},
329 {38, "lv-lv"},
330 {39, "lt-lt"},
331 {40, "tg-tj"},
332 {41, "fa-ir"},
333 {42, "vi-vn"},
334 {43, "hy-am"},
335 {44, "az-az"},
336 {45, "eu-es"},
337 {46, "hsb"},
338 {47, "mk-mk"},
339 {48, "st-za"},
340 {49, "ts-za"},
341 {50, "tn-za"},
342 {51, "ve-za"},
343 {52, "xh-za"},
344 {53, "zu-za"},
345 {54, "af-za"},
346 {55, "ka-ge"},
347 {56, "fo-fo"},
348 {57, "hi-in"},
349 {58, "mt-mt"},
350 {59, "se-no"},
351 {60, "ga-ie"},
352 {61, "yi"},
353 {62, "ms-my"},
354 {63, "kk-kz"},
355 {64, "ky-kg"},
356 {65, "sw-ke"},
357 {66, "tk-tm"},
358 {67, "uz-uz"},
359 {68, "tt-ru"},
360 {69, "bn-bd"},
361 {70, "pa-in"},
362 {71, "gu-in"},
363 {72, "or-in"},
364 {73, "ta-in"},
365 {74, "te-in"},
366 {75, "kn-in"},
367 {76, "ml-in"},
368 {77, "as-in"},
369 {78, "mr-in"},
370 {79, "sa-in"},
371 {80, "mn-mn"},
372 {81, "bo-cn"},
373 {82, "cy-gb"},
374 {83, "km-kh"},
375 {84, "lo-la"},
376 {85, "my-mm"},
377 {86, "gl-es"},
378 {87, "kok"},
379 {88, "mni"},
380 {89, "sd-pk"},
381 {90, "syr"},
382 {91, "si-lk"},
383 {92, "chr"},
384 {93, "iu-ca"},
385 {94, "am-et"},
386 {95, "tzm"},
387 {96, "ks-in"},
388 {97, "ne-np"},
389 {98, "fy-nl"},
390 {99, "ps-af"},
391 {100, "fil"},
392 {101, "dv-mv"},
393 {102, "bin"},
394 {103, "ff-sn"},
395 {104, "ha-ng"},
396 {105, "ibb"},
397 {106, "yo-ng"},
398 {107, "quz"},
399 {108, "nso"},
400 {109, "ba-ru"},
401 {110, "lb-lu"},
402 {111, "kl-gl"},
403 {112, "ig-ng"},
404 {113, "kr-ng"},
405 {114, "om-et"},
406 {115, "ti-er"},
407 {116, "gn-py"},
408 {117, "haw"},
409 {118, "la-va"},
410 {119, "so-so"},
411 {120, "ii-cn"},
412 {121, "pap"},
413 {122, "arn"},
414 {124, "moh"},
415 {126, "br-fr"},
416 {127, "iv-iv"},
417 {128, "ug-cn"},
418 {129, "mi-nz"},
419 {130, "oc-fr"},
420 {131, "co-fr"},
421 {132, "gsw"},
422 {133, "sah"},
423 {134, "quc"},
424 {135, "rw-rw"},
425 {136, "wo-sn"},
426 {140, "fa-ir"},
427 {145, "gd-gb"},
428 {146, "ku-iq"},
429 {1025, "ar-sa"},
430 {1026, "bg"},
431 {1027, "ca"},
432 {1028, "zh-tw"},
433 {1029, "cs"},
434 {1030, "da"},
435 {1031, "de"},
436 {1032, "el"},
437 {1033, "en-us"},
438 {1034, "es"},
439 {1035, "fi"},
440 {1036, "fr"},
441 {1037, "he"},
442 {1038, "hu"},
443 {1039, "is"},
444 {1040, "it"},
445 {1041, "ja"},
446 {1042, "ko"},
447 {1043, "nl"},
448 {1044, "no"},
449 {1045, "pl"},
450 {1046, "pt-br"},
451 {1047, "rm"},
452 {1048, "ro"},
453 {1049, "ru"},
454 {1050, "hr"},
455 {1051, "sk"},
456 {1052, "sq"},
457 {1053, "sv"},
458 {1054, "th"},
459 {1055, "tr"},
460 {1056, "ur"},
461 {1057, "id"},
462 {1058, "uk"},
463 {1059, "be"},
464 {1060, "sl"},
465 {1061, "et"},
466 {1062, "lv"},
467 {1063, "lt"},
468 {1064, "tg-tj"},
469 {1065, "fa"},
470 {1066, "vi"},
471 {1067, "hy"},
472 {1068, "az"},
473 {1069, "eu"},
474 {1070, "sb"},
475 {1071, "mk"},
476 {1072, "sx"},
477 {1073, "ts"},
478 {1074, "tn"},
479 {1075, "ve-za"},
480 {1076, "xh"},
481 {1077, "zu"},
482 {1078, "af"},
483 {1079, "ka"},
484 {1080, "fo"},
485 {1081, "hi"},
486 {1082, "mt"},
487 {1083, "se-no"},
488 {1084, "gd"},
489 {1085, "yi"},
490 {1086, "ms"},
491 {1087, "kk"},
492 {1088, "kz"},
493 {1089, "sw"},
494 {1090, "tk-tm"},
495 {1091, "uz"},
496 {1092, "tt"},
497 {1093, "bn"},
498 {1094, "pa"},
499 {1095, "gu"},
500 {1096, "or"},
501 {1097, "ta"},
502 {1098, "te"},
503 {1099, "kn"},
504 {1100, "ml"},
505 {1101, "as"},
506 {1102, "mr"},
507 {1103, "sa"},
508 {1104, "mn"},
509 {1105, "bo-cn"},
510 {1106, "cy-gb"},
511 {1107, "km-kh"},
512 {1108, "lo-la"},
513 {1109, "my-mm"},
514 {1110, "gl"},
515 {1111, "kok"},
516 {1112, "mni"},
517 {1113, "sd-in"},
518 {1114, "syr"},
519 {1115, "si-lk"},
520 {1116, "chr"},
521 {1117, "iu-ca"},
522 {1118, "am-et"},
523 {1119, "tzm"},
524 {1120, "ks-in"},
525 {1121, "ne-np"},
526 {1122, "fy-nl"},
527 {1123, "ps-af"},
528 {1124, "fil"},
529 {1125, "div"},
530 {1126, "bin"},
531 {1127, "ff-ng"},
532 {1128, "ha-ng"},
533 {1129, "ibb"},
534 {1130, "yo-ng"},
535 {1131, "quz"},
536 {1132, "nso"},
537 {1133, "ba-ru"},
538 {1134, "lb-lu"},
539 {1135, "kl-gl"},
540 {1136, "ig-ng"},
541 {1137, "kr-ng"},
542 {1138, "om-et"},
543 {1139, "ti-et"},
544 {1140, "gn-py"},
545 {1141, "haw"},
546 {1142, "la-va"},
547 {1143, "so-so"},
548 {1144, "ii-cn"},
549 {1145, "pap"},
550 {1146, "arn"},
551 {1148, "moh"},
552 {1150, "br-fr"},
553 {1152, "ug-cn"},
554 {1153, "mi-nz"},
555 {1154, "oc-fr"},
556 {1155, "co-fr"},
557 {1156, "gsw"},
558 {1157, "sah"},
559 {1158, "quc"},
560 {1159, "rw-rw"},
561 {1160, "wo-sn"},
562 {1164, "fa-af"},
563 {1169, "gd-gb"},
564 {1170, "ku-iq"},
565 {1281, "en-us"},
566 {1534, "qps"},
567 {2049, "ar-iq"},
568 {2051, "ca-es"},
569 {2052, "zh-cn"},
570 {2055, "de-ch"},
571 {2057, "en-gb"},
572 {2058, "es-mx"},
573 {2060, "fr-be"},
574 {2064, "it-ch"},
575 {2067, "nl-be"},
576 {2068, "nn-no"},
577 {2070, "pt"},
578 {2072, "ro-md"},
579 {2073, "ru-md"},
580 {2074, "sr"},
581 {2077, "sv-fi"},
582 {2080, "ur-in"},
583 {2092, "az"},
584 {2094, "dsb"},
585 {2098, "tn-bw"},
586 {2107, "se-se"},
587 {2108, "ga-ie"},
588 {2110, "ms"},
589 {2115, "uz"},
590 {2117, "bn-bd"},
591 {2118, "pa-pk"},
592 {2121, "ta-lk"},
593 {2128, "mn-cn"},
594 {2137, "sd-pk"},
595 {2141, "iu-ca"},
596 {2143, "tzm"},
597 {2144, "ks-in"},
598 {2145, "ne"},
599 {2151, "ff-sn"},
600 {2155, "quz"},
601 {2163, "ti-er"},
602 {2305, "en-us"},
603 {2559, "ar-sa"},
604 {3073, "ar-eg"},
605 {3076, "zh-hk"},
606 {3079, "de-at"},
607 {3081, "en-au"},
608 {3082, "es"},
609 {3084, "fr-ca"},
610 {3098, "sr"},
611 {3131, "se-fi"},
612 {3152, "mn-mn"},
613 {3153, "dz-bt"},
614 {3179, "quz"},
615 {4096, "ks-in"},
616 {4097, "ar-ly"},
617 {4100, "zh-sg"},
618 {4103, "de-lu"},
619 {4105, "en-ca"},
620 {4106, "es-gt"},
621 {4108, "fr-ch"},
622 {4122, "hr-ba"},
623 {4155, "smj"},
624 {4191, "tzm"},
625 {5120, "en-us"},
626 {5121, "ar-dz"},
627 {5124, "zh-mo"},
628 {5127, "de-li"},
629 {5129, "en-nz"},
630 {5130, "es-cr"},
631 {5132, "fr-lu"},
632 {5146, "bs-ba"},
633 {5179, "smj"},
634 {6145, "ar-ma"},
635 {6153, "en-ie"},
636 {6154, "es-pa"},
637 {6156, "fr-mc"},
638 {6170, "sr-ba"},
639 {6203, "sma"},
640 {7169, "ar-tn"},
641 {7177, "en-za"},
642 {7178, "es-do"},
643 {7180, "fr"},
644 {7194, "sr-ba"},
645 {7227, "sma"},
646 {8193, "ar-om"},
647 {8201, "en-jm"},
648 {8202, "es-ve"},
649 {8204, "fr-re"},
650 {8218, "bs-ba"},
651 {8251, "sms"},
652 {9217, "ar-ye"},
653 {9225, "en"},
654 {9226, "es-co"},
655 {9228, "fr-cd"},
656 {9242, "sr-rs"},
657 {9275, "smn"},
658 {10241, "ar-sy"},
659 {10249, "en-bz"},
660 {10250, "es-pe"},
661 {10252, "fr-sn"},
662 {10266, "sr-rs"},
663 {11265, "ar-jo"},
664 {11273, "en-tt"},
665 {11274, "es-ar"},
666 {11276, "fr-cm"},
667 {11290, "sr-me"},
668 {12289, "ar-lb"},
669 {12297, "en-zw"},
670 {12298, "es-ec"},
671 {12300, "fr-ci"},
672 {12314, "sr-me"},
673 {13313, "ar-kw"},
674 {13321, "en-ph"},
675 {13322, "es-cl"},
676 {13324, "fr-ml"},
677 {14337, "ar-ae"},
678 {14345, "en-id"},
679 {14346, "es-uy"},
680 {14348, "fr-ma"},
681 {15361, "ar-bh"},
682 {15369, "en-hk"},
683 {15370, "es-py"},
684 {15372, "fr-ht"},
685 {16385, "ar-qa"},
686 {16393, "en-in"},
687 {16394, "es-bo"},
688 {17417, "en-my"},
689 {17418, "es-sv"},
690 {18441, "en-sg"},
691 {18442, "es-hn"},
692 {19465, "en-ae"},
693 {19466, "es-ni"},
694 {20490, "es-pr"},
695 {21514, "es-us"},
696 {22538, "es"},
697 {23562, "es-cu"},
698 {25626, "bs-ba"},
699 {26650, "bs-ba"},
700 {27674, "sr-rs"},
701 {28698, "sr-rs"},
702 {28731, "smn"},
703 {29740, "az-az"},
704 {29755, "sms"},
705 {30724, "zh-cn"},
706 {30740, "nn-no"},
707 {30746, "bs-ba"},
708 {30764, "az-az"},
709 {30779, "sma"},
710 {30787, "uz-uz"},
711 {30800, "mn-mn"},
712 {30813, "iu-ca"},
713 {30815, "tzm"},
714 {31748, "zh-hk"},
715 {31764, "nb-no"},
716 {31770, "sr-rs"},
717 {31784, "tg-tj"},
718 {31790, "dsb"},
719 {31803, "smj"},
720 {31811, "uz-uz"},
721 {31814, "pa-pk"},
722 {31824, "mn-cn"},
723 {31833, "sd-pk"},
724 {31836, "chr"},
725 {31837, "iu-ca"},
726 {31839, "tzm"},
727 {31847, "ff-sn"},
728 {31848, "ha-ng"},
729 {31878, "quc"},
730 {31890, "ku-iq"},
731 };
732 if (auto el = languages.find(lang); el != languages.end())
733 return el->second;
734 return fallback;
735 }
736}
737
738#if defined(__GNUC__)
739#pragma GCC diagnostic pop
740#endif