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