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