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