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