timespec_get: New module.
[gnulib.git] / lib / localename.c
blob4c785f11f034c8d9deaf6729f6878313145be058
1 /* Determine name of the currently selected locale.
2 Copyright (C) 1995-2021 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation; either version 2.1 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
17 /* Written by Ulrich Drepper <drepper@gnu.org>, 1995. */
18 /* Native Windows code written by Tor Lillqvist <tml@iki.fi>. */
19 /* Mac OS X code written by Bruno Haible <bruno@clisp.org>. */
21 #include <config.h>
23 /* Specification. */
24 #ifdef IN_LIBINTL
25 # include "gettextP.h"
26 #else
27 # include "localename.h"
28 #endif
30 #include <limits.h>
31 #include <stdbool.h>
32 #include <stddef.h>
33 #include <stdlib.h>
34 #include <locale.h>
35 #include <string.h>
37 #include "flexmember.h"
38 #include "setlocale_null.h"
39 #include "thread-optim.h"
41 /* We cannot support uselocale() on platforms where the locale_t type is fake.
42 See intl-thread-locale.m4 for details. */
43 #if HAVE_WORKING_USELOCALE && !HAVE_FAKE_LOCALES
44 # define HAVE_GOOD_USELOCALE 1
45 #endif
47 #if HAVE_GOOD_USELOCALE
48 /* Mac OS X 10.5 defines the locale_t type in <xlocale.h>. */
49 # if defined __APPLE__ && defined __MACH__
50 # include <xlocale.h>
51 # endif
52 # if (__GLIBC__ >= 2 && !defined __UCLIBC__) || (defined __linux__ && HAVE_LANGINFO_H) || defined __CYGWIN__
53 # include <langinfo.h>
54 # endif
55 # if !defined IN_LIBINTL
56 # include "glthread/lock.h"
57 # endif
58 # if defined __sun
59 # if HAVE_GETLOCALENAME_L
60 /* Solaris >= 12. */
61 extern char * getlocalename_l(int, locale_t);
62 # elif HAVE_SOLARIS114_LOCALES
63 # include <sys/localedef.h>
64 # endif
65 # endif
66 # if HAVE_NAMELESS_LOCALES
67 # include <errno.h>
68 # include "localename-table.h"
69 # endif
70 #endif
72 #if HAVE_CFPREFERENCESCOPYAPPVALUE
73 # include <CoreFoundation/CFString.h>
74 # include <CoreFoundation/CFPreferences.h>
75 #endif
77 #if defined _WIN32 && !defined __CYGWIN__
78 # define WINDOWS_NATIVE
79 # if !defined IN_LIBINTL
80 # include "glthread/lock.h"
81 # endif
82 #endif
84 #if defined WINDOWS_NATIVE || defined __CYGWIN__ /* Native Windows or Cygwin */
85 # define WIN32_LEAN_AND_MEAN
86 # include <windows.h>
87 # include <winnls.h>
88 /* List of language codes, sorted by value:
89 0x01 LANG_ARABIC
90 0x02 LANG_BULGARIAN
91 0x03 LANG_CATALAN
92 0x04 LANG_CHINESE
93 0x05 LANG_CZECH
94 0x06 LANG_DANISH
95 0x07 LANG_GERMAN
96 0x08 LANG_GREEK
97 0x09 LANG_ENGLISH
98 0x0a LANG_SPANISH
99 0x0b LANG_FINNISH
100 0x0c LANG_FRENCH
101 0x0d LANG_HEBREW
102 0x0e LANG_HUNGARIAN
103 0x0f LANG_ICELANDIC
104 0x10 LANG_ITALIAN
105 0x11 LANG_JAPANESE
106 0x12 LANG_KOREAN
107 0x13 LANG_DUTCH
108 0x14 LANG_NORWEGIAN
109 0x15 LANG_POLISH
110 0x16 LANG_PORTUGUESE
111 0x17 LANG_ROMANSH
112 0x18 LANG_ROMANIAN
113 0x19 LANG_RUSSIAN
114 0x1a LANG_CROATIAN == LANG_SERBIAN
115 0x1b LANG_SLOVAK
116 0x1c LANG_ALBANIAN
117 0x1d LANG_SWEDISH
118 0x1e LANG_THAI
119 0x1f LANG_TURKISH
120 0x20 LANG_URDU
121 0x21 LANG_INDONESIAN
122 0x22 LANG_UKRAINIAN
123 0x23 LANG_BELARUSIAN
124 0x24 LANG_SLOVENIAN
125 0x25 LANG_ESTONIAN
126 0x26 LANG_LATVIAN
127 0x27 LANG_LITHUANIAN
128 0x28 LANG_TAJIK
129 0x29 LANG_FARSI
130 0x2a LANG_VIETNAMESE
131 0x2b LANG_ARMENIAN
132 0x2c LANG_AZERI
133 0x2d LANG_BASQUE
134 0x2e LANG_SORBIAN
135 0x2f LANG_MACEDONIAN
136 0x30 LANG_SUTU
137 0x31 LANG_TSONGA
138 0x32 LANG_TSWANA
139 0x33 LANG_VENDA
140 0x34 LANG_XHOSA
141 0x35 LANG_ZULU
142 0x36 LANG_AFRIKAANS
143 0x37 LANG_GEORGIAN
144 0x38 LANG_FAEROESE
145 0x39 LANG_HINDI
146 0x3a LANG_MALTESE
147 0x3b LANG_SAMI
148 0x3c LANG_GAELIC
149 0x3d LANG_YIDDISH
150 0x3e LANG_MALAY
151 0x3f LANG_KAZAK
152 0x40 LANG_KYRGYZ
153 0x41 LANG_SWAHILI
154 0x42 LANG_TURKMEN
155 0x43 LANG_UZBEK
156 0x44 LANG_TATAR
157 0x45 LANG_BENGALI
158 0x46 LANG_PUNJABI
159 0x47 LANG_GUJARATI
160 0x48 LANG_ORIYA
161 0x49 LANG_TAMIL
162 0x4a LANG_TELUGU
163 0x4b LANG_KANNADA
164 0x4c LANG_MALAYALAM
165 0x4d LANG_ASSAMESE
166 0x4e LANG_MARATHI
167 0x4f LANG_SANSKRIT
168 0x50 LANG_MONGOLIAN
169 0x51 LANG_TIBETAN
170 0x52 LANG_WELSH
171 0x53 LANG_CAMBODIAN
172 0x54 LANG_LAO
173 0x55 LANG_BURMESE
174 0x56 LANG_GALICIAN
175 0x57 LANG_KONKANI
176 0x58 LANG_MANIPURI
177 0x59 LANG_SINDHI
178 0x5a LANG_SYRIAC
179 0x5b LANG_SINHALESE
180 0x5c LANG_CHEROKEE
181 0x5d LANG_INUKTITUT
182 0x5e LANG_AMHARIC
183 0x5f LANG_TAMAZIGHT
184 0x60 LANG_KASHMIRI
185 0x61 LANG_NEPALI
186 0x62 LANG_FRISIAN
187 0x63 LANG_PASHTO
188 0x64 LANG_TAGALOG
189 0x65 LANG_DIVEHI
190 0x66 LANG_EDO
191 0x67 LANG_FULFULDE
192 0x68 LANG_HAUSA
193 0x69 LANG_IBIBIO
194 0x6a LANG_YORUBA
195 0x6d LANG_BASHKIR
196 0x6e LANG_LUXEMBOURGISH
197 0x6f LANG_GREENLANDIC
198 0x70 LANG_IGBO
199 0x71 LANG_KANURI
200 0x72 LANG_OROMO
201 0x73 LANG_TIGRINYA
202 0x74 LANG_GUARANI
203 0x75 LANG_HAWAIIAN
204 0x76 LANG_LATIN
205 0x77 LANG_SOMALI
206 0x78 LANG_YI
207 0x79 LANG_PAPIAMENTU
208 0x7a LANG_MAPUDUNGUN
209 0x7c LANG_MOHAWK
210 0x7e LANG_BRETON
211 0x82 LANG_OCCITAN
212 0x83 LANG_CORSICAN
213 0x84 LANG_ALSATIAN
214 0x85 LANG_YAKUT
215 0x86 LANG_KICHE
216 0x87 LANG_KINYARWANDA
217 0x88 LANG_WOLOF
218 0x8c LANG_DARI
219 0x91 LANG_SCOTTISH_GAELIC
221 /* Mingw headers don't have latest language and sublanguage codes. */
222 # ifndef LANG_AFRIKAANS
223 # define LANG_AFRIKAANS 0x36
224 # endif
225 # ifndef LANG_ALBANIAN
226 # define LANG_ALBANIAN 0x1c
227 # endif
228 # ifndef LANG_ALSATIAN
229 # define LANG_ALSATIAN 0x84
230 # endif
231 # ifndef LANG_AMHARIC
232 # define LANG_AMHARIC 0x5e
233 # endif
234 # ifndef LANG_ARABIC
235 # define LANG_ARABIC 0x01
236 # endif
237 # ifndef LANG_ARMENIAN
238 # define LANG_ARMENIAN 0x2b
239 # endif
240 # ifndef LANG_ASSAMESE
241 # define LANG_ASSAMESE 0x4d
242 # endif
243 # ifndef LANG_AZERI
244 # define LANG_AZERI 0x2c
245 # endif
246 # ifndef LANG_BASHKIR
247 # define LANG_BASHKIR 0x6d
248 # endif
249 # ifndef LANG_BASQUE
250 # define LANG_BASQUE 0x2d
251 # endif
252 # ifndef LANG_BELARUSIAN
253 # define LANG_BELARUSIAN 0x23
254 # endif
255 # ifndef LANG_BENGALI
256 # define LANG_BENGALI 0x45
257 # endif
258 # ifndef LANG_BRETON
259 # define LANG_BRETON 0x7e
260 # endif
261 # ifndef LANG_BURMESE
262 # define LANG_BURMESE 0x55
263 # endif
264 # ifndef LANG_CAMBODIAN
265 # define LANG_CAMBODIAN 0x53
266 # endif
267 # ifndef LANG_CATALAN
268 # define LANG_CATALAN 0x03
269 # endif
270 # ifndef LANG_CHEROKEE
271 # define LANG_CHEROKEE 0x5c
272 # endif
273 # ifndef LANG_CORSICAN
274 # define LANG_CORSICAN 0x83
275 # endif
276 # ifndef LANG_DARI
277 # define LANG_DARI 0x8c
278 # endif
279 # ifndef LANG_DIVEHI
280 # define LANG_DIVEHI 0x65
281 # endif
282 # ifndef LANG_EDO
283 # define LANG_EDO 0x66
284 # endif
285 # ifndef LANG_ESTONIAN
286 # define LANG_ESTONIAN 0x25
287 # endif
288 # ifndef LANG_FAEROESE
289 # define LANG_FAEROESE 0x38
290 # endif
291 # ifndef LANG_FARSI
292 # define LANG_FARSI 0x29
293 # endif
294 # ifndef LANG_FRISIAN
295 # define LANG_FRISIAN 0x62
296 # endif
297 # ifndef LANG_FULFULDE
298 # define LANG_FULFULDE 0x67
299 # endif
300 # ifndef LANG_GAELIC
301 # define LANG_GAELIC 0x3c
302 # endif
303 # ifndef LANG_GALICIAN
304 # define LANG_GALICIAN 0x56
305 # endif
306 # ifndef LANG_GEORGIAN
307 # define LANG_GEORGIAN 0x37
308 # endif
309 # ifndef LANG_GREENLANDIC
310 # define LANG_GREENLANDIC 0x6f
311 # endif
312 # ifndef LANG_GUARANI
313 # define LANG_GUARANI 0x74
314 # endif
315 # ifndef LANG_GUJARATI
316 # define LANG_GUJARATI 0x47
317 # endif
318 # ifndef LANG_HAUSA
319 # define LANG_HAUSA 0x68
320 # endif
321 # ifndef LANG_HAWAIIAN
322 # define LANG_HAWAIIAN 0x75
323 # endif
324 # ifndef LANG_HEBREW
325 # define LANG_HEBREW 0x0d
326 # endif
327 # ifndef LANG_HINDI
328 # define LANG_HINDI 0x39
329 # endif
330 # ifndef LANG_IBIBIO
331 # define LANG_IBIBIO 0x69
332 # endif
333 # ifndef LANG_IGBO
334 # define LANG_IGBO 0x70
335 # endif
336 # ifndef LANG_INDONESIAN
337 # define LANG_INDONESIAN 0x21
338 # endif
339 # ifndef LANG_INUKTITUT
340 # define LANG_INUKTITUT 0x5d
341 # endif
342 # ifndef LANG_KANNADA
343 # define LANG_KANNADA 0x4b
344 # endif
345 # ifndef LANG_KANURI
346 # define LANG_KANURI 0x71
347 # endif
348 # ifndef LANG_KASHMIRI
349 # define LANG_KASHMIRI 0x60
350 # endif
351 # ifndef LANG_KAZAK
352 # define LANG_KAZAK 0x3f
353 # endif
354 # ifndef LANG_KICHE
355 # define LANG_KICHE 0x86
356 # endif
357 # ifndef LANG_KINYARWANDA
358 # define LANG_KINYARWANDA 0x87
359 # endif
360 # ifndef LANG_KONKANI
361 # define LANG_KONKANI 0x57
362 # endif
363 # ifndef LANG_KYRGYZ
364 # define LANG_KYRGYZ 0x40
365 # endif
366 # ifndef LANG_LAO
367 # define LANG_LAO 0x54
368 # endif
369 # ifndef LANG_LATIN
370 # define LANG_LATIN 0x76
371 # endif
372 # ifndef LANG_LATVIAN
373 # define LANG_LATVIAN 0x26
374 # endif
375 # ifndef LANG_LITHUANIAN
376 # define LANG_LITHUANIAN 0x27
377 # endif
378 # ifndef LANG_LUXEMBOURGISH
379 # define LANG_LUXEMBOURGISH 0x6e
380 # endif
381 # ifndef LANG_MACEDONIAN
382 # define LANG_MACEDONIAN 0x2f
383 # endif
384 # ifndef LANG_MALAY
385 # define LANG_MALAY 0x3e
386 # endif
387 # ifndef LANG_MALAYALAM
388 # define LANG_MALAYALAM 0x4c
389 # endif
390 # ifndef LANG_MALTESE
391 # define LANG_MALTESE 0x3a
392 # endif
393 # ifndef LANG_MANIPURI
394 # define LANG_MANIPURI 0x58
395 # endif
396 # ifndef LANG_MAORI
397 # define LANG_MAORI 0x81
398 # endif
399 # ifndef LANG_MAPUDUNGUN
400 # define LANG_MAPUDUNGUN 0x7a
401 # endif
402 # ifndef LANG_MARATHI
403 # define LANG_MARATHI 0x4e
404 # endif
405 # ifndef LANG_MOHAWK
406 # define LANG_MOHAWK 0x7c
407 # endif
408 # ifndef LANG_MONGOLIAN
409 # define LANG_MONGOLIAN 0x50
410 # endif
411 # ifndef LANG_NEPALI
412 # define LANG_NEPALI 0x61
413 # endif
414 # ifndef LANG_OCCITAN
415 # define LANG_OCCITAN 0x82
416 # endif
417 # ifndef LANG_ORIYA
418 # define LANG_ORIYA 0x48
419 # endif
420 # ifndef LANG_OROMO
421 # define LANG_OROMO 0x72
422 # endif
423 # ifndef LANG_PAPIAMENTU
424 # define LANG_PAPIAMENTU 0x79
425 # endif
426 # ifndef LANG_PASHTO
427 # define LANG_PASHTO 0x63
428 # endif
429 # ifndef LANG_PUNJABI
430 # define LANG_PUNJABI 0x46
431 # endif
432 # ifndef LANG_QUECHUA
433 # define LANG_QUECHUA 0x6b
434 # endif
435 # ifndef LANG_ROMANSH
436 # define LANG_ROMANSH 0x17
437 # endif
438 # ifndef LANG_SAMI
439 # define LANG_SAMI 0x3b
440 # endif
441 # ifndef LANG_SANSKRIT
442 # define LANG_SANSKRIT 0x4f
443 # endif
444 # ifndef LANG_SCOTTISH_GAELIC
445 # define LANG_SCOTTISH_GAELIC 0x91
446 # endif
447 # ifndef LANG_SERBIAN
448 # define LANG_SERBIAN 0x1a
449 # endif
450 # ifndef LANG_SINDHI
451 # define LANG_SINDHI 0x59
452 # endif
453 # ifndef LANG_SINHALESE
454 # define LANG_SINHALESE 0x5b
455 # endif
456 # ifndef LANG_SLOVAK
457 # define LANG_SLOVAK 0x1b
458 # endif
459 # ifndef LANG_SOMALI
460 # define LANG_SOMALI 0x77
461 # endif
462 # ifndef LANG_SORBIAN
463 # define LANG_SORBIAN 0x2e
464 # endif
465 # ifndef LANG_SOTHO
466 # define LANG_SOTHO 0x6c
467 # endif
468 # ifndef LANG_SUTU
469 # define LANG_SUTU 0x30
470 # endif
471 # ifndef LANG_SWAHILI
472 # define LANG_SWAHILI 0x41
473 # endif
474 # ifndef LANG_SYRIAC
475 # define LANG_SYRIAC 0x5a
476 # endif
477 # ifndef LANG_TAGALOG
478 # define LANG_TAGALOG 0x64
479 # endif
480 # ifndef LANG_TAJIK
481 # define LANG_TAJIK 0x28
482 # endif
483 # ifndef LANG_TAMAZIGHT
484 # define LANG_TAMAZIGHT 0x5f
485 # endif
486 # ifndef LANG_TAMIL
487 # define LANG_TAMIL 0x49
488 # endif
489 # ifndef LANG_TATAR
490 # define LANG_TATAR 0x44
491 # endif
492 # ifndef LANG_TELUGU
493 # define LANG_TELUGU 0x4a
494 # endif
495 # ifndef LANG_THAI
496 # define LANG_THAI 0x1e
497 # endif
498 # ifndef LANG_TIBETAN
499 # define LANG_TIBETAN 0x51
500 # endif
501 # ifndef LANG_TIGRINYA
502 # define LANG_TIGRINYA 0x73
503 # endif
504 # ifndef LANG_TSONGA
505 # define LANG_TSONGA 0x31
506 # endif
507 # ifndef LANG_TSWANA
508 # define LANG_TSWANA 0x32
509 # endif
510 # ifndef LANG_TURKMEN
511 # define LANG_TURKMEN 0x42
512 # endif
513 # ifndef LANG_UIGHUR
514 # define LANG_UIGHUR 0x80
515 # endif
516 # ifndef LANG_UKRAINIAN
517 # define LANG_UKRAINIAN 0x22
518 # endif
519 # ifndef LANG_URDU
520 # define LANG_URDU 0x20
521 # endif
522 # ifndef LANG_UZBEK
523 # define LANG_UZBEK 0x43
524 # endif
525 # ifndef LANG_VENDA
526 # define LANG_VENDA 0x33
527 # endif
528 # ifndef LANG_VIETNAMESE
529 # define LANG_VIETNAMESE 0x2a
530 # endif
531 # ifndef LANG_WELSH
532 # define LANG_WELSH 0x52
533 # endif
534 # ifndef LANG_WOLOF
535 # define LANG_WOLOF 0x88
536 # endif
537 # ifndef LANG_XHOSA
538 # define LANG_XHOSA 0x34
539 # endif
540 # ifndef LANG_YAKUT
541 # define LANG_YAKUT 0x85
542 # endif
543 # ifndef LANG_YI
544 # define LANG_YI 0x78
545 # endif
546 # ifndef LANG_YIDDISH
547 # define LANG_YIDDISH 0x3d
548 # endif
549 # ifndef LANG_YORUBA
550 # define LANG_YORUBA 0x6a
551 # endif
552 # ifndef LANG_ZULU
553 # define LANG_ZULU 0x35
554 # endif
555 # ifndef SUBLANG_AFRIKAANS_SOUTH_AFRICA
556 # define SUBLANG_AFRIKAANS_SOUTH_AFRICA 0x01
557 # endif
558 # ifndef SUBLANG_ALBANIAN_ALBANIA
559 # define SUBLANG_ALBANIAN_ALBANIA 0x01
560 # endif
561 # ifndef SUBLANG_ALSATIAN_FRANCE
562 # define SUBLANG_ALSATIAN_FRANCE 0x01
563 # endif
564 # ifndef SUBLANG_AMHARIC_ETHIOPIA
565 # define SUBLANG_AMHARIC_ETHIOPIA 0x01
566 # endif
567 # ifndef SUBLANG_ARABIC_SAUDI_ARABIA
568 # define SUBLANG_ARABIC_SAUDI_ARABIA 0x01
569 # endif
570 # ifndef SUBLANG_ARABIC_IRAQ
571 # define SUBLANG_ARABIC_IRAQ 0x02
572 # endif
573 # ifndef SUBLANG_ARABIC_EGYPT
574 # define SUBLANG_ARABIC_EGYPT 0x03
575 # endif
576 # ifndef SUBLANG_ARABIC_LIBYA
577 # define SUBLANG_ARABIC_LIBYA 0x04
578 # endif
579 # ifndef SUBLANG_ARABIC_ALGERIA
580 # define SUBLANG_ARABIC_ALGERIA 0x05
581 # endif
582 # ifndef SUBLANG_ARABIC_MOROCCO
583 # define SUBLANG_ARABIC_MOROCCO 0x06
584 # endif
585 # ifndef SUBLANG_ARABIC_TUNISIA
586 # define SUBLANG_ARABIC_TUNISIA 0x07
587 # endif
588 # ifndef SUBLANG_ARABIC_OMAN
589 # define SUBLANG_ARABIC_OMAN 0x08
590 # endif
591 # ifndef SUBLANG_ARABIC_YEMEN
592 # define SUBLANG_ARABIC_YEMEN 0x09
593 # endif
594 # ifndef SUBLANG_ARABIC_SYRIA
595 # define SUBLANG_ARABIC_SYRIA 0x0a
596 # endif
597 # ifndef SUBLANG_ARABIC_JORDAN
598 # define SUBLANG_ARABIC_JORDAN 0x0b
599 # endif
600 # ifndef SUBLANG_ARABIC_LEBANON
601 # define SUBLANG_ARABIC_LEBANON 0x0c
602 # endif
603 # ifndef SUBLANG_ARABIC_KUWAIT
604 # define SUBLANG_ARABIC_KUWAIT 0x0d
605 # endif
606 # ifndef SUBLANG_ARABIC_UAE
607 # define SUBLANG_ARABIC_UAE 0x0e
608 # endif
609 # ifndef SUBLANG_ARABIC_BAHRAIN
610 # define SUBLANG_ARABIC_BAHRAIN 0x0f
611 # endif
612 # ifndef SUBLANG_ARABIC_QATAR
613 # define SUBLANG_ARABIC_QATAR 0x10
614 # endif
615 # ifndef SUBLANG_ARMENIAN_ARMENIA
616 # define SUBLANG_ARMENIAN_ARMENIA 0x01
617 # endif
618 # ifndef SUBLANG_ASSAMESE_INDIA
619 # define SUBLANG_ASSAMESE_INDIA 0x01
620 # endif
621 # ifndef SUBLANG_AZERI_LATIN
622 # define SUBLANG_AZERI_LATIN 0x01
623 # endif
624 # ifndef SUBLANG_AZERI_CYRILLIC
625 # define SUBLANG_AZERI_CYRILLIC 0x02
626 # endif
627 # ifndef SUBLANG_BASHKIR_RUSSIA
628 # define SUBLANG_BASHKIR_RUSSIA 0x01
629 # endif
630 # ifndef SUBLANG_BASQUE_BASQUE
631 # define SUBLANG_BASQUE_BASQUE 0x01
632 # endif
633 # ifndef SUBLANG_BELARUSIAN_BELARUS
634 # define SUBLANG_BELARUSIAN_BELARUS 0x01
635 # endif
636 # ifndef SUBLANG_BENGALI_INDIA
637 # define SUBLANG_BENGALI_INDIA 0x01
638 # endif
639 # ifndef SUBLANG_BENGALI_BANGLADESH
640 # define SUBLANG_BENGALI_BANGLADESH 0x02
641 # endif
642 # ifndef SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN
643 # define SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN 0x05
644 # endif
645 # ifndef SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC
646 # define SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC 0x08
647 # endif
648 # ifndef SUBLANG_BRETON_FRANCE
649 # define SUBLANG_BRETON_FRANCE 0x01
650 # endif
651 # ifndef SUBLANG_BULGARIAN_BULGARIA
652 # define SUBLANG_BULGARIAN_BULGARIA 0x01
653 # endif
654 # ifndef SUBLANG_CAMBODIAN_CAMBODIA
655 # define SUBLANG_CAMBODIAN_CAMBODIA 0x01
656 # endif
657 # ifndef SUBLANG_CATALAN_SPAIN
658 # define SUBLANG_CATALAN_SPAIN 0x01
659 # endif
660 # ifndef SUBLANG_CORSICAN_FRANCE
661 # define SUBLANG_CORSICAN_FRANCE 0x01
662 # endif
663 # ifndef SUBLANG_CROATIAN_CROATIA
664 # define SUBLANG_CROATIAN_CROATIA 0x01
665 # endif
666 # ifndef SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN
667 # define SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN 0x04
668 # endif
669 # ifndef SUBLANG_CHINESE_MACAU
670 # define SUBLANG_CHINESE_MACAU 0x05
671 # endif
672 # ifndef SUBLANG_CZECH_CZECH_REPUBLIC
673 # define SUBLANG_CZECH_CZECH_REPUBLIC 0x01
674 # endif
675 # ifndef SUBLANG_DANISH_DENMARK
676 # define SUBLANG_DANISH_DENMARK 0x01
677 # endif
678 # ifndef SUBLANG_DARI_AFGHANISTAN
679 # define SUBLANG_DARI_AFGHANISTAN 0x01
680 # endif
681 # ifndef SUBLANG_DIVEHI_MALDIVES
682 # define SUBLANG_DIVEHI_MALDIVES 0x01
683 # endif
684 # ifndef SUBLANG_DUTCH_SURINAM
685 # define SUBLANG_DUTCH_SURINAM 0x03
686 # endif
687 # ifndef SUBLANG_ENGLISH_SOUTH_AFRICA
688 # define SUBLANG_ENGLISH_SOUTH_AFRICA 0x07
689 # endif
690 # ifndef SUBLANG_ENGLISH_JAMAICA
691 # define SUBLANG_ENGLISH_JAMAICA 0x08
692 # endif
693 # ifndef SUBLANG_ENGLISH_CARIBBEAN
694 # define SUBLANG_ENGLISH_CARIBBEAN 0x09
695 # endif
696 # ifndef SUBLANG_ENGLISH_BELIZE
697 # define SUBLANG_ENGLISH_BELIZE 0x0a
698 # endif
699 # ifndef SUBLANG_ENGLISH_TRINIDAD
700 # define SUBLANG_ENGLISH_TRINIDAD 0x0b
701 # endif
702 # ifndef SUBLANG_ENGLISH_ZIMBABWE
703 # define SUBLANG_ENGLISH_ZIMBABWE 0x0c
704 # endif
705 # ifndef SUBLANG_ENGLISH_PHILIPPINES
706 # define SUBLANG_ENGLISH_PHILIPPINES 0x0d
707 # endif
708 # ifndef SUBLANG_ENGLISH_INDONESIA
709 # define SUBLANG_ENGLISH_INDONESIA 0x0e
710 # endif
711 # ifndef SUBLANG_ENGLISH_HONGKONG
712 # define SUBLANG_ENGLISH_HONGKONG 0x0f
713 # endif
714 # ifndef SUBLANG_ENGLISH_INDIA
715 # define SUBLANG_ENGLISH_INDIA 0x10
716 # endif
717 # ifndef SUBLANG_ENGLISH_MALAYSIA
718 # define SUBLANG_ENGLISH_MALAYSIA 0x11
719 # endif
720 # ifndef SUBLANG_ENGLISH_SINGAPORE
721 # define SUBLANG_ENGLISH_SINGAPORE 0x12
722 # endif
723 # ifndef SUBLANG_ESTONIAN_ESTONIA
724 # define SUBLANG_ESTONIAN_ESTONIA 0x01
725 # endif
726 # ifndef SUBLANG_FAEROESE_FAROE_ISLANDS
727 # define SUBLANG_FAEROESE_FAROE_ISLANDS 0x01
728 # endif
729 # ifndef SUBLANG_FARSI_IRAN
730 # define SUBLANG_FARSI_IRAN 0x01
731 # endif
732 # ifndef SUBLANG_FINNISH_FINLAND
733 # define SUBLANG_FINNISH_FINLAND 0x01
734 # endif
735 # ifndef SUBLANG_FRENCH_LUXEMBOURG
736 # define SUBLANG_FRENCH_LUXEMBOURG 0x05
737 # endif
738 # ifndef SUBLANG_FRENCH_MONACO
739 # define SUBLANG_FRENCH_MONACO 0x06
740 # endif
741 # ifndef SUBLANG_FRENCH_WESTINDIES
742 # define SUBLANG_FRENCH_WESTINDIES 0x07
743 # endif
744 # ifndef SUBLANG_FRENCH_REUNION
745 # define SUBLANG_FRENCH_REUNION 0x08
746 # endif
747 # ifndef SUBLANG_FRENCH_CONGO
748 # define SUBLANG_FRENCH_CONGO 0x09
749 # endif
750 # ifndef SUBLANG_FRENCH_SENEGAL
751 # define SUBLANG_FRENCH_SENEGAL 0x0a
752 # endif
753 # ifndef SUBLANG_FRENCH_CAMEROON
754 # define SUBLANG_FRENCH_CAMEROON 0x0b
755 # endif
756 # ifndef SUBLANG_FRENCH_COTEDIVOIRE
757 # define SUBLANG_FRENCH_COTEDIVOIRE 0x0c
758 # endif
759 # ifndef SUBLANG_FRENCH_MALI
760 # define SUBLANG_FRENCH_MALI 0x0d
761 # endif
762 # ifndef SUBLANG_FRENCH_MOROCCO
763 # define SUBLANG_FRENCH_MOROCCO 0x0e
764 # endif
765 # ifndef SUBLANG_FRENCH_HAITI
766 # define SUBLANG_FRENCH_HAITI 0x0f
767 # endif
768 # ifndef SUBLANG_FRISIAN_NETHERLANDS
769 # define SUBLANG_FRISIAN_NETHERLANDS 0x01
770 # endif
771 # ifndef SUBLANG_GALICIAN_SPAIN
772 # define SUBLANG_GALICIAN_SPAIN 0x01
773 # endif
774 # ifndef SUBLANG_GEORGIAN_GEORGIA
775 # define SUBLANG_GEORGIAN_GEORGIA 0x01
776 # endif
777 # ifndef SUBLANG_GERMAN_LUXEMBOURG
778 # define SUBLANG_GERMAN_LUXEMBOURG 0x04
779 # endif
780 # ifndef SUBLANG_GERMAN_LIECHTENSTEIN
781 # define SUBLANG_GERMAN_LIECHTENSTEIN 0x05
782 # endif
783 # ifndef SUBLANG_GREEK_GREECE
784 # define SUBLANG_GREEK_GREECE 0x01
785 # endif
786 # ifndef SUBLANG_GREENLANDIC_GREENLAND
787 # define SUBLANG_GREENLANDIC_GREENLAND 0x01
788 # endif
789 # ifndef SUBLANG_GUJARATI_INDIA
790 # define SUBLANG_GUJARATI_INDIA 0x01
791 # endif
792 # ifndef SUBLANG_HAUSA_NIGERIA_LATIN
793 # define SUBLANG_HAUSA_NIGERIA_LATIN 0x01
794 # endif
795 # ifndef SUBLANG_HEBREW_ISRAEL
796 # define SUBLANG_HEBREW_ISRAEL 0x01
797 # endif
798 # ifndef SUBLANG_HINDI_INDIA
799 # define SUBLANG_HINDI_INDIA 0x01
800 # endif
801 # ifndef SUBLANG_HUNGARIAN_HUNGARY
802 # define SUBLANG_HUNGARIAN_HUNGARY 0x01
803 # endif
804 # ifndef SUBLANG_ICELANDIC_ICELAND
805 # define SUBLANG_ICELANDIC_ICELAND 0x01
806 # endif
807 # ifndef SUBLANG_IGBO_NIGERIA
808 # define SUBLANG_IGBO_NIGERIA 0x01
809 # endif
810 # ifndef SUBLANG_INDONESIAN_INDONESIA
811 # define SUBLANG_INDONESIAN_INDONESIA 0x01
812 # endif
813 # ifndef SUBLANG_INUKTITUT_CANADA
814 # define SUBLANG_INUKTITUT_CANADA 0x01
815 # endif
816 # undef SUBLANG_INUKTITUT_CANADA_LATIN
817 # define SUBLANG_INUKTITUT_CANADA_LATIN 0x02
818 # undef SUBLANG_IRISH_IRELAND
819 # define SUBLANG_IRISH_IRELAND 0x02
820 # ifndef SUBLANG_JAPANESE_JAPAN
821 # define SUBLANG_JAPANESE_JAPAN 0x01
822 # endif
823 # ifndef SUBLANG_KANNADA_INDIA
824 # define SUBLANG_KANNADA_INDIA 0x01
825 # endif
826 # ifndef SUBLANG_KASHMIRI_INDIA
827 # define SUBLANG_KASHMIRI_INDIA 0x02
828 # endif
829 # ifndef SUBLANG_KAZAK_KAZAKHSTAN
830 # define SUBLANG_KAZAK_KAZAKHSTAN 0x01
831 # endif
832 # ifndef SUBLANG_KICHE_GUATEMALA
833 # define SUBLANG_KICHE_GUATEMALA 0x01
834 # endif
835 # ifndef SUBLANG_KINYARWANDA_RWANDA
836 # define SUBLANG_KINYARWANDA_RWANDA 0x01
837 # endif
838 # ifndef SUBLANG_KONKANI_INDIA
839 # define SUBLANG_KONKANI_INDIA 0x01
840 # endif
841 # ifndef SUBLANG_KYRGYZ_KYRGYZSTAN
842 # define SUBLANG_KYRGYZ_KYRGYZSTAN 0x01
843 # endif
844 # ifndef SUBLANG_LAO_LAOS
845 # define SUBLANG_LAO_LAOS 0x01
846 # endif
847 # ifndef SUBLANG_LATVIAN_LATVIA
848 # define SUBLANG_LATVIAN_LATVIA 0x01
849 # endif
850 # ifndef SUBLANG_LITHUANIAN_LITHUANIA
851 # define SUBLANG_LITHUANIAN_LITHUANIA 0x01
852 # endif
853 # undef SUBLANG_LOWER_SORBIAN_GERMANY
854 # define SUBLANG_LOWER_SORBIAN_GERMANY 0x02
855 # ifndef SUBLANG_LUXEMBOURGISH_LUXEMBOURG
856 # define SUBLANG_LUXEMBOURGISH_LUXEMBOURG 0x01
857 # endif
858 # ifndef SUBLANG_MACEDONIAN_MACEDONIA
859 # define SUBLANG_MACEDONIAN_MACEDONIA 0x01
860 # endif
861 # ifndef SUBLANG_MALAY_MALAYSIA
862 # define SUBLANG_MALAY_MALAYSIA 0x01
863 # endif
864 # ifndef SUBLANG_MALAY_BRUNEI_DARUSSALAM
865 # define SUBLANG_MALAY_BRUNEI_DARUSSALAM 0x02
866 # endif
867 # ifndef SUBLANG_MALAYALAM_INDIA
868 # define SUBLANG_MALAYALAM_INDIA 0x01
869 # endif
870 # ifndef SUBLANG_MALTESE_MALTA
871 # define SUBLANG_MALTESE_MALTA 0x01
872 # endif
873 # ifndef SUBLANG_MAORI_NEW_ZEALAND
874 # define SUBLANG_MAORI_NEW_ZEALAND 0x01
875 # endif
876 # ifndef SUBLANG_MAPUDUNGUN_CHILE
877 # define SUBLANG_MAPUDUNGUN_CHILE 0x01
878 # endif
879 # ifndef SUBLANG_MARATHI_INDIA
880 # define SUBLANG_MARATHI_INDIA 0x01
881 # endif
882 # ifndef SUBLANG_MOHAWK_CANADA
883 # define SUBLANG_MOHAWK_CANADA 0x01
884 # endif
885 # ifndef SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA
886 # define SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA 0x01
887 # endif
888 # ifndef SUBLANG_MONGOLIAN_PRC
889 # define SUBLANG_MONGOLIAN_PRC 0x02
890 # endif
891 # ifndef SUBLANG_NEPALI_NEPAL
892 # define SUBLANG_NEPALI_NEPAL 0x01
893 # endif
894 # ifndef SUBLANG_NEPALI_INDIA
895 # define SUBLANG_NEPALI_INDIA 0x02
896 # endif
897 # ifndef SUBLANG_OCCITAN_FRANCE
898 # define SUBLANG_OCCITAN_FRANCE 0x01
899 # endif
900 # ifndef SUBLANG_ORIYA_INDIA
901 # define SUBLANG_ORIYA_INDIA 0x01
902 # endif
903 # ifndef SUBLANG_PASHTO_AFGHANISTAN
904 # define SUBLANG_PASHTO_AFGHANISTAN 0x01
905 # endif
906 # ifndef SUBLANG_POLISH_POLAND
907 # define SUBLANG_POLISH_POLAND 0x01
908 # endif
909 # ifndef SUBLANG_PUNJABI_INDIA
910 # define SUBLANG_PUNJABI_INDIA 0x01
911 # endif
912 # ifndef SUBLANG_PUNJABI_PAKISTAN
913 # define SUBLANG_PUNJABI_PAKISTAN 0x02
914 # endif
915 # ifndef SUBLANG_QUECHUA_BOLIVIA
916 # define SUBLANG_QUECHUA_BOLIVIA 0x01
917 # endif
918 # ifndef SUBLANG_QUECHUA_ECUADOR
919 # define SUBLANG_QUECHUA_ECUADOR 0x02
920 # endif
921 # ifndef SUBLANG_QUECHUA_PERU
922 # define SUBLANG_QUECHUA_PERU 0x03
923 # endif
924 # ifndef SUBLANG_ROMANIAN_ROMANIA
925 # define SUBLANG_ROMANIAN_ROMANIA 0x01
926 # endif
927 # ifndef SUBLANG_ROMANIAN_MOLDOVA
928 # define SUBLANG_ROMANIAN_MOLDOVA 0x02
929 # endif
930 # ifndef SUBLANG_ROMANSH_SWITZERLAND
931 # define SUBLANG_ROMANSH_SWITZERLAND 0x01
932 # endif
933 # ifndef SUBLANG_RUSSIAN_RUSSIA
934 # define SUBLANG_RUSSIAN_RUSSIA 0x01
935 # endif
936 # ifndef SUBLANG_RUSSIAN_MOLDAVIA
937 # define SUBLANG_RUSSIAN_MOLDAVIA 0x02
938 # endif
939 # ifndef SUBLANG_SAMI_NORTHERN_NORWAY
940 # define SUBLANG_SAMI_NORTHERN_NORWAY 0x01
941 # endif
942 # ifndef SUBLANG_SAMI_NORTHERN_SWEDEN
943 # define SUBLANG_SAMI_NORTHERN_SWEDEN 0x02
944 # endif
945 # ifndef SUBLANG_SAMI_NORTHERN_FINLAND
946 # define SUBLANG_SAMI_NORTHERN_FINLAND 0x03
947 # endif
948 # ifndef SUBLANG_SAMI_LULE_NORWAY
949 # define SUBLANG_SAMI_LULE_NORWAY 0x04
950 # endif
951 # ifndef SUBLANG_SAMI_LULE_SWEDEN
952 # define SUBLANG_SAMI_LULE_SWEDEN 0x05
953 # endif
954 # ifndef SUBLANG_SAMI_SOUTHERN_NORWAY
955 # define SUBLANG_SAMI_SOUTHERN_NORWAY 0x06
956 # endif
957 # ifndef SUBLANG_SAMI_SOUTHERN_SWEDEN
958 # define SUBLANG_SAMI_SOUTHERN_SWEDEN 0x07
959 # endif
960 # undef SUBLANG_SAMI_SKOLT_FINLAND
961 # define SUBLANG_SAMI_SKOLT_FINLAND 0x08
962 # undef SUBLANG_SAMI_INARI_FINLAND
963 # define SUBLANG_SAMI_INARI_FINLAND 0x09
964 # ifndef SUBLANG_SANSKRIT_INDIA
965 # define SUBLANG_SANSKRIT_INDIA 0x01
966 # endif
967 # ifndef SUBLANG_SERBIAN_LATIN
968 # define SUBLANG_SERBIAN_LATIN 0x02
969 # endif
970 # ifndef SUBLANG_SERBIAN_CYRILLIC
971 # define SUBLANG_SERBIAN_CYRILLIC 0x03
972 # endif
973 # ifndef SUBLANG_SINDHI_INDIA
974 # define SUBLANG_SINDHI_INDIA 0x01
975 # endif
976 # undef SUBLANG_SINDHI_PAKISTAN
977 # define SUBLANG_SINDHI_PAKISTAN 0x02
978 # ifndef SUBLANG_SINDHI_AFGHANISTAN
979 # define SUBLANG_SINDHI_AFGHANISTAN 0x02
980 # endif
981 # ifndef SUBLANG_SINHALESE_SRI_LANKA
982 # define SUBLANG_SINHALESE_SRI_LANKA 0x01
983 # endif
984 # ifndef SUBLANG_SLOVAK_SLOVAKIA
985 # define SUBLANG_SLOVAK_SLOVAKIA 0x01
986 # endif
987 # ifndef SUBLANG_SLOVENIAN_SLOVENIA
988 # define SUBLANG_SLOVENIAN_SLOVENIA 0x01
989 # endif
990 # ifndef SUBLANG_SOTHO_SOUTH_AFRICA
991 # define SUBLANG_SOTHO_SOUTH_AFRICA 0x01
992 # endif
993 # ifndef SUBLANG_SPANISH_GUATEMALA
994 # define SUBLANG_SPANISH_GUATEMALA 0x04
995 # endif
996 # ifndef SUBLANG_SPANISH_COSTA_RICA
997 # define SUBLANG_SPANISH_COSTA_RICA 0x05
998 # endif
999 # ifndef SUBLANG_SPANISH_PANAMA
1000 # define SUBLANG_SPANISH_PANAMA 0x06
1001 # endif
1002 # ifndef SUBLANG_SPANISH_DOMINICAN_REPUBLIC
1003 # define SUBLANG_SPANISH_DOMINICAN_REPUBLIC 0x07
1004 # endif
1005 # ifndef SUBLANG_SPANISH_VENEZUELA
1006 # define SUBLANG_SPANISH_VENEZUELA 0x08
1007 # endif
1008 # ifndef SUBLANG_SPANISH_COLOMBIA
1009 # define SUBLANG_SPANISH_COLOMBIA 0x09
1010 # endif
1011 # ifndef SUBLANG_SPANISH_PERU
1012 # define SUBLANG_SPANISH_PERU 0x0a
1013 # endif
1014 # ifndef SUBLANG_SPANISH_ARGENTINA
1015 # define SUBLANG_SPANISH_ARGENTINA 0x0b
1016 # endif
1017 # ifndef SUBLANG_SPANISH_ECUADOR
1018 # define SUBLANG_SPANISH_ECUADOR 0x0c
1019 # endif
1020 # ifndef SUBLANG_SPANISH_CHILE
1021 # define SUBLANG_SPANISH_CHILE 0x0d
1022 # endif
1023 # ifndef SUBLANG_SPANISH_URUGUAY
1024 # define SUBLANG_SPANISH_URUGUAY 0x0e
1025 # endif
1026 # ifndef SUBLANG_SPANISH_PARAGUAY
1027 # define SUBLANG_SPANISH_PARAGUAY 0x0f
1028 # endif
1029 # ifndef SUBLANG_SPANISH_BOLIVIA
1030 # define SUBLANG_SPANISH_BOLIVIA 0x10
1031 # endif
1032 # ifndef SUBLANG_SPANISH_EL_SALVADOR
1033 # define SUBLANG_SPANISH_EL_SALVADOR 0x11
1034 # endif
1035 # ifndef SUBLANG_SPANISH_HONDURAS
1036 # define SUBLANG_SPANISH_HONDURAS 0x12
1037 # endif
1038 # ifndef SUBLANG_SPANISH_NICARAGUA
1039 # define SUBLANG_SPANISH_NICARAGUA 0x13
1040 # endif
1041 # ifndef SUBLANG_SPANISH_PUERTO_RICO
1042 # define SUBLANG_SPANISH_PUERTO_RICO 0x14
1043 # endif
1044 # ifndef SUBLANG_SPANISH_US
1045 # define SUBLANG_SPANISH_US 0x15
1046 # endif
1047 # ifndef SUBLANG_SWAHILI_KENYA
1048 # define SUBLANG_SWAHILI_KENYA 0x01
1049 # endif
1050 # ifndef SUBLANG_SWEDISH_SWEDEN
1051 # define SUBLANG_SWEDISH_SWEDEN 0x01
1052 # endif
1053 # ifndef SUBLANG_SWEDISH_FINLAND
1054 # define SUBLANG_SWEDISH_FINLAND 0x02
1055 # endif
1056 # ifndef SUBLANG_SYRIAC_SYRIA
1057 # define SUBLANG_SYRIAC_SYRIA 0x01
1058 # endif
1059 # ifndef SUBLANG_TAGALOG_PHILIPPINES
1060 # define SUBLANG_TAGALOG_PHILIPPINES 0x01
1061 # endif
1062 # ifndef SUBLANG_TAJIK_TAJIKISTAN
1063 # define SUBLANG_TAJIK_TAJIKISTAN 0x01
1064 # endif
1065 # ifndef SUBLANG_TAMAZIGHT_ARABIC
1066 # define SUBLANG_TAMAZIGHT_ARABIC 0x01
1067 # endif
1068 # ifndef SUBLANG_TAMAZIGHT_ALGERIA_LATIN
1069 # define SUBLANG_TAMAZIGHT_ALGERIA_LATIN 0x02
1070 # endif
1071 # ifndef SUBLANG_TAMIL_INDIA
1072 # define SUBLANG_TAMIL_INDIA 0x01
1073 # endif
1074 # ifndef SUBLANG_TATAR_RUSSIA
1075 # define SUBLANG_TATAR_RUSSIA 0x01
1076 # endif
1077 # ifndef SUBLANG_TELUGU_INDIA
1078 # define SUBLANG_TELUGU_INDIA 0x01
1079 # endif
1080 # ifndef SUBLANG_THAI_THAILAND
1081 # define SUBLANG_THAI_THAILAND 0x01
1082 # endif
1083 # ifndef SUBLANG_TIBETAN_PRC
1084 # define SUBLANG_TIBETAN_PRC 0x01
1085 # endif
1086 # undef SUBLANG_TIBETAN_BHUTAN
1087 # define SUBLANG_TIBETAN_BHUTAN 0x02
1088 # ifndef SUBLANG_TIGRINYA_ETHIOPIA
1089 # define SUBLANG_TIGRINYA_ETHIOPIA 0x01
1090 # endif
1091 # ifndef SUBLANG_TIGRINYA_ERITREA
1092 # define SUBLANG_TIGRINYA_ERITREA 0x02
1093 # endif
1094 # ifndef SUBLANG_TSWANA_SOUTH_AFRICA
1095 # define SUBLANG_TSWANA_SOUTH_AFRICA 0x01
1096 # endif
1097 # ifndef SUBLANG_TURKISH_TURKEY
1098 # define SUBLANG_TURKISH_TURKEY 0x01
1099 # endif
1100 # ifndef SUBLANG_TURKMEN_TURKMENISTAN
1101 # define SUBLANG_TURKMEN_TURKMENISTAN 0x01
1102 # endif
1103 # ifndef SUBLANG_UIGHUR_PRC
1104 # define SUBLANG_UIGHUR_PRC 0x01
1105 # endif
1106 # ifndef SUBLANG_UKRAINIAN_UKRAINE
1107 # define SUBLANG_UKRAINIAN_UKRAINE 0x01
1108 # endif
1109 # ifndef SUBLANG_UPPER_SORBIAN_GERMANY
1110 # define SUBLANG_UPPER_SORBIAN_GERMANY 0x01
1111 # endif
1112 # ifndef SUBLANG_URDU_PAKISTAN
1113 # define SUBLANG_URDU_PAKISTAN 0x01
1114 # endif
1115 # ifndef SUBLANG_URDU_INDIA
1116 # define SUBLANG_URDU_INDIA 0x02
1117 # endif
1118 # ifndef SUBLANG_UZBEK_LATIN
1119 # define SUBLANG_UZBEK_LATIN 0x01
1120 # endif
1121 # ifndef SUBLANG_UZBEK_CYRILLIC
1122 # define SUBLANG_UZBEK_CYRILLIC 0x02
1123 # endif
1124 # ifndef SUBLANG_VIETNAMESE_VIETNAM
1125 # define SUBLANG_VIETNAMESE_VIETNAM 0x01
1126 # endif
1127 # ifndef SUBLANG_WELSH_UNITED_KINGDOM
1128 # define SUBLANG_WELSH_UNITED_KINGDOM 0x01
1129 # endif
1130 # ifndef SUBLANG_WOLOF_SENEGAL
1131 # define SUBLANG_WOLOF_SENEGAL 0x01
1132 # endif
1133 # ifndef SUBLANG_XHOSA_SOUTH_AFRICA
1134 # define SUBLANG_XHOSA_SOUTH_AFRICA 0x01
1135 # endif
1136 # ifndef SUBLANG_YAKUT_RUSSIA
1137 # define SUBLANG_YAKUT_RUSSIA 0x01
1138 # endif
1139 # ifndef SUBLANG_YI_PRC
1140 # define SUBLANG_YI_PRC 0x01
1141 # endif
1142 # ifndef SUBLANG_YORUBA_NIGERIA
1143 # define SUBLANG_YORUBA_NIGERIA 0x01
1144 # endif
1145 # ifndef SUBLANG_ZULU_SOUTH_AFRICA
1146 # define SUBLANG_ZULU_SOUTH_AFRICA 0x01
1147 # endif
1148 /* GetLocaleInfoA operations. */
1149 # ifndef LOCALE_SNAME
1150 # define LOCALE_SNAME 0x5c
1151 # endif
1152 # ifndef LOCALE_NAME_MAX_LENGTH
1153 # define LOCALE_NAME_MAX_LENGTH 85
1154 # endif
1155 /* Don't assume that UNICODE is not defined. */
1156 # undef GetLocaleInfo
1157 # define GetLocaleInfo GetLocaleInfoA
1158 # undef EnumSystemLocales
1159 # define EnumSystemLocales EnumSystemLocalesA
1160 #endif
1162 /* We want to use the system's setlocale() function here, not the gnulib
1163 override. */
1164 #undef setlocale
1167 #if HAVE_CFPREFERENCESCOPYAPPVALUE
1168 /* Mac OS X 10.4 or newer */
1170 /* Canonicalize a Mac OS X locale name to a Unix locale name.
1171 NAME is a sufficiently large buffer.
1172 On input, it contains the Mac OS X locale name.
1173 On output, it contains the Unix locale name. */
1174 # if !defined IN_LIBINTL
1175 static
1176 # endif
1177 void
1178 gl_locale_name_canonicalize (char *name)
1180 /* This conversion is based on a posting by
1181 Deborah GoldSmith <goldsmit@apple.com> on 2005-03-08,
1182 https://lists.apple.com/archives/carbon-dev/2005/Mar/msg00293.html */
1184 /* Convert legacy (NeXTstep inherited) English names to Unix (ISO 639 and
1185 ISO 3166) names. Prior to Mac OS X 10.3, there is no API for doing this.
1186 Therefore we do it ourselves, using a table based on the results of the
1187 Mac OS X 10.3.8 function
1188 CFLocaleCreateCanonicalLocaleIdentifierFromString(). */
1189 typedef struct { const char legacy[21+1]; const char unixy[5+1]; }
1190 legacy_entry;
1191 static const legacy_entry legacy_table[] = {
1192 { "Afrikaans", "af" },
1193 { "Albanian", "sq" },
1194 { "Amharic", "am" },
1195 { "Arabic", "ar" },
1196 { "Armenian", "hy" },
1197 { "Assamese", "as" },
1198 { "Aymara", "ay" },
1199 { "Azerbaijani", "az" },
1200 { "Basque", "eu" },
1201 { "Belarusian", "be" },
1202 { "Belorussian", "be" },
1203 { "Bengali", "bn" },
1204 { "Brazilian Portugese", "pt_BR" },
1205 { "Brazilian Portuguese", "pt_BR" },
1206 { "Breton", "br" },
1207 { "Bulgarian", "bg" },
1208 { "Burmese", "my" },
1209 { "Byelorussian", "be" },
1210 { "Catalan", "ca" },
1211 { "Chewa", "ny" },
1212 { "Chichewa", "ny" },
1213 { "Chinese", "zh" },
1214 { "Chinese, Simplified", "zh_CN" },
1215 { "Chinese, Traditional", "zh_TW" },
1216 { "Chinese, Tradtional", "zh_TW" },
1217 { "Croatian", "hr" },
1218 { "Czech", "cs" },
1219 { "Danish", "da" },
1220 { "Dutch", "nl" },
1221 { "Dzongkha", "dz" },
1222 { "English", "en" },
1223 { "Esperanto", "eo" },
1224 { "Estonian", "et" },
1225 { "Faroese", "fo" },
1226 { "Farsi", "fa" },
1227 { "Finnish", "fi" },
1228 { "Flemish", "nl_BE" },
1229 { "French", "fr" },
1230 { "Galician", "gl" },
1231 { "Gallegan", "gl" },
1232 { "Georgian", "ka" },
1233 { "German", "de" },
1234 { "Greek", "el" },
1235 { "Greenlandic", "kl" },
1236 { "Guarani", "gn" },
1237 { "Gujarati", "gu" },
1238 { "Hawaiian", "haw" }, /* Yes, "haw", not "cpe". */
1239 { "Hebrew", "he" },
1240 { "Hindi", "hi" },
1241 { "Hungarian", "hu" },
1242 { "Icelandic", "is" },
1243 { "Indonesian", "id" },
1244 { "Inuktitut", "iu" },
1245 { "Irish", "ga" },
1246 { "Italian", "it" },
1247 { "Japanese", "ja" },
1248 { "Javanese", "jv" },
1249 { "Kalaallisut", "kl" },
1250 { "Kannada", "kn" },
1251 { "Kashmiri", "ks" },
1252 { "Kazakh", "kk" },
1253 { "Khmer", "km" },
1254 { "Kinyarwanda", "rw" },
1255 { "Kirghiz", "ky" },
1256 { "Korean", "ko" },
1257 { "Kurdish", "ku" },
1258 { "Latin", "la" },
1259 { "Latvian", "lv" },
1260 { "Lithuanian", "lt" },
1261 { "Macedonian", "mk" },
1262 { "Malagasy", "mg" },
1263 { "Malay", "ms" },
1264 { "Malayalam", "ml" },
1265 { "Maltese", "mt" },
1266 { "Manx", "gv" },
1267 { "Marathi", "mr" },
1268 { "Moldavian", "mo" },
1269 { "Mongolian", "mn" },
1270 { "Nepali", "ne" },
1271 { "Norwegian", "nb" }, /* Yes, "nb", not the obsolete "no". */
1272 { "Nyanja", "ny" },
1273 { "Nynorsk", "nn" },
1274 { "Oriya", "or" },
1275 { "Oromo", "om" },
1276 { "Panjabi", "pa" },
1277 { "Pashto", "ps" },
1278 { "Persian", "fa" },
1279 { "Polish", "pl" },
1280 { "Portuguese", "pt" },
1281 { "Portuguese, Brazilian", "pt_BR" },
1282 { "Punjabi", "pa" },
1283 { "Pushto", "ps" },
1284 { "Quechua", "qu" },
1285 { "Romanian", "ro" },
1286 { "Ruanda", "rw" },
1287 { "Rundi", "rn" },
1288 { "Russian", "ru" },
1289 { "Sami", "se_NO" }, /* Not just "se". */
1290 { "Sanskrit", "sa" },
1291 { "Scottish", "gd" },
1292 { "Serbian", "sr" },
1293 { "Simplified Chinese", "zh_CN" },
1294 { "Sindhi", "sd" },
1295 { "Sinhalese", "si" },
1296 { "Slovak", "sk" },
1297 { "Slovenian", "sl" },
1298 { "Somali", "so" },
1299 { "Spanish", "es" },
1300 { "Sundanese", "su" },
1301 { "Swahili", "sw" },
1302 { "Swedish", "sv" },
1303 { "Tagalog", "tl" },
1304 { "Tajik", "tg" },
1305 { "Tajiki", "tg" },
1306 { "Tamil", "ta" },
1307 { "Tatar", "tt" },
1308 { "Telugu", "te" },
1309 { "Thai", "th" },
1310 { "Tibetan", "bo" },
1311 { "Tigrinya", "ti" },
1312 { "Tongan", "to" },
1313 { "Traditional Chinese", "zh_TW" },
1314 { "Turkish", "tr" },
1315 { "Turkmen", "tk" },
1316 { "Uighur", "ug" },
1317 { "Ukrainian", "uk" },
1318 { "Urdu", "ur" },
1319 { "Uzbek", "uz" },
1320 { "Vietnamese", "vi" },
1321 { "Welsh", "cy" },
1322 { "Yiddish", "yi" }
1325 /* Convert new-style locale names with language tags (ISO 639 and ISO 15924)
1326 to Unix (ISO 639 and ISO 3166) names. */
1327 typedef struct { const char langtag[7+1]; const char unixy[12+1]; }
1328 langtag_entry;
1329 static const langtag_entry langtag_table[] = {
1330 /* Mac OS X has "az-Arab", "az-Cyrl", "az-Latn".
1331 The default script for az on Unix is Latin. */
1332 { "az-Latn", "az" },
1333 /* Mac OS X has "bs-Cyrl", "bs-Latn".
1334 The default script for bs on Unix is Latin. */
1335 { "bs-Latn", "bs" },
1336 /* Mac OS X has "ga-dots". Does not yet exist on Unix. */
1337 { "ga-dots", "ga" },
1338 /* Mac OS X has "kk-Cyrl".
1339 The default script for kk on Unix is Cyrillic. */
1340 { "kk-Cyrl", "kk" },
1341 /* Mac OS X has "mn-Cyrl", "mn-Mong".
1342 The default script for mn on Unix is Cyrillic. */
1343 { "mn-Cyrl", "mn" },
1344 /* Mac OS X has "ms-Arab", "ms-Latn".
1345 The default script for ms on Unix is Latin. */
1346 { "ms-Latn", "ms" },
1347 /* Mac OS X has "pa-Arab", "pa-Guru".
1348 Country codes are used to distinguish these on Unix. */
1349 { "pa-Arab", "pa_PK" },
1350 { "pa-Guru", "pa_IN" },
1351 /* Mac OS X has "shi-Latn", "shi-Tfng". Does not yet exist on Unix. */
1352 /* Mac OS X has "sr-Cyrl", "sr-Latn".
1353 The default script for sr on Unix is Cyrillic. */
1354 { "sr-Cyrl", "sr" },
1355 /* Mac OS X has "tg-Cyrl".
1356 The default script for tg on Unix is Cyrillic. */
1357 { "tg-Cyrl", "tg" },
1358 /* Mac OS X has "tk-Cyrl".
1359 The default script for tk on Unix is Cyrillic. */
1360 { "tk-Cyrl", "tk" },
1361 /* Mac OS X has "tt-Cyrl".
1362 The default script for tt on Unix is Cyrillic. */
1363 { "tt-Cyrl", "tt" },
1364 /* Mac OS X has "uz-Arab", "uz-Cyrl", "uz-Latn".
1365 The default script for uz on Unix is Latin. */
1366 { "uz-Latn", "uz" },
1367 /* Mac OS X has "vai-Latn", "vai-Vaii". Does not yet exist on Unix. */
1368 /* Mac OS X has "yue-Hans", "yue-Hant".
1369 The default script for yue on Unix is Simplified Han. */
1370 { "yue-Hans", "yue" },
1371 /* Mac OS X has "zh-Hans", "zh-Hant".
1372 Country codes are used to distinguish these on Unix. */
1373 { "zh-Hans", "zh_CN" },
1374 { "zh-Hant", "zh_TW" }
1377 /* Convert script names (ISO 15924) to Unix conventions.
1378 See https://www.unicode.org/iso15924/iso15924-codes.html */
1379 typedef struct { const char script[4+1]; const char unixy[9+1]; }
1380 script_entry;
1381 static const script_entry script_table[] = {
1382 { "Arab", "arabic" },
1383 { "Cyrl", "cyrillic" },
1384 { "Latn", "latin" },
1385 { "Mong", "mongolian" }
1388 /* Step 1: Convert using legacy_table. */
1389 if (name[0] >= 'A' && name[0] <= 'Z')
1391 unsigned int i1, i2;
1392 i1 = 0;
1393 i2 = sizeof (legacy_table) / sizeof (legacy_entry);
1394 while (i2 - i1 > 1)
1396 /* At this point we know that if name occurs in legacy_table,
1397 its index must be >= i1 and < i2. */
1398 unsigned int i = (i1 + i2) >> 1;
1399 const legacy_entry *p = &legacy_table[i];
1400 if (strcmp (name, p->legacy) < 0)
1401 i2 = i;
1402 else
1403 i1 = i;
1405 if (strcmp (name, legacy_table[i1].legacy) == 0)
1407 strcpy (name, legacy_table[i1].unixy);
1408 return;
1412 /* Step 2: Convert using langtag_table and script_table. */
1413 if (strlen (name) == 7 && name[2] == '-')
1415 unsigned int i1, i2;
1416 i1 = 0;
1417 i2 = sizeof (langtag_table) / sizeof (langtag_entry);
1418 while (i2 - i1 > 1)
1420 /* At this point we know that if name occurs in langtag_table,
1421 its index must be >= i1 and < i2. */
1422 unsigned int i = (i1 + i2) >> 1;
1423 const langtag_entry *p = &langtag_table[i];
1424 if (strcmp (name, p->langtag) < 0)
1425 i2 = i;
1426 else
1427 i1 = i;
1429 if (strcmp (name, langtag_table[i1].langtag) == 0)
1431 strcpy (name, langtag_table[i1].unixy);
1432 return;
1435 i1 = 0;
1436 i2 = sizeof (script_table) / sizeof (script_entry);
1437 while (i2 - i1 > 1)
1439 /* At this point we know that if (name + 3) occurs in script_table,
1440 its index must be >= i1 and < i2. */
1441 unsigned int i = (i1 + i2) >> 1;
1442 const script_entry *p = &script_table[i];
1443 if (strcmp (name + 3, p->script) < 0)
1444 i2 = i;
1445 else
1446 i1 = i;
1448 if (strcmp (name + 3, script_table[i1].script) == 0)
1450 name[2] = '@';
1451 strcpy (name + 3, script_table[i1].unixy);
1452 return;
1456 /* Step 3: Convert new-style dash to Unix underscore. */
1458 char *p;
1459 for (p = name; *p != '\0'; p++)
1460 if (*p == '-')
1461 *p = '_';
1465 #endif
1468 #if defined WINDOWS_NATIVE || defined __CYGWIN__ /* Native Windows or Cygwin */
1470 /* Canonicalize a Windows native locale name to a Unix locale name.
1471 NAME is a sufficiently large buffer.
1472 On input, it contains the Windows locale name.
1473 On output, it contains the Unix locale name. */
1474 # if !defined IN_LIBINTL
1475 static
1476 # endif
1477 void
1478 gl_locale_name_canonicalize (char *name)
1480 /* FIXME: This is probably incomplete: it does not handle "zh-Hans" and
1481 "zh-Hant". */
1482 char *p;
1484 for (p = name; *p != '\0'; p++)
1485 if (*p == '-')
1487 *p = '_';
1488 p++;
1489 for (; *p != '\0'; p++)
1491 if (*p >= 'a' && *p <= 'z')
1492 *p += 'A' - 'a';
1493 if (*p == '-')
1495 *p = '\0';
1496 return;
1499 return;
1503 # if !defined IN_LIBINTL
1504 static
1505 # endif
1506 const char *
1507 gl_locale_name_from_win32_LANGID (LANGID langid)
1509 /* Activate the new code only when the GETTEXT_MUI environment variable is
1510 set, for the time being, since the new code is not well tested. */
1511 if (getenv ("GETTEXT_MUI") != NULL)
1513 static char namebuf[256];
1515 /* Query the system's notion of locale name.
1516 On Windows95/98/ME, GetLocaleInfoA returns some incorrect results.
1517 But we don't need to support systems that are so old. */
1518 if (GetLocaleInfoA (MAKELCID (langid, SORT_DEFAULT), LOCALE_SNAME,
1519 namebuf, sizeof (namebuf) - 1))
1521 /* Convert it to a Unix locale name. */
1522 gl_locale_name_canonicalize (namebuf);
1523 return namebuf;
1526 /* Internet Explorer has an LCID to RFC3066 name mapping stored in
1527 HKEY_CLASSES_ROOT\Mime\Database\Rfc1766. But we better don't use that
1528 since IE's i18n subsystem is known to be inconsistent with the native
1529 Windows base (e.g. they have different character conversion facilities
1530 that produce different results). */
1531 /* Use our own table. */
1533 int primary, sub;
1535 /* Split into language and territory part. */
1536 primary = PRIMARYLANGID (langid);
1537 sub = SUBLANGID (langid);
1539 /* Dispatch on language.
1540 See also https://www.unicode.org/unicode/onlinedat/languages.html .
1541 For details about languages, see https://www.ethnologue.com/ . */
1542 switch (primary)
1544 case LANG_AFRIKAANS:
1545 switch (sub)
1547 case SUBLANG_AFRIKAANS_SOUTH_AFRICA: return "af_ZA";
1549 return "af";
1550 case LANG_ALBANIAN:
1551 switch (sub)
1553 case SUBLANG_ALBANIAN_ALBANIA: return "sq_AL";
1555 return "sq";
1556 case LANG_ALSATIAN:
1557 switch (sub)
1559 case SUBLANG_ALSATIAN_FRANCE: return "gsw_FR";
1561 return "gsw";
1562 case LANG_AMHARIC:
1563 switch (sub)
1565 case SUBLANG_AMHARIC_ETHIOPIA: return "am_ET";
1567 return "am";
1568 case LANG_ARABIC:
1569 switch (sub)
1571 case SUBLANG_ARABIC_SAUDI_ARABIA: return "ar_SA";
1572 case SUBLANG_ARABIC_IRAQ: return "ar_IQ";
1573 case SUBLANG_ARABIC_EGYPT: return "ar_EG";
1574 case SUBLANG_ARABIC_LIBYA: return "ar_LY";
1575 case SUBLANG_ARABIC_ALGERIA: return "ar_DZ";
1576 case SUBLANG_ARABIC_MOROCCO: return "ar_MA";
1577 case SUBLANG_ARABIC_TUNISIA: return "ar_TN";
1578 case SUBLANG_ARABIC_OMAN: return "ar_OM";
1579 case SUBLANG_ARABIC_YEMEN: return "ar_YE";
1580 case SUBLANG_ARABIC_SYRIA: return "ar_SY";
1581 case SUBLANG_ARABIC_JORDAN: return "ar_JO";
1582 case SUBLANG_ARABIC_LEBANON: return "ar_LB";
1583 case SUBLANG_ARABIC_KUWAIT: return "ar_KW";
1584 case SUBLANG_ARABIC_UAE: return "ar_AE";
1585 case SUBLANG_ARABIC_BAHRAIN: return "ar_BH";
1586 case SUBLANG_ARABIC_QATAR: return "ar_QA";
1588 return "ar";
1589 case LANG_ARMENIAN:
1590 switch (sub)
1592 case SUBLANG_ARMENIAN_ARMENIA: return "hy_AM";
1594 return "hy";
1595 case LANG_ASSAMESE:
1596 switch (sub)
1598 case SUBLANG_ASSAMESE_INDIA: return "as_IN";
1600 return "as";
1601 case LANG_AZERI:
1602 switch (sub)
1604 /* FIXME: Adjust this when Azerbaijani locales appear on Unix. */
1605 case 0x1e: return "az@latin";
1606 case SUBLANG_AZERI_LATIN: return "az_AZ@latin";
1607 case 0x1d: return "az@cyrillic";
1608 case SUBLANG_AZERI_CYRILLIC: return "az_AZ@cyrillic";
1610 return "az";
1611 case LANG_BASHKIR:
1612 switch (sub)
1614 case SUBLANG_BASHKIR_RUSSIA: return "ba_RU";
1616 return "ba";
1617 case LANG_BASQUE:
1618 switch (sub)
1620 case SUBLANG_BASQUE_BASQUE: return "eu_ES";
1622 return "eu"; /* Ambiguous: could be "eu_ES" or "eu_FR". */
1623 case LANG_BELARUSIAN:
1624 switch (sub)
1626 case SUBLANG_BELARUSIAN_BELARUS: return "be_BY";
1628 return "be";
1629 case LANG_BENGALI:
1630 switch (sub)
1632 case SUBLANG_BENGALI_INDIA: return "bn_IN";
1633 case SUBLANG_BENGALI_BANGLADESH: return "bn_BD";
1635 return "bn";
1636 case LANG_BRETON:
1637 switch (sub)
1639 case SUBLANG_BRETON_FRANCE: return "br_FR";
1641 return "br";
1642 case LANG_BULGARIAN:
1643 switch (sub)
1645 case SUBLANG_BULGARIAN_BULGARIA: return "bg_BG";
1647 return "bg";
1648 case LANG_BURMESE:
1649 switch (sub)
1651 case SUBLANG_DEFAULT: return "my_MM";
1653 return "my";
1654 case LANG_CAMBODIAN:
1655 switch (sub)
1657 case SUBLANG_CAMBODIAN_CAMBODIA: return "km_KH";
1659 return "km";
1660 case LANG_CATALAN:
1661 switch (sub)
1663 case SUBLANG_CATALAN_SPAIN: return "ca_ES";
1665 return "ca";
1666 case LANG_CHEROKEE:
1667 switch (sub)
1669 case SUBLANG_DEFAULT: return "chr_US";
1671 return "chr";
1672 case LANG_CHINESE:
1673 switch (sub)
1675 case SUBLANG_CHINESE_TRADITIONAL: case 0x1f: return "zh_TW";
1676 case SUBLANG_CHINESE_SIMPLIFIED: case 0x00: return "zh_CN";
1677 case SUBLANG_CHINESE_HONGKONG: return "zh_HK"; /* traditional */
1678 case SUBLANG_CHINESE_SINGAPORE: return "zh_SG"; /* simplified */
1679 case SUBLANG_CHINESE_MACAU: return "zh_MO"; /* traditional */
1681 return "zh";
1682 case LANG_CORSICAN:
1683 switch (sub)
1685 case SUBLANG_CORSICAN_FRANCE: return "co_FR";
1687 return "co";
1688 case LANG_CROATIAN: /* LANG_CROATIAN == LANG_SERBIAN == LANG_BOSNIAN
1689 * What used to be called Serbo-Croatian
1690 * should really now be two separate
1691 * languages because of political reasons.
1692 * (Says tml, who knows nothing about Serbian
1693 * or Croatian.)
1694 * (I can feel those flames coming already.)
1696 switch (sub)
1698 /* Croatian */
1699 case 0x00: return "hr";
1700 case SUBLANG_CROATIAN_CROATIA: return "hr_HR";
1701 case SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN: return "hr_BA";
1702 /* Serbian */
1703 case 0x1f: return "sr";
1704 case 0x1c: return "sr"; /* latin */
1705 case SUBLANG_SERBIAN_LATIN: return "sr_CS"; /* latin */
1706 case 0x09: return "sr_RS"; /* latin */
1707 case 0x0b: return "sr_ME"; /* latin */
1708 case 0x06: return "sr_BA"; /* latin */
1709 case 0x1b: return "sr@cyrillic";
1710 case SUBLANG_SERBIAN_CYRILLIC: return "sr_CS@cyrillic";
1711 case 0x0a: return "sr_RS@cyrillic";
1712 case 0x0c: return "sr_ME@cyrillic";
1713 case 0x07: return "sr_BA@cyrillic";
1714 /* Bosnian */
1715 case 0x1e: return "bs";
1716 case 0x1a: return "bs"; /* latin */
1717 case SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN: return "bs_BA"; /* latin */
1718 case 0x19: return "bs@cyrillic";
1719 case SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC: return "bs_BA@cyrillic";
1721 return "hr";
1722 case LANG_CZECH:
1723 switch (sub)
1725 case SUBLANG_CZECH_CZECH_REPUBLIC: return "cs_CZ";
1727 return "cs";
1728 case LANG_DANISH:
1729 switch (sub)
1731 case SUBLANG_DANISH_DENMARK: return "da_DK";
1733 return "da";
1734 case LANG_DARI:
1735 /* FIXME: Adjust this when such locales appear on Unix. */
1736 switch (sub)
1738 case SUBLANG_DARI_AFGHANISTAN: return "prs_AF";
1740 return "prs";
1741 case LANG_DIVEHI:
1742 switch (sub)
1744 case SUBLANG_DIVEHI_MALDIVES: return "dv_MV";
1746 return "dv";
1747 case LANG_DUTCH:
1748 switch (sub)
1750 case SUBLANG_DUTCH: return "nl_NL";
1751 case SUBLANG_DUTCH_BELGIAN: /* FLEMISH, VLAAMS */ return "nl_BE";
1752 case SUBLANG_DUTCH_SURINAM: return "nl_SR";
1754 return "nl";
1755 case LANG_EDO:
1756 switch (sub)
1758 case SUBLANG_DEFAULT: return "bin_NG";
1760 return "bin";
1761 case LANG_ENGLISH:
1762 switch (sub)
1764 /* SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. Heh. I thought
1765 * English was the language spoken in England.
1766 * Oh well.
1768 case SUBLANG_ENGLISH_US: return "en_US";
1769 case SUBLANG_ENGLISH_UK: return "en_GB";
1770 case SUBLANG_ENGLISH_AUS: return "en_AU";
1771 case SUBLANG_ENGLISH_CAN: return "en_CA";
1772 case SUBLANG_ENGLISH_NZ: return "en_NZ";
1773 case SUBLANG_ENGLISH_EIRE: return "en_IE";
1774 case SUBLANG_ENGLISH_SOUTH_AFRICA: return "en_ZA";
1775 case SUBLANG_ENGLISH_JAMAICA: return "en_JM";
1776 case SUBLANG_ENGLISH_CARIBBEAN: return "en_GD"; /* Grenada? */
1777 case SUBLANG_ENGLISH_BELIZE: return "en_BZ";
1778 case SUBLANG_ENGLISH_TRINIDAD: return "en_TT";
1779 case SUBLANG_ENGLISH_ZIMBABWE: return "en_ZW";
1780 case SUBLANG_ENGLISH_PHILIPPINES: return "en_PH";
1781 case SUBLANG_ENGLISH_INDONESIA: return "en_ID";
1782 case SUBLANG_ENGLISH_HONGKONG: return "en_HK";
1783 case SUBLANG_ENGLISH_INDIA: return "en_IN";
1784 case SUBLANG_ENGLISH_MALAYSIA: return "en_MY";
1785 case SUBLANG_ENGLISH_SINGAPORE: return "en_SG";
1787 return "en";
1788 case LANG_ESTONIAN:
1789 switch (sub)
1791 case SUBLANG_ESTONIAN_ESTONIA: return "et_EE";
1793 return "et";
1794 case LANG_FAEROESE:
1795 switch (sub)
1797 case SUBLANG_FAEROESE_FAROE_ISLANDS: return "fo_FO";
1799 return "fo";
1800 case LANG_FARSI:
1801 switch (sub)
1803 case SUBLANG_FARSI_IRAN: return "fa_IR";
1805 return "fa";
1806 case LANG_FINNISH:
1807 switch (sub)
1809 case SUBLANG_FINNISH_FINLAND: return "fi_FI";
1811 return "fi";
1812 case LANG_FRENCH:
1813 switch (sub)
1815 case SUBLANG_FRENCH: return "fr_FR";
1816 case SUBLANG_FRENCH_BELGIAN: /* WALLOON */ return "fr_BE";
1817 case SUBLANG_FRENCH_CANADIAN: return "fr_CA";
1818 case SUBLANG_FRENCH_SWISS: return "fr_CH";
1819 case SUBLANG_FRENCH_LUXEMBOURG: return "fr_LU";
1820 case SUBLANG_FRENCH_MONACO: return "fr_MC";
1821 case SUBLANG_FRENCH_WESTINDIES: return "fr"; /* Caribbean? */
1822 case SUBLANG_FRENCH_REUNION: return "fr_RE";
1823 case SUBLANG_FRENCH_CONGO: return "fr_CG";
1824 case SUBLANG_FRENCH_SENEGAL: return "fr_SN";
1825 case SUBLANG_FRENCH_CAMEROON: return "fr_CM";
1826 case SUBLANG_FRENCH_COTEDIVOIRE: return "fr_CI";
1827 case SUBLANG_FRENCH_MALI: return "fr_ML";
1828 case SUBLANG_FRENCH_MOROCCO: return "fr_MA";
1829 case SUBLANG_FRENCH_HAITI: return "fr_HT";
1831 return "fr";
1832 case LANG_FRISIAN:
1833 switch (sub)
1835 case SUBLANG_FRISIAN_NETHERLANDS: return "fy_NL";
1837 return "fy";
1838 case LANG_FULFULDE:
1839 /* Spoken in Nigeria, Guinea, Senegal, Mali, Niger, Cameroon, Benin. */
1840 switch (sub)
1842 case SUBLANG_DEFAULT: return "ff_NG";
1844 return "ff";
1845 case LANG_GAELIC:
1846 switch (sub)
1848 case 0x01: /* SCOTTISH */
1849 /* old, superseded by LANG_SCOTTISH_GAELIC */
1850 return "gd_GB";
1851 case SUBLANG_IRISH_IRELAND: return "ga_IE";
1853 return "ga";
1854 case LANG_GALICIAN:
1855 switch (sub)
1857 case SUBLANG_GALICIAN_SPAIN: return "gl_ES";
1859 return "gl";
1860 case LANG_GEORGIAN:
1861 switch (sub)
1863 case SUBLANG_GEORGIAN_GEORGIA: return "ka_GE";
1865 return "ka";
1866 case LANG_GERMAN:
1867 switch (sub)
1869 case SUBLANG_GERMAN: return "de_DE";
1870 case SUBLANG_GERMAN_SWISS: return "de_CH";
1871 case SUBLANG_GERMAN_AUSTRIAN: return "de_AT";
1872 case SUBLANG_GERMAN_LUXEMBOURG: return "de_LU";
1873 case SUBLANG_GERMAN_LIECHTENSTEIN: return "de_LI";
1875 return "de";
1876 case LANG_GREEK:
1877 switch (sub)
1879 case SUBLANG_GREEK_GREECE: return "el_GR";
1881 return "el";
1882 case LANG_GREENLANDIC:
1883 switch (sub)
1885 case SUBLANG_GREENLANDIC_GREENLAND: return "kl_GL";
1887 return "kl";
1888 case LANG_GUARANI:
1889 switch (sub)
1891 case SUBLANG_DEFAULT: return "gn_PY";
1893 return "gn";
1894 case LANG_GUJARATI:
1895 switch (sub)
1897 case SUBLANG_GUJARATI_INDIA: return "gu_IN";
1899 return "gu";
1900 case LANG_HAUSA:
1901 switch (sub)
1903 case 0x1f: return "ha";
1904 case SUBLANG_HAUSA_NIGERIA_LATIN: return "ha_NG";
1906 return "ha";
1907 case LANG_HAWAIIAN:
1908 /* FIXME: Do they mean Hawaiian ("haw_US", 1000 speakers)
1909 or Hawaii Creole English ("cpe_US", 600000 speakers)? */
1910 switch (sub)
1912 case SUBLANG_DEFAULT: return "cpe_US";
1914 return "cpe";
1915 case LANG_HEBREW:
1916 switch (sub)
1918 case SUBLANG_HEBREW_ISRAEL: return "he_IL";
1920 return "he";
1921 case LANG_HINDI:
1922 switch (sub)
1924 case SUBLANG_HINDI_INDIA: return "hi_IN";
1926 return "hi";
1927 case LANG_HUNGARIAN:
1928 switch (sub)
1930 case SUBLANG_HUNGARIAN_HUNGARY: return "hu_HU";
1932 return "hu";
1933 case LANG_IBIBIO:
1934 switch (sub)
1936 case SUBLANG_DEFAULT: return "nic_NG";
1938 return "nic";
1939 case LANG_ICELANDIC:
1940 switch (sub)
1942 case SUBLANG_ICELANDIC_ICELAND: return "is_IS";
1944 return "is";
1945 case LANG_IGBO:
1946 switch (sub)
1948 case SUBLANG_IGBO_NIGERIA: return "ig_NG";
1950 return "ig";
1951 case LANG_INDONESIAN:
1952 switch (sub)
1954 case SUBLANG_INDONESIAN_INDONESIA: return "id_ID";
1956 return "id";
1957 case LANG_INUKTITUT:
1958 switch (sub)
1960 case 0x1e: return "iu"; /* syllabic */
1961 case SUBLANG_INUKTITUT_CANADA: return "iu_CA"; /* syllabic */
1962 case 0x1f: return "iu@latin";
1963 case SUBLANG_INUKTITUT_CANADA_LATIN: return "iu_CA@latin";
1965 return "iu";
1966 case LANG_ITALIAN:
1967 switch (sub)
1969 case SUBLANG_ITALIAN: return "it_IT";
1970 case SUBLANG_ITALIAN_SWISS: return "it_CH";
1972 return "it";
1973 case LANG_JAPANESE:
1974 switch (sub)
1976 case SUBLANG_JAPANESE_JAPAN: return "ja_JP";
1978 return "ja";
1979 case LANG_KANNADA:
1980 switch (sub)
1982 case SUBLANG_KANNADA_INDIA: return "kn_IN";
1984 return "kn";
1985 case LANG_KANURI:
1986 switch (sub)
1988 case SUBLANG_DEFAULT: return "kr_NG";
1990 return "kr";
1991 case LANG_KASHMIRI:
1992 switch (sub)
1994 case SUBLANG_DEFAULT: return "ks_PK";
1995 case SUBLANG_KASHMIRI_INDIA: return "ks_IN";
1997 return "ks";
1998 case LANG_KAZAK:
1999 switch (sub)
2001 case SUBLANG_KAZAK_KAZAKHSTAN: return "kk_KZ";
2003 return "kk";
2004 case LANG_KICHE:
2005 /* FIXME: Adjust this when such locales appear on Unix. */
2006 switch (sub)
2008 case SUBLANG_KICHE_GUATEMALA: return "qut_GT";
2010 return "qut";
2011 case LANG_KINYARWANDA:
2012 switch (sub)
2014 case SUBLANG_KINYARWANDA_RWANDA: return "rw_RW";
2016 return "rw";
2017 case LANG_KONKANI:
2018 /* FIXME: Adjust this when such locales appear on Unix. */
2019 switch (sub)
2021 case SUBLANG_KONKANI_INDIA: return "kok_IN";
2023 return "kok";
2024 case LANG_KOREAN:
2025 switch (sub)
2027 case SUBLANG_DEFAULT: return "ko_KR";
2029 return "ko";
2030 case LANG_KYRGYZ:
2031 switch (sub)
2033 case SUBLANG_KYRGYZ_KYRGYZSTAN: return "ky_KG";
2035 return "ky";
2036 case LANG_LAO:
2037 switch (sub)
2039 case SUBLANG_LAO_LAOS: return "lo_LA";
2041 return "lo";
2042 case LANG_LATIN:
2043 switch (sub)
2045 case SUBLANG_DEFAULT: return "la_VA";
2047 return "la";
2048 case LANG_LATVIAN:
2049 switch (sub)
2051 case SUBLANG_LATVIAN_LATVIA: return "lv_LV";
2053 return "lv";
2054 case LANG_LITHUANIAN:
2055 switch (sub)
2057 case SUBLANG_LITHUANIAN_LITHUANIA: return "lt_LT";
2059 return "lt";
2060 case LANG_LUXEMBOURGISH:
2061 switch (sub)
2063 case SUBLANG_LUXEMBOURGISH_LUXEMBOURG: return "lb_LU";
2065 return "lb";
2066 case LANG_MACEDONIAN:
2067 switch (sub)
2069 case SUBLANG_MACEDONIAN_MACEDONIA: return "mk_MK";
2071 return "mk";
2072 case LANG_MALAY:
2073 switch (sub)
2075 case SUBLANG_MALAY_MALAYSIA: return "ms_MY";
2076 case SUBLANG_MALAY_BRUNEI_DARUSSALAM: return "ms_BN";
2078 return "ms";
2079 case LANG_MALAYALAM:
2080 switch (sub)
2082 case SUBLANG_MALAYALAM_INDIA: return "ml_IN";
2084 return "ml";
2085 case LANG_MALTESE:
2086 switch (sub)
2088 case SUBLANG_MALTESE_MALTA: return "mt_MT";
2090 return "mt";
2091 case LANG_MANIPURI:
2092 /* FIXME: Adjust this when such locales appear on Unix. */
2093 switch (sub)
2095 case SUBLANG_DEFAULT: return "mni_IN";
2097 return "mni";
2098 case LANG_MAORI:
2099 switch (sub)
2101 case SUBLANG_MAORI_NEW_ZEALAND: return "mi_NZ";
2103 return "mi";
2104 case LANG_MAPUDUNGUN:
2105 switch (sub)
2107 case SUBLANG_MAPUDUNGUN_CHILE: return "arn_CL";
2109 return "arn";
2110 case LANG_MARATHI:
2111 switch (sub)
2113 case SUBLANG_MARATHI_INDIA: return "mr_IN";
2115 return "mr";
2116 case LANG_MOHAWK:
2117 switch (sub)
2119 case SUBLANG_MOHAWK_CANADA: return "moh_CA";
2121 return "moh";
2122 case LANG_MONGOLIAN:
2123 switch (sub)
2125 case SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA: case 0x1e: return "mn_MN";
2126 case SUBLANG_MONGOLIAN_PRC: case 0x1f: return "mn_CN";
2128 return "mn"; /* Ambiguous: could be "mn_CN" or "mn_MN". */
2129 case LANG_NEPALI:
2130 switch (sub)
2132 case SUBLANG_NEPALI_NEPAL: return "ne_NP";
2133 case SUBLANG_NEPALI_INDIA: return "ne_IN";
2135 return "ne";
2136 case LANG_NORWEGIAN:
2137 switch (sub)
2139 case 0x1f: return "nb";
2140 case SUBLANG_NORWEGIAN_BOKMAL: return "nb_NO";
2141 case 0x1e: return "nn";
2142 case SUBLANG_NORWEGIAN_NYNORSK: return "nn_NO";
2144 return "no";
2145 case LANG_OCCITAN:
2146 switch (sub)
2148 case SUBLANG_OCCITAN_FRANCE: return "oc_FR";
2150 return "oc";
2151 case LANG_ORIYA:
2152 switch (sub)
2154 case SUBLANG_ORIYA_INDIA: return "or_IN";
2156 return "or";
2157 case LANG_OROMO:
2158 switch (sub)
2160 case SUBLANG_DEFAULT: return "om_ET";
2162 return "om";
2163 case LANG_PAPIAMENTU:
2164 switch (sub)
2166 case SUBLANG_DEFAULT: return "pap_AN";
2168 return "pap";
2169 case LANG_PASHTO:
2170 switch (sub)
2172 case SUBLANG_PASHTO_AFGHANISTAN: return "ps_AF";
2174 return "ps"; /* Ambiguous: could be "ps_PK" or "ps_AF". */
2175 case LANG_POLISH:
2176 switch (sub)
2178 case SUBLANG_POLISH_POLAND: return "pl_PL";
2180 return "pl";
2181 case LANG_PORTUGUESE:
2182 switch (sub)
2184 /* Hmm. SUBLANG_PORTUGUESE_BRAZILIAN == SUBLANG_DEFAULT.
2185 Same phenomenon as SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. */
2186 case SUBLANG_PORTUGUESE_BRAZILIAN: return "pt_BR";
2187 case SUBLANG_PORTUGUESE: return "pt_PT";
2189 return "pt";
2190 case LANG_PUNJABI:
2191 switch (sub)
2193 case SUBLANG_PUNJABI_INDIA: return "pa_IN"; /* Gurmukhi script */
2194 case SUBLANG_PUNJABI_PAKISTAN: return "pa_PK"; /* Arabic script */
2196 return "pa";
2197 case LANG_QUECHUA:
2198 /* Note: Microsoft uses the non-ISO language code "quz". */
2199 switch (sub)
2201 case SUBLANG_QUECHUA_BOLIVIA: return "qu_BO";
2202 case SUBLANG_QUECHUA_ECUADOR: return "qu_EC";
2203 case SUBLANG_QUECHUA_PERU: return "qu_PE";
2205 return "qu";
2206 case LANG_ROMANIAN:
2207 switch (sub)
2209 case SUBLANG_ROMANIAN_ROMANIA: return "ro_RO";
2210 case SUBLANG_ROMANIAN_MOLDOVA: return "ro_MD";
2212 return "ro";
2213 case LANG_ROMANSH:
2214 switch (sub)
2216 case SUBLANG_ROMANSH_SWITZERLAND: return "rm_CH";
2218 return "rm";
2219 case LANG_RUSSIAN:
2220 switch (sub)
2222 case SUBLANG_RUSSIAN_RUSSIA: return "ru_RU";
2223 case SUBLANG_RUSSIAN_MOLDAVIA: return "ru_MD";
2225 return "ru"; /* Ambiguous: could be "ru_RU" or "ru_UA" or "ru_MD". */
2226 case LANG_SAMI:
2227 switch (sub)
2229 /* Northern Sami */
2230 case 0x00: return "se";
2231 case SUBLANG_SAMI_NORTHERN_NORWAY: return "se_NO";
2232 case SUBLANG_SAMI_NORTHERN_SWEDEN: return "se_SE";
2233 case SUBLANG_SAMI_NORTHERN_FINLAND: return "se_FI";
2234 /* Lule Sami */
2235 case 0x1f: return "smj";
2236 case SUBLANG_SAMI_LULE_NORWAY: return "smj_NO";
2237 case SUBLANG_SAMI_LULE_SWEDEN: return "smj_SE";
2238 /* Southern Sami */
2239 case 0x1e: return "sma";
2240 case SUBLANG_SAMI_SOUTHERN_NORWAY: return "sma_NO";
2241 case SUBLANG_SAMI_SOUTHERN_SWEDEN: return "sma_SE";
2242 /* Skolt Sami */
2243 case 0x1d: return "sms";
2244 case SUBLANG_SAMI_SKOLT_FINLAND: return "sms_FI";
2245 /* Inari Sami */
2246 case 0x1c: return "smn";
2247 case SUBLANG_SAMI_INARI_FINLAND: return "smn_FI";
2249 return "se"; /* or "smi"? */
2250 case LANG_SANSKRIT:
2251 switch (sub)
2253 case SUBLANG_SANSKRIT_INDIA: return "sa_IN";
2255 return "sa";
2256 case LANG_SCOTTISH_GAELIC:
2257 switch (sub)
2259 case SUBLANG_DEFAULT: return "gd_GB";
2261 return "gd";
2262 case LANG_SINDHI:
2263 switch (sub)
2265 case SUBLANG_SINDHI_INDIA: return "sd_IN";
2266 case SUBLANG_SINDHI_PAKISTAN: return "sd_PK";
2267 /*case SUBLANG_SINDHI_AFGHANISTAN: return "sd_AF";*/
2269 return "sd";
2270 case LANG_SINHALESE:
2271 switch (sub)
2273 case SUBLANG_SINHALESE_SRI_LANKA: return "si_LK";
2275 return "si";
2276 case LANG_SLOVAK:
2277 switch (sub)
2279 case SUBLANG_SLOVAK_SLOVAKIA: return "sk_SK";
2281 return "sk";
2282 case LANG_SLOVENIAN:
2283 switch (sub)
2285 case SUBLANG_SLOVENIAN_SLOVENIA: return "sl_SI";
2287 return "sl";
2288 case LANG_SOMALI:
2289 switch (sub)
2291 case SUBLANG_DEFAULT: return "so_SO";
2293 return "so";
2294 case LANG_SORBIAN:
2295 /* FIXME: Adjust this when such locales appear on Unix. */
2296 switch (sub)
2298 /* Upper Sorbian */
2299 case 0x00: return "hsb";
2300 case SUBLANG_UPPER_SORBIAN_GERMANY: return "hsb_DE";
2301 /* Lower Sorbian */
2302 case 0x1f: return "dsb";
2303 case SUBLANG_LOWER_SORBIAN_GERMANY: return "dsb_DE";
2305 return "wen";
2306 case LANG_SOTHO:
2307 /* <https://docs.microsoft.com/en-us/windows/desktop/Intl/language-identifier-constants-and-strings>
2308 calls it "Sesotho sa Leboa"; according to
2309 <https://www.ethnologue.com/show_language.asp?code=nso>
2310 <https://www.ethnologue.com/show_language.asp?code=sot>
2311 it's the same as Northern Sotho. */
2312 switch (sub)
2314 case SUBLANG_SOTHO_SOUTH_AFRICA: return "nso_ZA";
2316 return "nso";
2317 case LANG_SPANISH:
2318 switch (sub)
2320 case SUBLANG_SPANISH: return "es_ES";
2321 case SUBLANG_SPANISH_MEXICAN: return "es_MX";
2322 case SUBLANG_SPANISH_MODERN:
2323 return "es_ES@modern"; /* not seen on Unix */
2324 case SUBLANG_SPANISH_GUATEMALA: return "es_GT";
2325 case SUBLANG_SPANISH_COSTA_RICA: return "es_CR";
2326 case SUBLANG_SPANISH_PANAMA: return "es_PA";
2327 case SUBLANG_SPANISH_DOMINICAN_REPUBLIC: return "es_DO";
2328 case SUBLANG_SPANISH_VENEZUELA: return "es_VE";
2329 case SUBLANG_SPANISH_COLOMBIA: return "es_CO";
2330 case SUBLANG_SPANISH_PERU: return "es_PE";
2331 case SUBLANG_SPANISH_ARGENTINA: return "es_AR";
2332 case SUBLANG_SPANISH_ECUADOR: return "es_EC";
2333 case SUBLANG_SPANISH_CHILE: return "es_CL";
2334 case SUBLANG_SPANISH_URUGUAY: return "es_UY";
2335 case SUBLANG_SPANISH_PARAGUAY: return "es_PY";
2336 case SUBLANG_SPANISH_BOLIVIA: return "es_BO";
2337 case SUBLANG_SPANISH_EL_SALVADOR: return "es_SV";
2338 case SUBLANG_SPANISH_HONDURAS: return "es_HN";
2339 case SUBLANG_SPANISH_NICARAGUA: return "es_NI";
2340 case SUBLANG_SPANISH_PUERTO_RICO: return "es_PR";
2341 case SUBLANG_SPANISH_US: return "es_US";
2343 return "es";
2344 case LANG_SUTU:
2345 switch (sub)
2347 case SUBLANG_DEFAULT: return "bnt_TZ"; /* or "st_LS" or "nso_ZA"? */
2349 return "bnt";
2350 case LANG_SWAHILI:
2351 switch (sub)
2353 case SUBLANG_SWAHILI_KENYA: return "sw_KE";
2355 return "sw";
2356 case LANG_SWEDISH:
2357 switch (sub)
2359 case SUBLANG_SWEDISH_SWEDEN: return "sv_SE";
2360 case SUBLANG_SWEDISH_FINLAND: return "sv_FI";
2362 return "sv";
2363 case LANG_SYRIAC:
2364 switch (sub)
2366 case SUBLANG_SYRIAC_SYRIA: return "syr_SY"; /* An extinct language. */
2368 return "syr";
2369 case LANG_TAGALOG:
2370 switch (sub)
2372 case SUBLANG_TAGALOG_PHILIPPINES: return "tl_PH"; /* or "fil_PH"? */
2374 return "tl"; /* or "fil"? */
2375 case LANG_TAJIK:
2376 switch (sub)
2378 case 0x1f: return "tg";
2379 case SUBLANG_TAJIK_TAJIKISTAN: return "tg_TJ";
2381 return "tg";
2382 case LANG_TAMAZIGHT:
2383 /* Note: Microsoft uses the non-ISO language code "tmz". */
2384 switch (sub)
2386 /* FIXME: Adjust this when Tamazight locales appear on Unix. */
2387 case SUBLANG_TAMAZIGHT_ARABIC: return "ber_MA@arabic";
2388 case 0x1f: return "ber@latin";
2389 case SUBLANG_TAMAZIGHT_ALGERIA_LATIN: return "ber_DZ@latin";
2391 return "ber";
2392 case LANG_TAMIL:
2393 switch (sub)
2395 case SUBLANG_TAMIL_INDIA: return "ta_IN";
2397 return "ta"; /* Ambiguous: could be "ta_IN" or "ta_LK" or "ta_SG". */
2398 case LANG_TATAR:
2399 switch (sub)
2401 case SUBLANG_TATAR_RUSSIA: return "tt_RU";
2403 return "tt";
2404 case LANG_TELUGU:
2405 switch (sub)
2407 case SUBLANG_TELUGU_INDIA: return "te_IN";
2409 return "te";
2410 case LANG_THAI:
2411 switch (sub)
2413 case SUBLANG_THAI_THAILAND: return "th_TH";
2415 return "th";
2416 case LANG_TIBETAN:
2417 switch (sub)
2419 case SUBLANG_TIBETAN_PRC:
2420 /* Most Tibetans would not like "bo_CN". But Tibet does not yet
2421 have a country code of its own. */
2422 return "bo";
2423 case SUBLANG_TIBETAN_BHUTAN: return "bo_BT";
2425 return "bo";
2426 case LANG_TIGRINYA:
2427 switch (sub)
2429 case SUBLANG_TIGRINYA_ETHIOPIA: return "ti_ET";
2430 case SUBLANG_TIGRINYA_ERITREA: return "ti_ER";
2432 return "ti";
2433 case LANG_TSONGA:
2434 switch (sub)
2436 case SUBLANG_DEFAULT: return "ts_ZA";
2438 return "ts";
2439 case LANG_TSWANA:
2440 /* Spoken in South Africa, Botswana. */
2441 switch (sub)
2443 case SUBLANG_TSWANA_SOUTH_AFRICA: return "tn_ZA";
2445 return "tn";
2446 case LANG_TURKISH:
2447 switch (sub)
2449 case SUBLANG_TURKISH_TURKEY: return "tr_TR";
2451 return "tr";
2452 case LANG_TURKMEN:
2453 switch (sub)
2455 case SUBLANG_TURKMEN_TURKMENISTAN: return "tk_TM";
2457 return "tk";
2458 case LANG_UIGHUR:
2459 switch (sub)
2461 case SUBLANG_UIGHUR_PRC: return "ug_CN";
2463 return "ug";
2464 case LANG_UKRAINIAN:
2465 switch (sub)
2467 case SUBLANG_UKRAINIAN_UKRAINE: return "uk_UA";
2469 return "uk";
2470 case LANG_URDU:
2471 switch (sub)
2473 case SUBLANG_URDU_PAKISTAN: return "ur_PK";
2474 case SUBLANG_URDU_INDIA: return "ur_IN";
2476 return "ur";
2477 case LANG_UZBEK:
2478 switch (sub)
2480 case 0x1f: return "uz";
2481 case SUBLANG_UZBEK_LATIN: return "uz_UZ";
2482 case 0x1e: return "uz@cyrillic";
2483 case SUBLANG_UZBEK_CYRILLIC: return "uz_UZ@cyrillic";
2485 return "uz";
2486 case LANG_VENDA:
2487 switch (sub)
2489 case SUBLANG_DEFAULT: return "ve_ZA";
2491 return "ve";
2492 case LANG_VIETNAMESE:
2493 switch (sub)
2495 case SUBLANG_VIETNAMESE_VIETNAM: return "vi_VN";
2497 return "vi";
2498 case LANG_WELSH:
2499 switch (sub)
2501 case SUBLANG_WELSH_UNITED_KINGDOM: return "cy_GB";
2503 return "cy";
2504 case LANG_WOLOF:
2505 switch (sub)
2507 case SUBLANG_WOLOF_SENEGAL: return "wo_SN";
2509 return "wo";
2510 case LANG_XHOSA:
2511 switch (sub)
2513 case SUBLANG_XHOSA_SOUTH_AFRICA: return "xh_ZA";
2515 return "xh";
2516 case LANG_YAKUT:
2517 switch (sub)
2519 case SUBLANG_YAKUT_RUSSIA: return "sah_RU";
2521 return "sah";
2522 case LANG_YI:
2523 switch (sub)
2525 case SUBLANG_YI_PRC: return "ii_CN";
2527 return "ii";
2528 case LANG_YIDDISH:
2529 switch (sub)
2531 case SUBLANG_DEFAULT: return "yi_IL";
2533 return "yi";
2534 case LANG_YORUBA:
2535 switch (sub)
2537 case SUBLANG_YORUBA_NIGERIA: return "yo_NG";
2539 return "yo";
2540 case LANG_ZULU:
2541 switch (sub)
2543 case SUBLANG_ZULU_SOUTH_AFRICA: return "zu_ZA";
2545 return "zu";
2546 default: return "C";
2551 # if !defined IN_LIBINTL
2552 static
2553 # endif
2554 const char *
2555 gl_locale_name_from_win32_LCID (LCID lcid)
2557 LANGID langid;
2559 /* Strip off the sorting rules, keep only the language part. */
2560 langid = LANGIDFROMLCID (lcid);
2562 return gl_locale_name_from_win32_LANGID (langid);
2565 # ifdef WINDOWS_NATIVE
2567 /* Two variables to interface between get_lcid and the EnumLocales
2568 callback function below. */
2569 static LCID found_lcid;
2570 static char lname[LC_MAX * (LOCALE_NAME_MAX_LENGTH + 1) + 1];
2572 /* Callback function for EnumLocales. */
2573 static BOOL CALLBACK
2574 enum_locales_fn (LPSTR locale_num_str)
2576 char *endp;
2577 char locval[2 * LOCALE_NAME_MAX_LENGTH + 1 + 1];
2578 LCID try_lcid = strtoul (locale_num_str, &endp, 16);
2580 if (GetLocaleInfo (try_lcid, LOCALE_SENGLANGUAGE,
2581 locval, LOCALE_NAME_MAX_LENGTH))
2583 strcat (locval, "_");
2584 if (GetLocaleInfo (try_lcid, LOCALE_SENGCOUNTRY,
2585 locval + strlen (locval), LOCALE_NAME_MAX_LENGTH))
2587 size_t locval_len = strlen (locval);
2589 if (strncmp (locval, lname, locval_len) == 0
2590 && (lname[locval_len] == '.'
2591 || lname[locval_len] == '\0'))
2593 found_lcid = try_lcid;
2594 return FALSE;
2598 return TRUE;
2601 /* This lock protects the get_lcid against multiple simultaneous calls. */
2602 gl_lock_define_initialized(static, get_lcid_lock)
2604 /* Return the Locale ID (LCID) number given the locale's name, a
2605 string, in LOCALE_NAME. This works by enumerating all the locales
2606 supported by the system, until we find one whose name matches
2607 LOCALE_NAME. */
2608 static LCID
2609 get_lcid (const char *locale_name)
2611 /* A simple cache. */
2612 static LCID last_lcid;
2613 static char last_locale[1000];
2615 /* Lock while looking for an LCID, to protect access to static
2616 variables: last_lcid, last_locale, found_lcid, and lname. */
2617 gl_lock_lock (get_lcid_lock);
2618 if (last_lcid > 0 && strcmp (locale_name, last_locale) == 0)
2620 gl_lock_unlock (get_lcid_lock);
2621 return last_lcid;
2623 strncpy (lname, locale_name, sizeof (lname) - 1);
2624 lname[sizeof (lname) - 1] = '\0';
2625 found_lcid = 0;
2626 EnumSystemLocales (enum_locales_fn, LCID_SUPPORTED);
2627 if (found_lcid > 0)
2629 last_lcid = found_lcid;
2630 strcpy (last_locale, locale_name);
2632 gl_lock_unlock (get_lcid_lock);
2633 return found_lcid;
2636 # endif
2637 #endif
2640 #if HAVE_GOOD_USELOCALE /* glibc, Mac OS X, FreeBSD >= 9.1, Cygwin >= 2.6,
2641 Solaris 11 OpenIndiana, or Solaris >= 11.4 */
2643 /* Simple hash set of strings. We don't want to drag in lots of hash table
2644 code here. */
2646 # define SIZE_BITS (sizeof (size_t) * CHAR_BIT)
2648 /* A hash function for NUL-terminated char* strings using
2649 the method described by Bruno Haible.
2650 See https://www.haible.de/bruno/hashfunc.html. */
2651 static size_t _GL_ATTRIBUTE_PURE
2652 string_hash (const void *x)
2654 const char *s = (const char *) x;
2655 size_t h = 0;
2657 for (; *s; s++)
2658 h = *s + ((h << 9) | (h >> (SIZE_BITS - 9)));
2660 return h;
2663 /* A hash table of fixed size. Multiple threads can access it read-only
2664 simultaneously, but only one thread can insert into it at the same time. */
2666 /* A node in a hash bucket collision list. */
2667 struct struniq_hash_node
2669 struct struniq_hash_node * volatile next;
2670 char contents[FLEXIBLE_ARRAY_MEMBER];
2673 # define STRUNIQ_HASH_TABLE_SIZE 257
2674 static struct struniq_hash_node * volatile struniq_hash_table[STRUNIQ_HASH_TABLE_SIZE]
2675 /* = { NULL, ..., NULL } */;
2677 /* This lock protects the struniq_hash_table against multiple simultaneous
2678 insertions. */
2679 gl_lock_define_initialized(static, struniq_lock)
2681 /* Store a copy of the given string in a string pool with indefinite extent.
2682 Return a pointer to this copy. */
2683 static const char *
2684 struniq (const char *string)
2686 size_t hashcode = string_hash (string);
2687 size_t slot = hashcode % STRUNIQ_HASH_TABLE_SIZE;
2688 size_t size;
2689 struct struniq_hash_node *new_node;
2690 struct struniq_hash_node *p;
2691 for (p = struniq_hash_table[slot]; p != NULL; p = p->next)
2692 if (strcmp (p->contents, string) == 0)
2693 return p->contents;
2694 size = strlen (string) + 1;
2695 new_node =
2696 (struct struniq_hash_node *)
2697 malloc (FLEXSIZEOF (struct struniq_hash_node, contents, size));
2698 if (new_node == NULL)
2699 /* Out of memory. Return a statically allocated string. */
2700 return "C";
2701 memcpy (new_node->contents, string, size);
2703 bool mt = gl_multithreaded ();
2704 /* Lock while inserting new_node. */
2705 if (mt) gl_lock_lock (struniq_lock);
2706 /* Check whether another thread already added the string while we were
2707 waiting on the lock. */
2708 for (p = struniq_hash_table[slot]; p != NULL; p = p->next)
2709 if (strcmp (p->contents, string) == 0)
2711 free (new_node);
2712 new_node = p;
2713 goto done;
2715 /* Really insert new_node into the hash table. Fill new_node entirely
2716 first, because other threads may be iterating over the linked list. */
2717 new_node->next = struniq_hash_table[slot];
2718 struniq_hash_table[slot] = new_node;
2719 done:
2720 /* Unlock after new_node is inserted. */
2721 if (mt) gl_lock_unlock (struniq_lock);
2723 return new_node->contents;
2726 #endif
2729 #if HAVE_GOOD_USELOCALE && HAVE_NAMELESS_LOCALES
2731 /* The 'locale_t' object does not contain the names of the locale categories.
2732 We have to associate them with the object through a hash table.
2733 The hash table is defined in localename-table.[hc]. */
2735 /* Returns the name of a given locale category in a given locale_t object,
2736 allocated as a string with indefinite extent. */
2737 static const char *
2738 get_locale_t_name (int category, locale_t locale)
2740 if (locale == LC_GLOBAL_LOCALE)
2742 /* Query the global locale. */
2743 const char *name = setlocale_null (category);
2744 if (name != NULL)
2745 return struniq (name);
2746 else
2747 /* Should normally not happen. */
2748 return "";
2750 else
2752 /* Look up the names in the hash table. */
2753 size_t hashcode = locale_hash_function (locale);
2754 size_t slot = hashcode % LOCALE_HASH_TABLE_SIZE;
2755 /* If the locale was not found in the table, return "". This can
2756 happen if the application uses the original newlocale()/duplocale()
2757 functions instead of the overridden ones. */
2758 const char *name = "";
2759 struct locale_hash_node *p;
2760 /* Lock while looking up the hash node. */
2761 gl_rwlock_rdlock (locale_lock);
2762 for (p = locale_hash_table[slot]; p != NULL; p = p->next)
2763 if (p->locale == locale)
2765 name = p->names.category_name[category];
2766 break;
2768 gl_rwlock_unlock (locale_lock);
2769 return name;
2773 # if !(defined newlocale && defined duplocale && defined freelocale)
2774 # error "newlocale, duplocale, freelocale not being replaced as expected!"
2775 # endif
2777 /* newlocale() override. */
2778 locale_t
2779 newlocale (int category_mask, const char *name, locale_t base)
2780 #undef newlocale
2782 struct locale_categories_names names;
2783 struct locale_hash_node *node;
2784 locale_t result;
2786 /* Make sure name has indefinite extent. */
2787 if (((LC_CTYPE_MASK | LC_NUMERIC_MASK | LC_TIME_MASK | LC_COLLATE_MASK
2788 | LC_MONETARY_MASK | LC_MESSAGES_MASK)
2789 & category_mask) != 0)
2790 name = struniq (name);
2792 /* Determine the category names of the result. */
2793 if (((LC_CTYPE_MASK | LC_NUMERIC_MASK | LC_TIME_MASK | LC_COLLATE_MASK
2794 | LC_MONETARY_MASK | LC_MESSAGES_MASK)
2795 & ~category_mask) == 0)
2797 /* Use name, ignore base. */
2798 int category;
2800 name = struniq (name);
2801 for (category = 0; category < 6; category++)
2802 names.category_name[category] = name;
2804 else
2806 /* Use base, possibly also name. */
2807 if (base == NULL)
2809 int category;
2811 for (category = 0; category < 6; category++)
2813 int mask;
2815 switch (category)
2817 case LC_CTYPE:
2818 mask = LC_CTYPE_MASK;
2819 break;
2820 case LC_NUMERIC:
2821 mask = LC_NUMERIC_MASK;
2822 break;
2823 case LC_TIME:
2824 mask = LC_TIME_MASK;
2825 break;
2826 case LC_COLLATE:
2827 mask = LC_COLLATE_MASK;
2828 break;
2829 case LC_MONETARY:
2830 mask = LC_MONETARY_MASK;
2831 break;
2832 case LC_MESSAGES:
2833 mask = LC_MESSAGES_MASK;
2834 break;
2835 default:
2836 abort ();
2838 names.category_name[category] =
2839 ((mask & category_mask) != 0 ? name : "C");
2842 else if (base == LC_GLOBAL_LOCALE)
2844 int category;
2846 for (category = 0; category < 6; category++)
2848 int mask;
2850 switch (category)
2852 case LC_CTYPE:
2853 mask = LC_CTYPE_MASK;
2854 break;
2855 case LC_NUMERIC:
2856 mask = LC_NUMERIC_MASK;
2857 break;
2858 case LC_TIME:
2859 mask = LC_TIME_MASK;
2860 break;
2861 case LC_COLLATE:
2862 mask = LC_COLLATE_MASK;
2863 break;
2864 case LC_MONETARY:
2865 mask = LC_MONETARY_MASK;
2866 break;
2867 case LC_MESSAGES:
2868 mask = LC_MESSAGES_MASK;
2869 break;
2870 default:
2871 abort ();
2873 names.category_name[category] =
2874 ((mask & category_mask) != 0
2875 ? name
2876 : get_locale_t_name (category, LC_GLOBAL_LOCALE));
2879 else
2881 /* Look up the names of base in the hash table. Like multiple calls
2882 of get_locale_t_name, but locking only once. */
2883 struct locale_hash_node *p;
2884 int category;
2886 /* Lock while looking up the hash node. */
2887 gl_rwlock_rdlock (locale_lock);
2888 for (p = locale_hash_table[locale_hash_function (base) % LOCALE_HASH_TABLE_SIZE];
2889 p != NULL;
2890 p = p->next)
2891 if (p->locale == base)
2892 break;
2894 for (category = 0; category < 6; category++)
2896 int mask;
2898 switch (category)
2900 case LC_CTYPE:
2901 mask = LC_CTYPE_MASK;
2902 break;
2903 case LC_NUMERIC:
2904 mask = LC_NUMERIC_MASK;
2905 break;
2906 case LC_TIME:
2907 mask = LC_TIME_MASK;
2908 break;
2909 case LC_COLLATE:
2910 mask = LC_COLLATE_MASK;
2911 break;
2912 case LC_MONETARY:
2913 mask = LC_MONETARY_MASK;
2914 break;
2915 case LC_MESSAGES:
2916 mask = LC_MESSAGES_MASK;
2917 break;
2918 default:
2919 abort ();
2921 names.category_name[category] =
2922 ((mask & category_mask) != 0
2923 ? name
2924 : (p != NULL ? p->names.category_name[category] : ""));
2927 gl_rwlock_unlock (locale_lock);
2931 node = (struct locale_hash_node *) malloc (sizeof (struct locale_hash_node));
2932 if (node == NULL)
2933 /* errno is set to ENOMEM. */
2934 return NULL;
2936 result = newlocale (category_mask, name, base);
2937 if (result == NULL)
2939 int saved_errno = errno;
2940 free (node);
2941 errno = saved_errno;
2942 return NULL;
2945 /* Fill the hash node. */
2946 node->locale = result;
2947 node->names = names;
2949 /* Insert it in the hash table. */
2951 size_t hashcode = locale_hash_function (result);
2952 size_t slot = hashcode % LOCALE_HASH_TABLE_SIZE;
2953 struct locale_hash_node *p;
2955 /* Lock while inserting the new node. */
2956 gl_rwlock_wrlock (locale_lock);
2957 for (p = locale_hash_table[slot]; p != NULL; p = p->next)
2958 if (p->locale == result)
2960 /* This can happen if the application uses the original freelocale()
2961 function instead of the overridden one. */
2962 p->names = node->names;
2963 break;
2965 if (p == NULL)
2967 node->next = locale_hash_table[slot];
2968 locale_hash_table[slot] = node;
2971 gl_rwlock_unlock (locale_lock);
2973 if (p != NULL)
2974 free (node);
2977 return result;
2980 /* duplocale() override. */
2981 locale_t
2982 duplocale (locale_t locale)
2983 #undef duplocale
2985 struct locale_hash_node *node;
2986 locale_t result;
2988 if (locale == NULL)
2989 /* Invalid argument. */
2990 abort ();
2992 node = (struct locale_hash_node *) malloc (sizeof (struct locale_hash_node));
2993 if (node == NULL)
2994 /* errno is set to ENOMEM. */
2995 return NULL;
2997 result = duplocale (locale);
2998 if (result == NULL)
3000 int saved_errno = errno;
3001 free (node);
3002 errno = saved_errno;
3003 return NULL;
3006 /* Fill the hash node. */
3007 node->locale = result;
3008 if (locale == LC_GLOBAL_LOCALE)
3010 int category;
3012 for (category = 0; category < 6; category++)
3013 node->names.category_name[category] =
3014 get_locale_t_name (category, LC_GLOBAL_LOCALE);
3016 /* Lock before inserting the new node. */
3017 gl_rwlock_wrlock (locale_lock);
3019 else
3021 struct locale_hash_node *p;
3023 /* Lock once, for the lookup and the insertion. */
3024 gl_rwlock_wrlock (locale_lock);
3026 for (p = locale_hash_table[locale_hash_function (locale) % LOCALE_HASH_TABLE_SIZE];
3027 p != NULL;
3028 p = p->next)
3029 if (p->locale == locale)
3030 break;
3031 if (p != NULL)
3032 node->names = p->names;
3033 else
3035 /* This can happen if the application uses the original
3036 newlocale()/duplocale() functions instead of the overridden
3037 ones. */
3038 int category;
3040 for (category = 0; category < 6; category++)
3041 node->names.category_name[category] = "";
3045 /* Insert it in the hash table. */
3047 size_t hashcode = locale_hash_function (result);
3048 size_t slot = hashcode % LOCALE_HASH_TABLE_SIZE;
3049 struct locale_hash_node *p;
3051 for (p = locale_hash_table[slot]; p != NULL; p = p->next)
3052 if (p->locale == result)
3054 /* This can happen if the application uses the original freelocale()
3055 function instead of the overridden one. */
3056 p->names = node->names;
3057 break;
3059 if (p == NULL)
3061 node->next = locale_hash_table[slot];
3062 locale_hash_table[slot] = node;
3065 gl_rwlock_unlock (locale_lock);
3067 if (p != NULL)
3068 free (node);
3071 return result;
3074 /* freelocale() override. */
3075 void
3076 freelocale (locale_t locale)
3077 #undef freelocale
3079 if (locale == NULL || locale == LC_GLOBAL_LOCALE)
3080 /* Invalid argument. */
3081 abort ();
3084 size_t hashcode = locale_hash_function (locale);
3085 size_t slot = hashcode % LOCALE_HASH_TABLE_SIZE;
3086 struct locale_hash_node *found;
3087 struct locale_hash_node **p;
3089 found = NULL;
3090 /* Lock while removing the hash node. */
3091 gl_rwlock_wrlock (locale_lock);
3092 for (p = &locale_hash_table[slot]; *p != NULL; p = &(*p)->next)
3093 if ((*p)->locale == locale)
3095 found = *p;
3096 *p = (*p)->next;
3097 break;
3099 gl_rwlock_unlock (locale_lock);
3100 free (found);
3103 freelocale (locale);
3106 #endif
3109 #if defined IN_LIBINTL || HAVE_GOOD_USELOCALE
3111 /* Like gl_locale_name_thread, except that the result is not in storage of
3112 indefinite extent. */
3113 # if !defined IN_LIBINTL
3114 static
3115 # endif
3116 const char *
3117 gl_locale_name_thread_unsafe (int category, const char *categoryname _GL_UNUSED)
3119 # if HAVE_GOOD_USELOCALE
3121 locale_t thread_locale = uselocale (NULL);
3122 if (thread_locale != LC_GLOBAL_LOCALE)
3124 # if __GLIBC__ >= 2 && !defined __UCLIBC__
3125 /* Work around an incorrect definition of the _NL_LOCALE_NAME macro in
3126 glibc < 2.12.
3127 See <https://sourceware.org/bugzilla/show_bug.cgi?id=10968>. */
3128 const char *name =
3129 nl_langinfo (_NL_ITEM ((category), _NL_ITEM_INDEX (-1)));
3130 if (name[0] == '\0')
3131 /* Fallback code for glibc < 2.4, which did not implement
3132 nl_langinfo (_NL_LOCALE_NAME (category)). */
3133 name = thread_locale->__names[category];
3134 return name;
3135 # elif defined __linux__ && HAVE_LANGINFO_H && defined NL_LOCALE_NAME
3136 /* musl libc */
3137 return nl_langinfo_l (NL_LOCALE_NAME (category), thread_locale);
3138 # elif (defined __FreeBSD__ || defined __DragonFly__) || (defined __APPLE__ && defined __MACH__)
3139 /* FreeBSD, Mac OS X */
3140 int mask;
3142 switch (category)
3144 case LC_CTYPE:
3145 mask = LC_CTYPE_MASK;
3146 break;
3147 case LC_NUMERIC:
3148 mask = LC_NUMERIC_MASK;
3149 break;
3150 case LC_TIME:
3151 mask = LC_TIME_MASK;
3152 break;
3153 case LC_COLLATE:
3154 mask = LC_COLLATE_MASK;
3155 break;
3156 case LC_MONETARY:
3157 mask = LC_MONETARY_MASK;
3158 break;
3159 case LC_MESSAGES:
3160 mask = LC_MESSAGES_MASK;
3161 break;
3162 default: /* We shouldn't get here. */
3163 return "";
3165 return querylocale (mask, thread_locale);
3166 # elif defined __sun
3167 # if HAVE_GETLOCALENAME_L
3168 /* Solaris >= 12. */
3169 return getlocalename_l (category, thread_locale);
3170 # elif HAVE_SOLARIS114_LOCALES
3171 /* Solaris >= 11.4. */
3172 void *lcp = (*thread_locale)->core.data->lcp;
3173 if (lcp != NULL)
3174 switch (category)
3176 case LC_CTYPE:
3177 case LC_NUMERIC:
3178 case LC_TIME:
3179 case LC_COLLATE:
3180 case LC_MONETARY:
3181 case LC_MESSAGES:
3182 return ((const char * const *) lcp)[category];
3183 default: /* We shouldn't get here. */
3184 return "";
3186 # elif HAVE_NAMELESS_LOCALES
3187 return get_locale_t_name (category, thread_locale);
3188 # else
3189 /* Solaris 11 OpenIndiana.
3190 For the internal structure of locale objects, see
3191 https://github.com/OpenIndiana/illumos-gate/blob/master/usr/src/lib/libc/port/locale/localeimpl.h */
3192 switch (category)
3194 case LC_CTYPE:
3195 case LC_NUMERIC:
3196 case LC_TIME:
3197 case LC_COLLATE:
3198 case LC_MONETARY:
3199 case LC_MESSAGES:
3200 return ((const char * const *) thread_locale)[category];
3201 default: /* We shouldn't get here. */
3202 return "";
3204 # endif
3205 # elif defined _AIX && HAVE_NAMELESS_LOCALES
3206 return get_locale_t_name (category, thread_locale);
3207 # elif defined __CYGWIN__
3208 /* Cygwin < 2.6 lacks uselocale and thread-local locales altogether.
3209 Cygwin <= 2.6.1 lacks NL_LOCALE_NAME, requiring peeking inside
3210 an opaque struct. */
3211 # ifdef NL_LOCALE_NAME
3212 return nl_langinfo_l (NL_LOCALE_NAME (category), thread_locale);
3213 # else
3214 /* FIXME: Remove when we can assume new-enough Cygwin. */
3215 struct __locale_t {
3216 char categories[7][32];
3218 return ((struct __locale_t *) thread_locale)->categories[category];
3219 # endif
3220 # elif defined __ANDROID__
3221 return MB_CUR_MAX == 4 ? "C.UTF-8" : "C";
3222 # endif
3225 # endif
3226 return NULL;
3229 #endif
3231 const char *
3232 gl_locale_name_thread (int category, const char *categoryname _GL_UNUSED)
3234 #if HAVE_GOOD_USELOCALE
3235 const char *name = gl_locale_name_thread_unsafe (category, categoryname);
3236 if (name != NULL)
3237 return struniq (name);
3238 #endif
3239 /* On WINDOWS_NATIVE, don't use GetThreadLocale() here, because when
3240 SetThreadLocale has not been called - which is a very frequent case -
3241 the value of GetThreadLocale() ignores past calls to 'setlocale'. */
3242 return NULL;
3245 /* XPG3 defines the result of 'setlocale (category, NULL)' as:
3246 "Directs 'setlocale()' to query 'category' and return the current
3247 setting of 'local'."
3248 However it does not specify the exact format. Neither do SUSV2 and
3249 ISO C 99. So we can use this feature only on selected systems (e.g.
3250 those using GNU C Library). */
3251 #if defined _LIBC || ((defined __GLIBC__ && __GLIBC__ >= 2) && !defined __UCLIBC__)
3252 # define HAVE_LOCALE_NULL
3253 #endif
3255 const char *
3256 gl_locale_name_posix (int category, const char *categoryname _GL_UNUSED)
3258 #if defined WINDOWS_NATIVE
3259 if (LC_MIN <= category && category <= LC_MAX)
3261 const char *locname =
3262 /* setlocale_null (category) is identical to setlocale (category, NULL)
3263 on this platform. */
3264 setlocale (category, NULL);
3266 /* Convert locale name to LCID. We don't want to use
3267 LocaleNameToLCID because (a) it is only available since Vista,
3268 and (b) it doesn't accept locale names returned by 'setlocale'. */
3269 LCID lcid = get_lcid (locname);
3271 if (lcid > 0)
3272 return gl_locale_name_from_win32_LCID (lcid);
3274 #endif
3276 const char *locname;
3278 /* Use the POSIX methods of looking to 'LC_ALL', 'LC_xxx', and 'LANG'.
3279 On some systems this can be done by the 'setlocale' function itself. */
3280 #if defined HAVE_LC_MESSAGES && defined HAVE_LOCALE_NULL
3281 locname = setlocale_null (category);
3282 #else
3283 /* On other systems we ignore what setlocale reports and instead look at the
3284 environment variables directly. This is necessary
3285 1. on systems which have a facility for customizing the default locale
3286 (Mac OS X, native Windows, Cygwin) and where the system's setlocale()
3287 function ignores this default locale (Mac OS X, Cygwin), in two cases:
3288 a. when the user missed to use the setlocale() override from libintl
3289 (for example by not including <libintl.h>),
3290 b. when setlocale supports only the "C" locale, such as on Cygwin
3291 1.5.x. In this case even the override from libintl cannot help.
3292 2. on all systems where setlocale supports only the "C" locale. */
3293 /* Strictly speaking, it is a POSIX violation to look at the environment
3294 variables regardless whether setlocale has been called or not. POSIX
3295 says:
3296 "For C-language programs, the POSIX locale shall be the
3297 default locale when the setlocale() function is not called."
3298 But we assume that all programs that use internationalized APIs call
3299 setlocale (LC_ALL, ""). */
3300 locname = gl_locale_name_environ (category, categoryname);
3301 #endif
3302 /* Convert the locale name from the format returned by setlocale() or found
3303 in the environment variables to the XPG syntax. */
3304 #if defined WINDOWS_NATIVE
3305 if (locname != NULL)
3307 /* Convert locale name to LCID. We don't want to use
3308 LocaleNameToLCID because (a) it is only available since Vista,
3309 and (b) it doesn't accept locale names returned by 'setlocale'. */
3310 LCID lcid = get_lcid (locname);
3312 if (lcid > 0)
3313 return gl_locale_name_from_win32_LCID (lcid);
3315 #endif
3316 return locname;
3320 const char *
3321 gl_locale_name_environ (int category _GL_UNUSED, const char *categoryname)
3323 const char *retval;
3325 /* Setting of LC_ALL overrides all other. */
3326 retval = getenv ("LC_ALL");
3327 if (retval != NULL && retval[0] != '\0')
3328 return retval;
3329 /* Next comes the name of the desired category. */
3330 retval = getenv (categoryname);
3331 if (retval != NULL && retval[0] != '\0')
3332 return retval;
3333 /* Last possibility is the LANG environment variable. */
3334 retval = getenv ("LANG");
3335 if (retval != NULL && retval[0] != '\0')
3337 #if HAVE_CFPREFERENCESCOPYAPPVALUE
3338 /* Mac OS X 10.2 or newer.
3339 Ignore invalid LANG value set by the Terminal application. */
3340 if (strcmp (retval, "UTF-8") != 0)
3341 #endif
3342 #if defined __CYGWIN__
3343 /* Cygwin.
3344 Ignore dummy LANG value set by ~/.profile. */
3345 if (strcmp (retval, "C.UTF-8") != 0)
3346 #endif
3347 return retval;
3350 return NULL;
3353 const char *
3354 gl_locale_name_default (void)
3356 /* POSIX:2001 says:
3357 "All implementations shall define a locale as the default locale, to be
3358 invoked when no environment variables are set, or set to the empty
3359 string. This default locale can be the POSIX locale or any other
3360 implementation-defined locale. Some implementations may provide
3361 facilities for local installation administrators to set the default
3362 locale, customizing it for each location. POSIX:2001 does not require
3363 such a facility.
3365 The systems with such a facility are Mac OS X and Windows: They provide a
3366 GUI that allows the user to choose a locale.
3367 - On Mac OS X, by default, none of LC_* or LANG are set. Starting with
3368 Mac OS X 10.4 or 10.5, LANG is set for processes launched by the
3369 'Terminal' application (but sometimes to an incorrect value "UTF-8").
3370 When no environment variable is set, setlocale (LC_ALL, "") uses the
3371 "C" locale.
3372 - On native Windows, by default, none of LC_* or LANG are set.
3373 When no environment variable is set, setlocale (LC_ALL, "") uses the
3374 locale chosen by the user.
3375 - On Cygwin 1.5.x, by default, none of LC_* or LANG are set.
3376 When no environment variable is set, setlocale (LC_ALL, "") uses the
3377 "C" locale.
3378 - On Cygwin 1.7, by default, LANG is set to "C.UTF-8" when the default
3379 ~/.profile is executed.
3380 When no environment variable is set, setlocale (LC_ALL, "") uses the
3381 "C.UTF-8" locale, which operates in the same way as the "C" locale.
3384 #if !(HAVE_CFPREFERENCESCOPYAPPVALUE || defined WINDOWS_NATIVE || defined __CYGWIN__)
3386 /* The system does not have a way of setting the locale, other than the
3387 POSIX specified environment variables. We use C as default locale. */
3388 return "C";
3390 #else
3392 /* Return an XPG style locale name language[_territory][@modifier].
3393 Don't even bother determining the codeset; it's not useful in this
3394 context, because message catalogs are not specific to a single
3395 codeset. */
3397 # if HAVE_CFPREFERENCESCOPYAPPVALUE
3398 /* Mac OS X 10.4 or newer */
3399 /* Don't use the API introduced in Mac OS X 10.5, CFLocaleCopyCurrent,
3400 because in macOS 10.13.4 it has the following behaviour:
3401 When two or more languages are specified in the
3402 "System Preferences > Language & Region > Preferred Languages" panel,
3403 it returns en_CC where CC is the territory (even when English is not among
3404 the preferred languages!). What we want instead is what
3405 CFLocaleCopyCurrent returned in earlier macOS releases and what
3406 CFPreferencesCopyAppValue still returns, namely ll_CC where ll is the
3407 first among the preferred languages and CC is the territory. */
3409 /* Cache the locale name, since CoreFoundation calls are expensive. */
3410 static const char *cached_localename;
3412 if (cached_localename == NULL)
3414 char namebuf[256];
3415 CFTypeRef value =
3416 CFPreferencesCopyAppValue (CFSTR ("AppleLocale"),
3417 kCFPreferencesCurrentApplication);
3418 if (value != NULL && CFGetTypeID (value) == CFStringGetTypeID ())
3420 CFStringRef name = (CFStringRef)value;
3422 if (CFStringGetCString (name, namebuf, sizeof (namebuf),
3423 kCFStringEncodingASCII))
3425 gl_locale_name_canonicalize (namebuf);
3426 cached_localename = strdup (namebuf);
3429 if (cached_localename == NULL)
3430 cached_localename = "C";
3432 return cached_localename;
3435 # endif
3437 # if defined WINDOWS_NATIVE || defined __CYGWIN__ /* Native Windows or Cygwin */
3439 LCID lcid;
3441 /* Use native Windows API locale ID. */
3442 lcid = GetThreadLocale ();
3444 return gl_locale_name_from_win32_LCID (lcid);
3446 # endif
3447 #endif
3450 /* Determine the current locale's name, and canonicalize it into XPG syntax
3451 language[_territory][.codeset][@modifier]
3452 The codeset part in the result is not reliable; the locale_charset()
3453 should be used for codeset information instead.
3454 The result must not be freed; it is statically allocated. */
3456 const char *
3457 gl_locale_name (int category, const char *categoryname)
3459 const char *retval;
3461 retval = gl_locale_name_thread (category, categoryname);
3462 if (retval != NULL)
3463 return retval;
3465 retval = gl_locale_name_posix (category, categoryname);
3466 if (retval != NULL)
3467 return retval;
3469 return gl_locale_name_default ();