1 /* Determine name of the currently selected locale.
2 Copyright (C) 1995-2021 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3 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 General Public License for more details.
14 You should have received a copy of the GNU 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>. */
25 # include "gettextP.h"
27 # include "localename.h"
37 #include "flexmember.h"
38 #include "setlocale_null.h"
39 #include "thread-optim.h"
41 #if HAVE_GOOD_USELOCALE
42 /* Mac OS X 10.5 defines the locale_t type in <xlocale.h>. */
43 # if defined __APPLE__ && defined __MACH__
46 # if (__GLIBC__ >= 2 && !defined __UCLIBC__) || (defined __linux__ && HAVE_LANGINFO_H) || defined __CYGWIN__
47 # include <langinfo.h>
49 # if !defined IN_LIBINTL
50 # include "glthread/lock.h"
53 # if HAVE_GETLOCALENAME_L
55 extern char * getlocalename_l(int, locale_t);
56 # elif HAVE_SOLARIS114_LOCALES
57 # include <sys/localedef.h>
60 # if HAVE_NAMELESS_LOCALES
61 # include "localename-table.h"
65 #if HAVE_CFPREFERENCESCOPYAPPVALUE
66 # include <CoreFoundation/CFString.h>
67 # include <CoreFoundation/CFPreferences.h>
70 #if defined _WIN32 && !defined __CYGWIN__
71 # define WINDOWS_NATIVE
72 # if !defined IN_LIBINTL
73 # include "glthread/lock.h"
77 #if defined WINDOWS_NATIVE || defined __CYGWIN__ /* Native Windows or Cygwin */
78 # define WIN32_LEAN_AND_MEAN
81 /* List of language codes, sorted by value:
107 0x1a LANG_CROATIAN == LANG_SERBIAN
189 0x6e LANG_LUXEMBOURGISH
190 0x6f LANG_GREENLANDIC
209 0x87 LANG_KINYARWANDA
212 0x91 LANG_SCOTTISH_GAELIC
214 /* Mingw headers don't have latest language and sublanguage codes. */
215 # ifndef LANG_AFRIKAANS
216 # define LANG_AFRIKAANS 0x36
218 # ifndef LANG_ALBANIAN
219 # define LANG_ALBANIAN 0x1c
221 # ifndef LANG_ALSATIAN
222 # define LANG_ALSATIAN 0x84
224 # ifndef LANG_AMHARIC
225 # define LANG_AMHARIC 0x5e
228 # define LANG_ARABIC 0x01
230 # ifndef LANG_ARMENIAN
231 # define LANG_ARMENIAN 0x2b
233 # ifndef LANG_ASSAMESE
234 # define LANG_ASSAMESE 0x4d
237 # define LANG_AZERI 0x2c
239 # ifndef LANG_BASHKIR
240 # define LANG_BASHKIR 0x6d
243 # define LANG_BASQUE 0x2d
245 # ifndef LANG_BELARUSIAN
246 # define LANG_BELARUSIAN 0x23
248 # ifndef LANG_BENGALI
249 # define LANG_BENGALI 0x45
252 # define LANG_BRETON 0x7e
254 # ifndef LANG_BURMESE
255 # define LANG_BURMESE 0x55
257 # ifndef LANG_CAMBODIAN
258 # define LANG_CAMBODIAN 0x53
260 # ifndef LANG_CATALAN
261 # define LANG_CATALAN 0x03
263 # ifndef LANG_CHEROKEE
264 # define LANG_CHEROKEE 0x5c
266 # ifndef LANG_CORSICAN
267 # define LANG_CORSICAN 0x83
270 # define LANG_DARI 0x8c
273 # define LANG_DIVEHI 0x65
276 # define LANG_EDO 0x66
278 # ifndef LANG_ESTONIAN
279 # define LANG_ESTONIAN 0x25
281 # ifndef LANG_FAEROESE
282 # define LANG_FAEROESE 0x38
285 # define LANG_FARSI 0x29
287 # ifndef LANG_FRISIAN
288 # define LANG_FRISIAN 0x62
290 # ifndef LANG_FULFULDE
291 # define LANG_FULFULDE 0x67
294 # define LANG_GAELIC 0x3c
296 # ifndef LANG_GALICIAN
297 # define LANG_GALICIAN 0x56
299 # ifndef LANG_GEORGIAN
300 # define LANG_GEORGIAN 0x37
302 # ifndef LANG_GREENLANDIC
303 # define LANG_GREENLANDIC 0x6f
305 # ifndef LANG_GUARANI
306 # define LANG_GUARANI 0x74
308 # ifndef LANG_GUJARATI
309 # define LANG_GUJARATI 0x47
312 # define LANG_HAUSA 0x68
314 # ifndef LANG_HAWAIIAN
315 # define LANG_HAWAIIAN 0x75
318 # define LANG_HEBREW 0x0d
321 # define LANG_HINDI 0x39
324 # define LANG_IBIBIO 0x69
327 # define LANG_IGBO 0x70
329 # ifndef LANG_INDONESIAN
330 # define LANG_INDONESIAN 0x21
332 # ifndef LANG_INUKTITUT
333 # define LANG_INUKTITUT 0x5d
335 # ifndef LANG_KANNADA
336 # define LANG_KANNADA 0x4b
339 # define LANG_KANURI 0x71
341 # ifndef LANG_KASHMIRI
342 # define LANG_KASHMIRI 0x60
345 # define LANG_KAZAK 0x3f
348 # define LANG_KICHE 0x86
350 # ifndef LANG_KINYARWANDA
351 # define LANG_KINYARWANDA 0x87
353 # ifndef LANG_KONKANI
354 # define LANG_KONKANI 0x57
357 # define LANG_KYRGYZ 0x40
360 # define LANG_LAO 0x54
363 # define LANG_LATIN 0x76
365 # ifndef LANG_LATVIAN
366 # define LANG_LATVIAN 0x26
368 # ifndef LANG_LITHUANIAN
369 # define LANG_LITHUANIAN 0x27
371 # ifndef LANG_LUXEMBOURGISH
372 # define LANG_LUXEMBOURGISH 0x6e
374 # ifndef LANG_MACEDONIAN
375 # define LANG_MACEDONIAN 0x2f
378 # define LANG_MALAY 0x3e
380 # ifndef LANG_MALAYALAM
381 # define LANG_MALAYALAM 0x4c
383 # ifndef LANG_MALTESE
384 # define LANG_MALTESE 0x3a
386 # ifndef LANG_MANIPURI
387 # define LANG_MANIPURI 0x58
390 # define LANG_MAORI 0x81
392 # ifndef LANG_MAPUDUNGUN
393 # define LANG_MAPUDUNGUN 0x7a
395 # ifndef LANG_MARATHI
396 # define LANG_MARATHI 0x4e
399 # define LANG_MOHAWK 0x7c
401 # ifndef LANG_MONGOLIAN
402 # define LANG_MONGOLIAN 0x50
405 # define LANG_NEPALI 0x61
407 # ifndef LANG_OCCITAN
408 # define LANG_OCCITAN 0x82
411 # define LANG_ORIYA 0x48
414 # define LANG_OROMO 0x72
416 # ifndef LANG_PAPIAMENTU
417 # define LANG_PAPIAMENTU 0x79
420 # define LANG_PASHTO 0x63
422 # ifndef LANG_PUNJABI
423 # define LANG_PUNJABI 0x46
425 # ifndef LANG_QUECHUA
426 # define LANG_QUECHUA 0x6b
428 # ifndef LANG_ROMANSH
429 # define LANG_ROMANSH 0x17
432 # define LANG_SAMI 0x3b
434 # ifndef LANG_SANSKRIT
435 # define LANG_SANSKRIT 0x4f
437 # ifndef LANG_SCOTTISH_GAELIC
438 # define LANG_SCOTTISH_GAELIC 0x91
440 # ifndef LANG_SERBIAN
441 # define LANG_SERBIAN 0x1a
444 # define LANG_SINDHI 0x59
446 # ifndef LANG_SINHALESE
447 # define LANG_SINHALESE 0x5b
450 # define LANG_SLOVAK 0x1b
453 # define LANG_SOMALI 0x77
455 # ifndef LANG_SORBIAN
456 # define LANG_SORBIAN 0x2e
459 # define LANG_SOTHO 0x6c
462 # define LANG_SUTU 0x30
464 # ifndef LANG_SWAHILI
465 # define LANG_SWAHILI 0x41
468 # define LANG_SYRIAC 0x5a
470 # ifndef LANG_TAGALOG
471 # define LANG_TAGALOG 0x64
474 # define LANG_TAJIK 0x28
476 # ifndef LANG_TAMAZIGHT
477 # define LANG_TAMAZIGHT 0x5f
480 # define LANG_TAMIL 0x49
483 # define LANG_TATAR 0x44
486 # define LANG_TELUGU 0x4a
489 # define LANG_THAI 0x1e
491 # ifndef LANG_TIBETAN
492 # define LANG_TIBETAN 0x51
494 # ifndef LANG_TIGRINYA
495 # define LANG_TIGRINYA 0x73
498 # define LANG_TSONGA 0x31
501 # define LANG_TSWANA 0x32
503 # ifndef LANG_TURKMEN
504 # define LANG_TURKMEN 0x42
507 # define LANG_UIGHUR 0x80
509 # ifndef LANG_UKRAINIAN
510 # define LANG_UKRAINIAN 0x22
513 # define LANG_URDU 0x20
516 # define LANG_UZBEK 0x43
519 # define LANG_VENDA 0x33
521 # ifndef LANG_VIETNAMESE
522 # define LANG_VIETNAMESE 0x2a
525 # define LANG_WELSH 0x52
528 # define LANG_WOLOF 0x88
531 # define LANG_XHOSA 0x34
534 # define LANG_YAKUT 0x85
537 # define LANG_YI 0x78
539 # ifndef LANG_YIDDISH
540 # define LANG_YIDDISH 0x3d
543 # define LANG_YORUBA 0x6a
546 # define LANG_ZULU 0x35
548 # ifndef SUBLANG_AFRIKAANS_SOUTH_AFRICA
549 # define SUBLANG_AFRIKAANS_SOUTH_AFRICA 0x01
551 # ifndef SUBLANG_ALBANIAN_ALBANIA
552 # define SUBLANG_ALBANIAN_ALBANIA 0x01
554 # ifndef SUBLANG_ALSATIAN_FRANCE
555 # define SUBLANG_ALSATIAN_FRANCE 0x01
557 # ifndef SUBLANG_AMHARIC_ETHIOPIA
558 # define SUBLANG_AMHARIC_ETHIOPIA 0x01
560 # ifndef SUBLANG_ARABIC_SAUDI_ARABIA
561 # define SUBLANG_ARABIC_SAUDI_ARABIA 0x01
563 # ifndef SUBLANG_ARABIC_IRAQ
564 # define SUBLANG_ARABIC_IRAQ 0x02
566 # ifndef SUBLANG_ARABIC_EGYPT
567 # define SUBLANG_ARABIC_EGYPT 0x03
569 # ifndef SUBLANG_ARABIC_LIBYA
570 # define SUBLANG_ARABIC_LIBYA 0x04
572 # ifndef SUBLANG_ARABIC_ALGERIA
573 # define SUBLANG_ARABIC_ALGERIA 0x05
575 # ifndef SUBLANG_ARABIC_MOROCCO
576 # define SUBLANG_ARABIC_MOROCCO 0x06
578 # ifndef SUBLANG_ARABIC_TUNISIA
579 # define SUBLANG_ARABIC_TUNISIA 0x07
581 # ifndef SUBLANG_ARABIC_OMAN
582 # define SUBLANG_ARABIC_OMAN 0x08
584 # ifndef SUBLANG_ARABIC_YEMEN
585 # define SUBLANG_ARABIC_YEMEN 0x09
587 # ifndef SUBLANG_ARABIC_SYRIA
588 # define SUBLANG_ARABIC_SYRIA 0x0a
590 # ifndef SUBLANG_ARABIC_JORDAN
591 # define SUBLANG_ARABIC_JORDAN 0x0b
593 # ifndef SUBLANG_ARABIC_LEBANON
594 # define SUBLANG_ARABIC_LEBANON 0x0c
596 # ifndef SUBLANG_ARABIC_KUWAIT
597 # define SUBLANG_ARABIC_KUWAIT 0x0d
599 # ifndef SUBLANG_ARABIC_UAE
600 # define SUBLANG_ARABIC_UAE 0x0e
602 # ifndef SUBLANG_ARABIC_BAHRAIN
603 # define SUBLANG_ARABIC_BAHRAIN 0x0f
605 # ifndef SUBLANG_ARABIC_QATAR
606 # define SUBLANG_ARABIC_QATAR 0x10
608 # ifndef SUBLANG_ARMENIAN_ARMENIA
609 # define SUBLANG_ARMENIAN_ARMENIA 0x01
611 # ifndef SUBLANG_ASSAMESE_INDIA
612 # define SUBLANG_ASSAMESE_INDIA 0x01
614 # ifndef SUBLANG_AZERI_LATIN
615 # define SUBLANG_AZERI_LATIN 0x01
617 # ifndef SUBLANG_AZERI_CYRILLIC
618 # define SUBLANG_AZERI_CYRILLIC 0x02
620 # ifndef SUBLANG_BASHKIR_RUSSIA
621 # define SUBLANG_BASHKIR_RUSSIA 0x01
623 # ifndef SUBLANG_BASQUE_BASQUE
624 # define SUBLANG_BASQUE_BASQUE 0x01
626 # ifndef SUBLANG_BELARUSIAN_BELARUS
627 # define SUBLANG_BELARUSIAN_BELARUS 0x01
629 # ifndef SUBLANG_BENGALI_INDIA
630 # define SUBLANG_BENGALI_INDIA 0x01
632 # ifndef SUBLANG_BENGALI_BANGLADESH
633 # define SUBLANG_BENGALI_BANGLADESH 0x02
635 # ifndef SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN
636 # define SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN 0x05
638 # ifndef SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC
639 # define SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC 0x08
641 # ifndef SUBLANG_BRETON_FRANCE
642 # define SUBLANG_BRETON_FRANCE 0x01
644 # ifndef SUBLANG_BULGARIAN_BULGARIA
645 # define SUBLANG_BULGARIAN_BULGARIA 0x01
647 # ifndef SUBLANG_CAMBODIAN_CAMBODIA
648 # define SUBLANG_CAMBODIAN_CAMBODIA 0x01
650 # ifndef SUBLANG_CATALAN_SPAIN
651 # define SUBLANG_CATALAN_SPAIN 0x01
653 # ifndef SUBLANG_CORSICAN_FRANCE
654 # define SUBLANG_CORSICAN_FRANCE 0x01
656 # ifndef SUBLANG_CROATIAN_CROATIA
657 # define SUBLANG_CROATIAN_CROATIA 0x01
659 # ifndef SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN
660 # define SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN 0x04
662 # ifndef SUBLANG_CHINESE_MACAU
663 # define SUBLANG_CHINESE_MACAU 0x05
665 # ifndef SUBLANG_CZECH_CZECH_REPUBLIC
666 # define SUBLANG_CZECH_CZECH_REPUBLIC 0x01
668 # ifndef SUBLANG_DANISH_DENMARK
669 # define SUBLANG_DANISH_DENMARK 0x01
671 # ifndef SUBLANG_DARI_AFGHANISTAN
672 # define SUBLANG_DARI_AFGHANISTAN 0x01
674 # ifndef SUBLANG_DIVEHI_MALDIVES
675 # define SUBLANG_DIVEHI_MALDIVES 0x01
677 # ifndef SUBLANG_DUTCH_SURINAM
678 # define SUBLANG_DUTCH_SURINAM 0x03
680 # ifndef SUBLANG_ENGLISH_SOUTH_AFRICA
681 # define SUBLANG_ENGLISH_SOUTH_AFRICA 0x07
683 # ifndef SUBLANG_ENGLISH_JAMAICA
684 # define SUBLANG_ENGLISH_JAMAICA 0x08
686 # ifndef SUBLANG_ENGLISH_CARIBBEAN
687 # define SUBLANG_ENGLISH_CARIBBEAN 0x09
689 # ifndef SUBLANG_ENGLISH_BELIZE
690 # define SUBLANG_ENGLISH_BELIZE 0x0a
692 # ifndef SUBLANG_ENGLISH_TRINIDAD
693 # define SUBLANG_ENGLISH_TRINIDAD 0x0b
695 # ifndef SUBLANG_ENGLISH_ZIMBABWE
696 # define SUBLANG_ENGLISH_ZIMBABWE 0x0c
698 # ifndef SUBLANG_ENGLISH_PHILIPPINES
699 # define SUBLANG_ENGLISH_PHILIPPINES 0x0d
701 # ifndef SUBLANG_ENGLISH_INDONESIA
702 # define SUBLANG_ENGLISH_INDONESIA 0x0e
704 # ifndef SUBLANG_ENGLISH_HONGKONG
705 # define SUBLANG_ENGLISH_HONGKONG 0x0f
707 # ifndef SUBLANG_ENGLISH_INDIA
708 # define SUBLANG_ENGLISH_INDIA 0x10
710 # ifndef SUBLANG_ENGLISH_MALAYSIA
711 # define SUBLANG_ENGLISH_MALAYSIA 0x11
713 # ifndef SUBLANG_ENGLISH_SINGAPORE
714 # define SUBLANG_ENGLISH_SINGAPORE 0x12
716 # ifndef SUBLANG_ESTONIAN_ESTONIA
717 # define SUBLANG_ESTONIAN_ESTONIA 0x01
719 # ifndef SUBLANG_FAEROESE_FAROE_ISLANDS
720 # define SUBLANG_FAEROESE_FAROE_ISLANDS 0x01
722 # ifndef SUBLANG_FARSI_IRAN
723 # define SUBLANG_FARSI_IRAN 0x01
725 # ifndef SUBLANG_FINNISH_FINLAND
726 # define SUBLANG_FINNISH_FINLAND 0x01
728 # ifndef SUBLANG_FRENCH_LUXEMBOURG
729 # define SUBLANG_FRENCH_LUXEMBOURG 0x05
731 # ifndef SUBLANG_FRENCH_MONACO
732 # define SUBLANG_FRENCH_MONACO 0x06
734 # ifndef SUBLANG_FRENCH_WESTINDIES
735 # define SUBLANG_FRENCH_WESTINDIES 0x07
737 # ifndef SUBLANG_FRENCH_REUNION
738 # define SUBLANG_FRENCH_REUNION 0x08
740 # ifndef SUBLANG_FRENCH_CONGO
741 # define SUBLANG_FRENCH_CONGO 0x09
743 # ifndef SUBLANG_FRENCH_SENEGAL
744 # define SUBLANG_FRENCH_SENEGAL 0x0a
746 # ifndef SUBLANG_FRENCH_CAMEROON
747 # define SUBLANG_FRENCH_CAMEROON 0x0b
749 # ifndef SUBLANG_FRENCH_COTEDIVOIRE
750 # define SUBLANG_FRENCH_COTEDIVOIRE 0x0c
752 # ifndef SUBLANG_FRENCH_MALI
753 # define SUBLANG_FRENCH_MALI 0x0d
755 # ifndef SUBLANG_FRENCH_MOROCCO
756 # define SUBLANG_FRENCH_MOROCCO 0x0e
758 # ifndef SUBLANG_FRENCH_HAITI
759 # define SUBLANG_FRENCH_HAITI 0x0f
761 # ifndef SUBLANG_FRISIAN_NETHERLANDS
762 # define SUBLANG_FRISIAN_NETHERLANDS 0x01
764 # ifndef SUBLANG_GALICIAN_SPAIN
765 # define SUBLANG_GALICIAN_SPAIN 0x01
767 # ifndef SUBLANG_GEORGIAN_GEORGIA
768 # define SUBLANG_GEORGIAN_GEORGIA 0x01
770 # ifndef SUBLANG_GERMAN_LUXEMBOURG
771 # define SUBLANG_GERMAN_LUXEMBOURG 0x04
773 # ifndef SUBLANG_GERMAN_LIECHTENSTEIN
774 # define SUBLANG_GERMAN_LIECHTENSTEIN 0x05
776 # ifndef SUBLANG_GREEK_GREECE
777 # define SUBLANG_GREEK_GREECE 0x01
779 # ifndef SUBLANG_GREENLANDIC_GREENLAND
780 # define SUBLANG_GREENLANDIC_GREENLAND 0x01
782 # ifndef SUBLANG_GUJARATI_INDIA
783 # define SUBLANG_GUJARATI_INDIA 0x01
785 # ifndef SUBLANG_HAUSA_NIGERIA_LATIN
786 # define SUBLANG_HAUSA_NIGERIA_LATIN 0x01
788 # ifndef SUBLANG_HEBREW_ISRAEL
789 # define SUBLANG_HEBREW_ISRAEL 0x01
791 # ifndef SUBLANG_HINDI_INDIA
792 # define SUBLANG_HINDI_INDIA 0x01
794 # ifndef SUBLANG_HUNGARIAN_HUNGARY
795 # define SUBLANG_HUNGARIAN_HUNGARY 0x01
797 # ifndef SUBLANG_ICELANDIC_ICELAND
798 # define SUBLANG_ICELANDIC_ICELAND 0x01
800 # ifndef SUBLANG_IGBO_NIGERIA
801 # define SUBLANG_IGBO_NIGERIA 0x01
803 # ifndef SUBLANG_INDONESIAN_INDONESIA
804 # define SUBLANG_INDONESIAN_INDONESIA 0x01
806 # ifndef SUBLANG_INUKTITUT_CANADA
807 # define SUBLANG_INUKTITUT_CANADA 0x01
809 # undef SUBLANG_INUKTITUT_CANADA_LATIN
810 # define SUBLANG_INUKTITUT_CANADA_LATIN 0x02
811 # undef SUBLANG_IRISH_IRELAND
812 # define SUBLANG_IRISH_IRELAND 0x02
813 # ifndef SUBLANG_JAPANESE_JAPAN
814 # define SUBLANG_JAPANESE_JAPAN 0x01
816 # ifndef SUBLANG_KANNADA_INDIA
817 # define SUBLANG_KANNADA_INDIA 0x01
819 # ifndef SUBLANG_KASHMIRI_INDIA
820 # define SUBLANG_KASHMIRI_INDIA 0x02
822 # ifndef SUBLANG_KAZAK_KAZAKHSTAN
823 # define SUBLANG_KAZAK_KAZAKHSTAN 0x01
825 # ifndef SUBLANG_KICHE_GUATEMALA
826 # define SUBLANG_KICHE_GUATEMALA 0x01
828 # ifndef SUBLANG_KINYARWANDA_RWANDA
829 # define SUBLANG_KINYARWANDA_RWANDA 0x01
831 # ifndef SUBLANG_KONKANI_INDIA
832 # define SUBLANG_KONKANI_INDIA 0x01
834 # ifndef SUBLANG_KYRGYZ_KYRGYZSTAN
835 # define SUBLANG_KYRGYZ_KYRGYZSTAN 0x01
837 # ifndef SUBLANG_LAO_LAOS
838 # define SUBLANG_LAO_LAOS 0x01
840 # ifndef SUBLANG_LATVIAN_LATVIA
841 # define SUBLANG_LATVIAN_LATVIA 0x01
843 # ifndef SUBLANG_LITHUANIAN_LITHUANIA
844 # define SUBLANG_LITHUANIAN_LITHUANIA 0x01
846 # undef SUBLANG_LOWER_SORBIAN_GERMANY
847 # define SUBLANG_LOWER_SORBIAN_GERMANY 0x02
848 # ifndef SUBLANG_LUXEMBOURGISH_LUXEMBOURG
849 # define SUBLANG_LUXEMBOURGISH_LUXEMBOURG 0x01
851 # ifndef SUBLANG_MACEDONIAN_MACEDONIA
852 # define SUBLANG_MACEDONIAN_MACEDONIA 0x01
854 # ifndef SUBLANG_MALAY_MALAYSIA
855 # define SUBLANG_MALAY_MALAYSIA 0x01
857 # ifndef SUBLANG_MALAY_BRUNEI_DARUSSALAM
858 # define SUBLANG_MALAY_BRUNEI_DARUSSALAM 0x02
860 # ifndef SUBLANG_MALAYALAM_INDIA
861 # define SUBLANG_MALAYALAM_INDIA 0x01
863 # ifndef SUBLANG_MALTESE_MALTA
864 # define SUBLANG_MALTESE_MALTA 0x01
866 # ifndef SUBLANG_MAORI_NEW_ZEALAND
867 # define SUBLANG_MAORI_NEW_ZEALAND 0x01
869 # ifndef SUBLANG_MAPUDUNGUN_CHILE
870 # define SUBLANG_MAPUDUNGUN_CHILE 0x01
872 # ifndef SUBLANG_MARATHI_INDIA
873 # define SUBLANG_MARATHI_INDIA 0x01
875 # ifndef SUBLANG_MOHAWK_CANADA
876 # define SUBLANG_MOHAWK_CANADA 0x01
878 # ifndef SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA
879 # define SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA 0x01
881 # ifndef SUBLANG_MONGOLIAN_PRC
882 # define SUBLANG_MONGOLIAN_PRC 0x02
884 # ifndef SUBLANG_NEPALI_NEPAL
885 # define SUBLANG_NEPALI_NEPAL 0x01
887 # ifndef SUBLANG_NEPALI_INDIA
888 # define SUBLANG_NEPALI_INDIA 0x02
890 # ifndef SUBLANG_OCCITAN_FRANCE
891 # define SUBLANG_OCCITAN_FRANCE 0x01
893 # ifndef SUBLANG_ORIYA_INDIA
894 # define SUBLANG_ORIYA_INDIA 0x01
896 # ifndef SUBLANG_PASHTO_AFGHANISTAN
897 # define SUBLANG_PASHTO_AFGHANISTAN 0x01
899 # ifndef SUBLANG_POLISH_POLAND
900 # define SUBLANG_POLISH_POLAND 0x01
902 # ifndef SUBLANG_PUNJABI_INDIA
903 # define SUBLANG_PUNJABI_INDIA 0x01
905 # ifndef SUBLANG_PUNJABI_PAKISTAN
906 # define SUBLANG_PUNJABI_PAKISTAN 0x02
908 # ifndef SUBLANG_QUECHUA_BOLIVIA
909 # define SUBLANG_QUECHUA_BOLIVIA 0x01
911 # ifndef SUBLANG_QUECHUA_ECUADOR
912 # define SUBLANG_QUECHUA_ECUADOR 0x02
914 # ifndef SUBLANG_QUECHUA_PERU
915 # define SUBLANG_QUECHUA_PERU 0x03
917 # ifndef SUBLANG_ROMANIAN_ROMANIA
918 # define SUBLANG_ROMANIAN_ROMANIA 0x01
920 # ifndef SUBLANG_ROMANIAN_MOLDOVA
921 # define SUBLANG_ROMANIAN_MOLDOVA 0x02
923 # ifndef SUBLANG_ROMANSH_SWITZERLAND
924 # define SUBLANG_ROMANSH_SWITZERLAND 0x01
926 # ifndef SUBLANG_RUSSIAN_RUSSIA
927 # define SUBLANG_RUSSIAN_RUSSIA 0x01
929 # ifndef SUBLANG_RUSSIAN_MOLDAVIA
930 # define SUBLANG_RUSSIAN_MOLDAVIA 0x02
932 # ifndef SUBLANG_SAMI_NORTHERN_NORWAY
933 # define SUBLANG_SAMI_NORTHERN_NORWAY 0x01
935 # ifndef SUBLANG_SAMI_NORTHERN_SWEDEN
936 # define SUBLANG_SAMI_NORTHERN_SWEDEN 0x02
938 # ifndef SUBLANG_SAMI_NORTHERN_FINLAND
939 # define SUBLANG_SAMI_NORTHERN_FINLAND 0x03
941 # ifndef SUBLANG_SAMI_LULE_NORWAY
942 # define SUBLANG_SAMI_LULE_NORWAY 0x04
944 # ifndef SUBLANG_SAMI_LULE_SWEDEN
945 # define SUBLANG_SAMI_LULE_SWEDEN 0x05
947 # ifndef SUBLANG_SAMI_SOUTHERN_NORWAY
948 # define SUBLANG_SAMI_SOUTHERN_NORWAY 0x06
950 # ifndef SUBLANG_SAMI_SOUTHERN_SWEDEN
951 # define SUBLANG_SAMI_SOUTHERN_SWEDEN 0x07
953 # undef SUBLANG_SAMI_SKOLT_FINLAND
954 # define SUBLANG_SAMI_SKOLT_FINLAND 0x08
955 # undef SUBLANG_SAMI_INARI_FINLAND
956 # define SUBLANG_SAMI_INARI_FINLAND 0x09
957 # ifndef SUBLANG_SANSKRIT_INDIA
958 # define SUBLANG_SANSKRIT_INDIA 0x01
960 # ifndef SUBLANG_SERBIAN_LATIN
961 # define SUBLANG_SERBIAN_LATIN 0x02
963 # ifndef SUBLANG_SERBIAN_CYRILLIC
964 # define SUBLANG_SERBIAN_CYRILLIC 0x03
966 # ifndef SUBLANG_SINDHI_INDIA
967 # define SUBLANG_SINDHI_INDIA 0x01
969 # undef SUBLANG_SINDHI_PAKISTAN
970 # define SUBLANG_SINDHI_PAKISTAN 0x02
971 # ifndef SUBLANG_SINDHI_AFGHANISTAN
972 # define SUBLANG_SINDHI_AFGHANISTAN 0x02
974 # ifndef SUBLANG_SINHALESE_SRI_LANKA
975 # define SUBLANG_SINHALESE_SRI_LANKA 0x01
977 # ifndef SUBLANG_SLOVAK_SLOVAKIA
978 # define SUBLANG_SLOVAK_SLOVAKIA 0x01
980 # ifndef SUBLANG_SLOVENIAN_SLOVENIA
981 # define SUBLANG_SLOVENIAN_SLOVENIA 0x01
983 # ifndef SUBLANG_SOTHO_SOUTH_AFRICA
984 # define SUBLANG_SOTHO_SOUTH_AFRICA 0x01
986 # ifndef SUBLANG_SPANISH_GUATEMALA
987 # define SUBLANG_SPANISH_GUATEMALA 0x04
989 # ifndef SUBLANG_SPANISH_COSTA_RICA
990 # define SUBLANG_SPANISH_COSTA_RICA 0x05
992 # ifndef SUBLANG_SPANISH_PANAMA
993 # define SUBLANG_SPANISH_PANAMA 0x06
995 # ifndef SUBLANG_SPANISH_DOMINICAN_REPUBLIC
996 # define SUBLANG_SPANISH_DOMINICAN_REPUBLIC 0x07
998 # ifndef SUBLANG_SPANISH_VENEZUELA
999 # define SUBLANG_SPANISH_VENEZUELA 0x08
1001 # ifndef SUBLANG_SPANISH_COLOMBIA
1002 # define SUBLANG_SPANISH_COLOMBIA 0x09
1004 # ifndef SUBLANG_SPANISH_PERU
1005 # define SUBLANG_SPANISH_PERU 0x0a
1007 # ifndef SUBLANG_SPANISH_ARGENTINA
1008 # define SUBLANG_SPANISH_ARGENTINA 0x0b
1010 # ifndef SUBLANG_SPANISH_ECUADOR
1011 # define SUBLANG_SPANISH_ECUADOR 0x0c
1013 # ifndef SUBLANG_SPANISH_CHILE
1014 # define SUBLANG_SPANISH_CHILE 0x0d
1016 # ifndef SUBLANG_SPANISH_URUGUAY
1017 # define SUBLANG_SPANISH_URUGUAY 0x0e
1019 # ifndef SUBLANG_SPANISH_PARAGUAY
1020 # define SUBLANG_SPANISH_PARAGUAY 0x0f
1022 # ifndef SUBLANG_SPANISH_BOLIVIA
1023 # define SUBLANG_SPANISH_BOLIVIA 0x10
1025 # ifndef SUBLANG_SPANISH_EL_SALVADOR
1026 # define SUBLANG_SPANISH_EL_SALVADOR 0x11
1028 # ifndef SUBLANG_SPANISH_HONDURAS
1029 # define SUBLANG_SPANISH_HONDURAS 0x12
1031 # ifndef SUBLANG_SPANISH_NICARAGUA
1032 # define SUBLANG_SPANISH_NICARAGUA 0x13
1034 # ifndef SUBLANG_SPANISH_PUERTO_RICO
1035 # define SUBLANG_SPANISH_PUERTO_RICO 0x14
1037 # ifndef SUBLANG_SPANISH_US
1038 # define SUBLANG_SPANISH_US 0x15
1040 # ifndef SUBLANG_SWAHILI_KENYA
1041 # define SUBLANG_SWAHILI_KENYA 0x01
1043 # ifndef SUBLANG_SWEDISH_SWEDEN
1044 # define SUBLANG_SWEDISH_SWEDEN 0x01
1046 # ifndef SUBLANG_SWEDISH_FINLAND
1047 # define SUBLANG_SWEDISH_FINLAND 0x02
1049 # ifndef SUBLANG_SYRIAC_SYRIA
1050 # define SUBLANG_SYRIAC_SYRIA 0x01
1052 # ifndef SUBLANG_TAGALOG_PHILIPPINES
1053 # define SUBLANG_TAGALOG_PHILIPPINES 0x01
1055 # ifndef SUBLANG_TAJIK_TAJIKISTAN
1056 # define SUBLANG_TAJIK_TAJIKISTAN 0x01
1058 # ifndef SUBLANG_TAMAZIGHT_ARABIC
1059 # define SUBLANG_TAMAZIGHT_ARABIC 0x01
1061 # ifndef SUBLANG_TAMAZIGHT_ALGERIA_LATIN
1062 # define SUBLANG_TAMAZIGHT_ALGERIA_LATIN 0x02
1064 # ifndef SUBLANG_TAMIL_INDIA
1065 # define SUBLANG_TAMIL_INDIA 0x01
1067 # ifndef SUBLANG_TATAR_RUSSIA
1068 # define SUBLANG_TATAR_RUSSIA 0x01
1070 # ifndef SUBLANG_TELUGU_INDIA
1071 # define SUBLANG_TELUGU_INDIA 0x01
1073 # ifndef SUBLANG_THAI_THAILAND
1074 # define SUBLANG_THAI_THAILAND 0x01
1076 # ifndef SUBLANG_TIBETAN_PRC
1077 # define SUBLANG_TIBETAN_PRC 0x01
1079 # undef SUBLANG_TIBETAN_BHUTAN
1080 # define SUBLANG_TIBETAN_BHUTAN 0x02
1081 # ifndef SUBLANG_TIGRINYA_ETHIOPIA
1082 # define SUBLANG_TIGRINYA_ETHIOPIA 0x01
1084 # ifndef SUBLANG_TIGRINYA_ERITREA
1085 # define SUBLANG_TIGRINYA_ERITREA 0x02
1087 # ifndef SUBLANG_TSWANA_SOUTH_AFRICA
1088 # define SUBLANG_TSWANA_SOUTH_AFRICA 0x01
1090 # ifndef SUBLANG_TURKISH_TURKEY
1091 # define SUBLANG_TURKISH_TURKEY 0x01
1093 # ifndef SUBLANG_TURKMEN_TURKMENISTAN
1094 # define SUBLANG_TURKMEN_TURKMENISTAN 0x01
1096 # ifndef SUBLANG_UIGHUR_PRC
1097 # define SUBLANG_UIGHUR_PRC 0x01
1099 # ifndef SUBLANG_UKRAINIAN_UKRAINE
1100 # define SUBLANG_UKRAINIAN_UKRAINE 0x01
1102 # ifndef SUBLANG_UPPER_SORBIAN_GERMANY
1103 # define SUBLANG_UPPER_SORBIAN_GERMANY 0x01
1105 # ifndef SUBLANG_URDU_PAKISTAN
1106 # define SUBLANG_URDU_PAKISTAN 0x01
1108 # ifndef SUBLANG_URDU_INDIA
1109 # define SUBLANG_URDU_INDIA 0x02
1111 # ifndef SUBLANG_UZBEK_LATIN
1112 # define SUBLANG_UZBEK_LATIN 0x01
1114 # ifndef SUBLANG_UZBEK_CYRILLIC
1115 # define SUBLANG_UZBEK_CYRILLIC 0x02
1117 # ifndef SUBLANG_VIETNAMESE_VIETNAM
1118 # define SUBLANG_VIETNAMESE_VIETNAM 0x01
1120 # ifndef SUBLANG_WELSH_UNITED_KINGDOM
1121 # define SUBLANG_WELSH_UNITED_KINGDOM 0x01
1123 # ifndef SUBLANG_WOLOF_SENEGAL
1124 # define SUBLANG_WOLOF_SENEGAL 0x01
1126 # ifndef SUBLANG_XHOSA_SOUTH_AFRICA
1127 # define SUBLANG_XHOSA_SOUTH_AFRICA 0x01
1129 # ifndef SUBLANG_YAKUT_RUSSIA
1130 # define SUBLANG_YAKUT_RUSSIA 0x01
1132 # ifndef SUBLANG_YI_PRC
1133 # define SUBLANG_YI_PRC 0x01
1135 # ifndef SUBLANG_YORUBA_NIGERIA
1136 # define SUBLANG_YORUBA_NIGERIA 0x01
1138 # ifndef SUBLANG_ZULU_SOUTH_AFRICA
1139 # define SUBLANG_ZULU_SOUTH_AFRICA 0x01
1141 /* GetLocaleInfoA operations. */
1142 # ifndef LOCALE_SNAME
1143 # define LOCALE_SNAME 0x5c
1145 # ifndef LOCALE_NAME_MAX_LENGTH
1146 # define LOCALE_NAME_MAX_LENGTH 85
1148 /* Don't assume that UNICODE is not defined. */
1149 # undef GetLocaleInfo
1150 # define GetLocaleInfo GetLocaleInfoA
1151 # undef EnumSystemLocales
1152 # define EnumSystemLocales EnumSystemLocalesA
1155 /* We want to use the system's setlocale() function here, not the gnulib
1160 #if HAVE_CFPREFERENCESCOPYAPPVALUE
1161 /* Mac OS X 10.4 or newer */
1163 /* Canonicalize a Mac OS X locale name to a Unix locale name.
1164 NAME is a sufficiently large buffer.
1165 On input, it contains the Mac OS X locale name.
1166 On output, it contains the Unix locale name. */
1167 # if !defined IN_LIBINTL
1171 gl_locale_name_canonicalize (char *name)
1173 /* This conversion is based on a posting by
1174 Deborah GoldSmith <goldsmit@apple.com> on 2005-03-08,
1175 https://lists.apple.com/archives/carbon-dev/2005/Mar/msg00293.html */
1177 /* Convert legacy (NeXTstep inherited) English names to Unix (ISO 639 and
1178 ISO 3166) names. Prior to Mac OS X 10.3, there is no API for doing this.
1179 Therefore we do it ourselves, using a table based on the results of the
1180 Mac OS X 10.3.8 function
1181 CFLocaleCreateCanonicalLocaleIdentifierFromString(). */
1182 typedef struct { const char legacy[21+1]; const char unixy[5+1]; }
1184 static const legacy_entry legacy_table[] = {
1185 { "Afrikaans", "af" },
1186 { "Albanian", "sq" },
1187 { "Amharic", "am" },
1189 { "Armenian", "hy" },
1190 { "Assamese", "as" },
1192 { "Azerbaijani", "az" },
1194 { "Belarusian", "be" },
1195 { "Belorussian", "be" },
1196 { "Bengali", "bn" },
1197 { "Brazilian Portugese", "pt_BR" },
1198 { "Brazilian Portuguese", "pt_BR" },
1200 { "Bulgarian", "bg" },
1201 { "Burmese", "my" },
1202 { "Byelorussian", "be" },
1203 { "Catalan", "ca" },
1205 { "Chichewa", "ny" },
1206 { "Chinese", "zh" },
1207 { "Chinese, Simplified", "zh_CN" },
1208 { "Chinese, Traditional", "zh_TW" },
1209 { "Chinese, Tradtional", "zh_TW" },
1210 { "Croatian", "hr" },
1214 { "Dzongkha", "dz" },
1215 { "English", "en" },
1216 { "Esperanto", "eo" },
1217 { "Estonian", "et" },
1218 { "Faroese", "fo" },
1220 { "Finnish", "fi" },
1221 { "Flemish", "nl_BE" },
1223 { "Galician", "gl" },
1224 { "Gallegan", "gl" },
1225 { "Georgian", "ka" },
1228 { "Greenlandic", "kl" },
1229 { "Guarani", "gn" },
1230 { "Gujarati", "gu" },
1231 { "Hawaiian", "haw" }, /* Yes, "haw", not "cpe". */
1234 { "Hungarian", "hu" },
1235 { "Icelandic", "is" },
1236 { "Indonesian", "id" },
1237 { "Inuktitut", "iu" },
1239 { "Italian", "it" },
1240 { "Japanese", "ja" },
1241 { "Javanese", "jv" },
1242 { "Kalaallisut", "kl" },
1243 { "Kannada", "kn" },
1244 { "Kashmiri", "ks" },
1247 { "Kinyarwanda", "rw" },
1248 { "Kirghiz", "ky" },
1250 { "Kurdish", "ku" },
1252 { "Latvian", "lv" },
1253 { "Lithuanian", "lt" },
1254 { "Macedonian", "mk" },
1255 { "Malagasy", "mg" },
1257 { "Malayalam", "ml" },
1258 { "Maltese", "mt" },
1260 { "Marathi", "mr" },
1261 { "Moldavian", "mo" },
1262 { "Mongolian", "mn" },
1264 { "Norwegian", "nb" }, /* Yes, "nb", not the obsolete "no". */
1266 { "Nynorsk", "nn" },
1269 { "Panjabi", "pa" },
1271 { "Persian", "fa" },
1273 { "Portuguese", "pt" },
1274 { "Portuguese, Brazilian", "pt_BR" },
1275 { "Punjabi", "pa" },
1277 { "Quechua", "qu" },
1278 { "Romanian", "ro" },
1281 { "Russian", "ru" },
1282 { "Sami", "se_NO" }, /* Not just "se". */
1283 { "Sanskrit", "sa" },
1284 { "Scottish", "gd" },
1285 { "Serbian", "sr" },
1286 { "Simplified Chinese", "zh_CN" },
1288 { "Sinhalese", "si" },
1290 { "Slovenian", "sl" },
1292 { "Spanish", "es" },
1293 { "Sundanese", "su" },
1294 { "Swahili", "sw" },
1295 { "Swedish", "sv" },
1296 { "Tagalog", "tl" },
1303 { "Tibetan", "bo" },
1304 { "Tigrinya", "ti" },
1306 { "Traditional Chinese", "zh_TW" },
1307 { "Turkish", "tr" },
1308 { "Turkmen", "tk" },
1310 { "Ukrainian", "uk" },
1313 { "Vietnamese", "vi" },
1318 /* Convert new-style locale names with language tags (ISO 639 and ISO 15924)
1319 to Unix (ISO 639 and ISO 3166) names. */
1320 typedef struct { const char langtag[7+1]; const char unixy[12+1]; }
1322 static const langtag_entry langtag_table[] = {
1323 /* Mac OS X has "az-Arab", "az-Cyrl", "az-Latn".
1324 The default script for az on Unix is Latin. */
1325 { "az-Latn", "az" },
1326 /* Mac OS X has "bs-Cyrl", "bs-Latn".
1327 The default script for bs on Unix is Latin. */
1328 { "bs-Latn", "bs" },
1329 /* Mac OS X has "ga-dots". Does not yet exist on Unix. */
1330 { "ga-dots", "ga" },
1331 /* Mac OS X has "kk-Cyrl".
1332 The default script for kk on Unix is Cyrillic. */
1333 { "kk-Cyrl", "kk" },
1334 /* Mac OS X has "mn-Cyrl", "mn-Mong".
1335 The default script for mn on Unix is Cyrillic. */
1336 { "mn-Cyrl", "mn" },
1337 /* Mac OS X has "ms-Arab", "ms-Latn".
1338 The default script for ms on Unix is Latin. */
1339 { "ms-Latn", "ms" },
1340 /* Mac OS X has "pa-Arab", "pa-Guru".
1341 Country codes are used to distinguish these on Unix. */
1342 { "pa-Arab", "pa_PK" },
1343 { "pa-Guru", "pa_IN" },
1344 /* Mac OS X has "shi-Latn", "shi-Tfng". Does not yet exist on Unix. */
1345 /* Mac OS X has "sr-Cyrl", "sr-Latn".
1346 The default script for sr on Unix is Cyrillic. */
1347 { "sr-Cyrl", "sr" },
1348 /* Mac OS X has "tg-Cyrl".
1349 The default script for tg on Unix is Cyrillic. */
1350 { "tg-Cyrl", "tg" },
1351 /* Mac OS X has "tk-Cyrl".
1352 The default script for tk on Unix is Cyrillic. */
1353 { "tk-Cyrl", "tk" },
1354 /* Mac OS X has "tt-Cyrl".
1355 The default script for tt on Unix is Cyrillic. */
1356 { "tt-Cyrl", "tt" },
1357 /* Mac OS X has "uz-Arab", "uz-Cyrl", "uz-Latn".
1358 The default script for uz on Unix is Latin. */
1359 { "uz-Latn", "uz" },
1360 /* Mac OS X has "vai-Latn", "vai-Vaii". Does not yet exist on Unix. */
1361 /* Mac OS X has "yue-Hans", "yue-Hant".
1362 The default script for yue on Unix is Simplified Han. */
1363 { "yue-Hans", "yue" },
1364 /* Mac OS X has "zh-Hans", "zh-Hant".
1365 Country codes are used to distinguish these on Unix. */
1366 { "zh-Hans", "zh_CN" },
1367 { "zh-Hant", "zh_TW" }
1370 /* Convert script names (ISO 15924) to Unix conventions.
1371 See https://www.unicode.org/iso15924/iso15924-codes.html */
1372 typedef struct { const char script[4+1]; const char unixy[9+1]; }
1374 static const script_entry script_table[] = {
1375 { "Arab", "arabic" },
1376 { "Cyrl", "cyrillic" },
1377 { "Latn", "latin" },
1378 { "Mong", "mongolian" }
1381 /* Step 1: Convert using legacy_table. */
1382 if (name[0] >= 'A' && name[0] <= 'Z')
1384 unsigned int i1, i2;
1386 i2 = sizeof (legacy_table) / sizeof (legacy_entry);
1389 /* At this point we know that if name occurs in legacy_table,
1390 its index must be >= i1 and < i2. */
1391 unsigned int i = (i1 + i2) >> 1;
1392 const legacy_entry *p = &legacy_table[i];
1393 if (strcmp (name, p->legacy) < 0)
1398 if (strcmp (name, legacy_table[i1].legacy) == 0)
1400 strcpy (name, legacy_table[i1].unixy);
1405 /* Step 2: Convert using langtag_table and script_table. */
1406 if (strlen (name) == 7 && name[2] == '-')
1408 unsigned int i1, i2;
1410 i2 = sizeof (langtag_table) / sizeof (langtag_entry);
1413 /* At this point we know that if name occurs in langtag_table,
1414 its index must be >= i1 and < i2. */
1415 unsigned int i = (i1 + i2) >> 1;
1416 const langtag_entry *p = &langtag_table[i];
1417 if (strcmp (name, p->langtag) < 0)
1422 if (strcmp (name, langtag_table[i1].langtag) == 0)
1424 strcpy (name, langtag_table[i1].unixy);
1429 i2 = sizeof (script_table) / sizeof (script_entry);
1432 /* At this point we know that if (name + 3) occurs in script_table,
1433 its index must be >= i1 and < i2. */
1434 unsigned int i = (i1 + i2) >> 1;
1435 const script_entry *p = &script_table[i];
1436 if (strcmp (name + 3, p->script) < 0)
1441 if (strcmp (name + 3, script_table[i1].script) == 0)
1444 strcpy (name + 3, script_table[i1].unixy);
1449 /* Step 3: Convert new-style dash to Unix underscore. */
1452 for (p = name; *p != '\0'; p++)
1461 #if defined WINDOWS_NATIVE || defined __CYGWIN__ /* Native Windows or Cygwin */
1463 /* Canonicalize a Windows native locale name to a Unix locale name.
1464 NAME is a sufficiently large buffer.
1465 On input, it contains the Windows locale name.
1466 On output, it contains the Unix locale name. */
1467 # if !defined IN_LIBINTL
1471 gl_locale_name_canonicalize (char *name)
1473 /* FIXME: This is probably incomplete: it does not handle "zh-Hans" and
1477 for (p = name; *p != '\0'; p++)
1482 for (; *p != '\0'; p++)
1484 if (*p >= 'a' && *p <= 'z')
1496 # if !defined IN_LIBINTL
1500 gl_locale_name_from_win32_LANGID (LANGID langid)
1502 /* Activate the new code only when the GETTEXT_MUI environment variable is
1503 set, for the time being, since the new code is not well tested. */
1504 if (getenv ("GETTEXT_MUI") != NULL)
1506 static char namebuf[256];
1508 /* Query the system's notion of locale name.
1509 On Windows95/98/ME, GetLocaleInfoA returns some incorrect results.
1510 But we don't need to support systems that are so old. */
1511 if (GetLocaleInfoA (MAKELCID (langid, SORT_DEFAULT), LOCALE_SNAME,
1512 namebuf, sizeof (namebuf) - 1))
1514 /* Convert it to a Unix locale name. */
1515 gl_locale_name_canonicalize (namebuf);
1519 /* Internet Explorer has an LCID to RFC3066 name mapping stored in
1520 HKEY_CLASSES_ROOT\Mime\Database\Rfc1766. But we better don't use that
1521 since IE's i18n subsystem is known to be inconsistent with the native
1522 Windows base (e.g. they have different character conversion facilities
1523 that produce different results). */
1524 /* Use our own table. */
1528 /* Split into language and territory part. */
1529 primary = PRIMARYLANGID (langid);
1530 sub = SUBLANGID (langid);
1532 /* Dispatch on language.
1533 See also https://www.unicode.org/unicode/onlinedat/languages.html .
1534 For details about languages, see https://www.ethnologue.com/ . */
1537 case LANG_AFRIKAANS:
1540 case SUBLANG_AFRIKAANS_SOUTH_AFRICA: return "af_ZA";
1546 case SUBLANG_ALBANIAN_ALBANIA: return "sq_AL";
1552 case SUBLANG_ALSATIAN_FRANCE: return "gsw_FR";
1558 case SUBLANG_AMHARIC_ETHIOPIA: return "am_ET";
1564 case SUBLANG_ARABIC_SAUDI_ARABIA: return "ar_SA";
1565 case SUBLANG_ARABIC_IRAQ: return "ar_IQ";
1566 case SUBLANG_ARABIC_EGYPT: return "ar_EG";
1567 case SUBLANG_ARABIC_LIBYA: return "ar_LY";
1568 case SUBLANG_ARABIC_ALGERIA: return "ar_DZ";
1569 case SUBLANG_ARABIC_MOROCCO: return "ar_MA";
1570 case SUBLANG_ARABIC_TUNISIA: return "ar_TN";
1571 case SUBLANG_ARABIC_OMAN: return "ar_OM";
1572 case SUBLANG_ARABIC_YEMEN: return "ar_YE";
1573 case SUBLANG_ARABIC_SYRIA: return "ar_SY";
1574 case SUBLANG_ARABIC_JORDAN: return "ar_JO";
1575 case SUBLANG_ARABIC_LEBANON: return "ar_LB";
1576 case SUBLANG_ARABIC_KUWAIT: return "ar_KW";
1577 case SUBLANG_ARABIC_UAE: return "ar_AE";
1578 case SUBLANG_ARABIC_BAHRAIN: return "ar_BH";
1579 case SUBLANG_ARABIC_QATAR: return "ar_QA";
1585 case SUBLANG_ARMENIAN_ARMENIA: return "hy_AM";
1591 case SUBLANG_ASSAMESE_INDIA: return "as_IN";
1597 /* FIXME: Adjust this when Azerbaijani locales appear on Unix. */
1598 case 0x1e: return "az@latin";
1599 case SUBLANG_AZERI_LATIN: return "az_AZ@latin";
1600 case 0x1d: return "az@cyrillic";
1601 case SUBLANG_AZERI_CYRILLIC: return "az_AZ@cyrillic";
1607 case SUBLANG_BASHKIR_RUSSIA: return "ba_RU";
1613 case SUBLANG_BASQUE_BASQUE: return "eu_ES";
1615 return "eu"; /* Ambiguous: could be "eu_ES" or "eu_FR". */
1616 case LANG_BELARUSIAN:
1619 case SUBLANG_BELARUSIAN_BELARUS: return "be_BY";
1625 case SUBLANG_BENGALI_INDIA: return "bn_IN";
1626 case SUBLANG_BENGALI_BANGLADESH: return "bn_BD";
1632 case SUBLANG_BRETON_FRANCE: return "br_FR";
1635 case LANG_BULGARIAN:
1638 case SUBLANG_BULGARIAN_BULGARIA: return "bg_BG";
1644 case SUBLANG_DEFAULT: return "my_MM";
1647 case LANG_CAMBODIAN:
1650 case SUBLANG_CAMBODIAN_CAMBODIA: return "km_KH";
1656 case SUBLANG_CATALAN_SPAIN: return "ca_ES";
1662 case SUBLANG_DEFAULT: return "chr_US";
1668 case SUBLANG_CHINESE_TRADITIONAL: case 0x1f: return "zh_TW";
1669 case SUBLANG_CHINESE_SIMPLIFIED: case 0x00: return "zh_CN";
1670 case SUBLANG_CHINESE_HONGKONG: return "zh_HK"; /* traditional */
1671 case SUBLANG_CHINESE_SINGAPORE: return "zh_SG"; /* simplified */
1672 case SUBLANG_CHINESE_MACAU: return "zh_MO"; /* traditional */
1678 case SUBLANG_CORSICAN_FRANCE: return "co_FR";
1681 case LANG_CROATIAN: /* LANG_CROATIAN == LANG_SERBIAN == LANG_BOSNIAN
1682 * What used to be called Serbo-Croatian
1683 * should really now be two separate
1684 * languages because of political reasons.
1685 * (Says tml, who knows nothing about Serbian
1687 * (I can feel those flames coming already.)
1692 case 0x00: return "hr";
1693 case SUBLANG_CROATIAN_CROATIA: return "hr_HR";
1694 case SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN: return "hr_BA";
1696 case 0x1f: return "sr";
1697 case 0x1c: return "sr"; /* latin */
1698 case SUBLANG_SERBIAN_LATIN: return "sr_CS"; /* latin */
1699 case 0x09: return "sr_RS"; /* latin */
1700 case 0x0b: return "sr_ME"; /* latin */
1701 case 0x06: return "sr_BA"; /* latin */
1702 case 0x1b: return "sr@cyrillic";
1703 case SUBLANG_SERBIAN_CYRILLIC: return "sr_CS@cyrillic";
1704 case 0x0a: return "sr_RS@cyrillic";
1705 case 0x0c: return "sr_ME@cyrillic";
1706 case 0x07: return "sr_BA@cyrillic";
1708 case 0x1e: return "bs";
1709 case 0x1a: return "bs"; /* latin */
1710 case SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN: return "bs_BA"; /* latin */
1711 case 0x19: return "bs@cyrillic";
1712 case SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC: return "bs_BA@cyrillic";
1718 case SUBLANG_CZECH_CZECH_REPUBLIC: return "cs_CZ";
1724 case SUBLANG_DANISH_DENMARK: return "da_DK";
1728 /* FIXME: Adjust this when such locales appear on Unix. */
1731 case SUBLANG_DARI_AFGHANISTAN: return "prs_AF";
1737 case SUBLANG_DIVEHI_MALDIVES: return "dv_MV";
1743 case SUBLANG_DUTCH: return "nl_NL";
1744 case SUBLANG_DUTCH_BELGIAN: /* FLEMISH, VLAAMS */ return "nl_BE";
1745 case SUBLANG_DUTCH_SURINAM: return "nl_SR";
1751 case SUBLANG_DEFAULT: return "bin_NG";
1757 /* SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. Heh. I thought
1758 * English was the language spoken in England.
1761 case SUBLANG_ENGLISH_US: return "en_US";
1762 case SUBLANG_ENGLISH_UK: return "en_GB";
1763 case SUBLANG_ENGLISH_AUS: return "en_AU";
1764 case SUBLANG_ENGLISH_CAN: return "en_CA";
1765 case SUBLANG_ENGLISH_NZ: return "en_NZ";
1766 case SUBLANG_ENGLISH_EIRE: return "en_IE";
1767 case SUBLANG_ENGLISH_SOUTH_AFRICA: return "en_ZA";
1768 case SUBLANG_ENGLISH_JAMAICA: return "en_JM";
1769 case SUBLANG_ENGLISH_CARIBBEAN: return "en_GD"; /* Grenada? */
1770 case SUBLANG_ENGLISH_BELIZE: return "en_BZ";
1771 case SUBLANG_ENGLISH_TRINIDAD: return "en_TT";
1772 case SUBLANG_ENGLISH_ZIMBABWE: return "en_ZW";
1773 case SUBLANG_ENGLISH_PHILIPPINES: return "en_PH";
1774 case SUBLANG_ENGLISH_INDONESIA: return "en_ID";
1775 case SUBLANG_ENGLISH_HONGKONG: return "en_HK";
1776 case SUBLANG_ENGLISH_INDIA: return "en_IN";
1777 case SUBLANG_ENGLISH_MALAYSIA: return "en_MY";
1778 case SUBLANG_ENGLISH_SINGAPORE: return "en_SG";
1784 case SUBLANG_ESTONIAN_ESTONIA: return "et_EE";
1790 case SUBLANG_FAEROESE_FAROE_ISLANDS: return "fo_FO";
1796 case SUBLANG_FARSI_IRAN: return "fa_IR";
1802 case SUBLANG_FINNISH_FINLAND: return "fi_FI";
1808 case SUBLANG_FRENCH: return "fr_FR";
1809 case SUBLANG_FRENCH_BELGIAN: /* WALLOON */ return "fr_BE";
1810 case SUBLANG_FRENCH_CANADIAN: return "fr_CA";
1811 case SUBLANG_FRENCH_SWISS: return "fr_CH";
1812 case SUBLANG_FRENCH_LUXEMBOURG: return "fr_LU";
1813 case SUBLANG_FRENCH_MONACO: return "fr_MC";
1814 case SUBLANG_FRENCH_WESTINDIES: return "fr"; /* Caribbean? */
1815 case SUBLANG_FRENCH_REUNION: return "fr_RE";
1816 case SUBLANG_FRENCH_CONGO: return "fr_CG";
1817 case SUBLANG_FRENCH_SENEGAL: return "fr_SN";
1818 case SUBLANG_FRENCH_CAMEROON: return "fr_CM";
1819 case SUBLANG_FRENCH_COTEDIVOIRE: return "fr_CI";
1820 case SUBLANG_FRENCH_MALI: return "fr_ML";
1821 case SUBLANG_FRENCH_MOROCCO: return "fr_MA";
1822 case SUBLANG_FRENCH_HAITI: return "fr_HT";
1828 case SUBLANG_FRISIAN_NETHERLANDS: return "fy_NL";
1832 /* Spoken in Nigeria, Guinea, Senegal, Mali, Niger, Cameroon, Benin. */
1835 case SUBLANG_DEFAULT: return "ff_NG";
1841 case 0x01: /* SCOTTISH */
1842 /* old, superseded by LANG_SCOTTISH_GAELIC */
1844 case SUBLANG_IRISH_IRELAND: return "ga_IE";
1850 case SUBLANG_GALICIAN_SPAIN: return "gl_ES";
1856 case SUBLANG_GEORGIAN_GEORGIA: return "ka_GE";
1862 case SUBLANG_GERMAN: return "de_DE";
1863 case SUBLANG_GERMAN_SWISS: return "de_CH";
1864 case SUBLANG_GERMAN_AUSTRIAN: return "de_AT";
1865 case SUBLANG_GERMAN_LUXEMBOURG: return "de_LU";
1866 case SUBLANG_GERMAN_LIECHTENSTEIN: return "de_LI";
1872 case SUBLANG_GREEK_GREECE: return "el_GR";
1875 case LANG_GREENLANDIC:
1878 case SUBLANG_GREENLANDIC_GREENLAND: return "kl_GL";
1884 case SUBLANG_DEFAULT: return "gn_PY";
1890 case SUBLANG_GUJARATI_INDIA: return "gu_IN";
1896 case 0x1f: return "ha";
1897 case SUBLANG_HAUSA_NIGERIA_LATIN: return "ha_NG";
1901 /* FIXME: Do they mean Hawaiian ("haw_US", 1000 speakers)
1902 or Hawaii Creole English ("cpe_US", 600000 speakers)? */
1905 case SUBLANG_DEFAULT: return "cpe_US";
1911 case SUBLANG_HEBREW_ISRAEL: return "he_IL";
1917 case SUBLANG_HINDI_INDIA: return "hi_IN";
1920 case LANG_HUNGARIAN:
1923 case SUBLANG_HUNGARIAN_HUNGARY: return "hu_HU";
1929 case SUBLANG_DEFAULT: return "nic_NG";
1932 case LANG_ICELANDIC:
1935 case SUBLANG_ICELANDIC_ICELAND: return "is_IS";
1941 case SUBLANG_IGBO_NIGERIA: return "ig_NG";
1944 case LANG_INDONESIAN:
1947 case SUBLANG_INDONESIAN_INDONESIA: return "id_ID";
1950 case LANG_INUKTITUT:
1953 case 0x1e: return "iu"; /* syllabic */
1954 case SUBLANG_INUKTITUT_CANADA: return "iu_CA"; /* syllabic */
1955 case 0x1f: return "iu@latin";
1956 case SUBLANG_INUKTITUT_CANADA_LATIN: return "iu_CA@latin";
1962 case SUBLANG_ITALIAN: return "it_IT";
1963 case SUBLANG_ITALIAN_SWISS: return "it_CH";
1969 case SUBLANG_JAPANESE_JAPAN: return "ja_JP";
1975 case SUBLANG_KANNADA_INDIA: return "kn_IN";
1981 case SUBLANG_DEFAULT: return "kr_NG";
1987 case SUBLANG_DEFAULT: return "ks_PK";
1988 case SUBLANG_KASHMIRI_INDIA: return "ks_IN";
1994 case SUBLANG_KAZAK_KAZAKHSTAN: return "kk_KZ";
1998 /* FIXME: Adjust this when such locales appear on Unix. */
2001 case SUBLANG_KICHE_GUATEMALA: return "qut_GT";
2004 case LANG_KINYARWANDA:
2007 case SUBLANG_KINYARWANDA_RWANDA: return "rw_RW";
2011 /* FIXME: Adjust this when such locales appear on Unix. */
2014 case SUBLANG_KONKANI_INDIA: return "kok_IN";
2020 case SUBLANG_DEFAULT: return "ko_KR";
2026 case SUBLANG_KYRGYZ_KYRGYZSTAN: return "ky_KG";
2032 case SUBLANG_LAO_LAOS: return "lo_LA";
2038 case SUBLANG_DEFAULT: return "la_VA";
2044 case SUBLANG_LATVIAN_LATVIA: return "lv_LV";
2047 case LANG_LITHUANIAN:
2050 case SUBLANG_LITHUANIAN_LITHUANIA: return "lt_LT";
2053 case LANG_LUXEMBOURGISH:
2056 case SUBLANG_LUXEMBOURGISH_LUXEMBOURG: return "lb_LU";
2059 case LANG_MACEDONIAN:
2062 case SUBLANG_MACEDONIAN_MACEDONIA: return "mk_MK";
2068 case SUBLANG_MALAY_MALAYSIA: return "ms_MY";
2069 case SUBLANG_MALAY_BRUNEI_DARUSSALAM: return "ms_BN";
2072 case LANG_MALAYALAM:
2075 case SUBLANG_MALAYALAM_INDIA: return "ml_IN";
2081 case SUBLANG_MALTESE_MALTA: return "mt_MT";
2085 /* FIXME: Adjust this when such locales appear on Unix. */
2088 case SUBLANG_DEFAULT: return "mni_IN";
2094 case SUBLANG_MAORI_NEW_ZEALAND: return "mi_NZ";
2097 case LANG_MAPUDUNGUN:
2100 case SUBLANG_MAPUDUNGUN_CHILE: return "arn_CL";
2106 case SUBLANG_MARATHI_INDIA: return "mr_IN";
2112 case SUBLANG_MOHAWK_CANADA: return "moh_CA";
2115 case LANG_MONGOLIAN:
2118 case SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA: case 0x1e: return "mn_MN";
2119 case SUBLANG_MONGOLIAN_PRC: case 0x1f: return "mn_CN";
2121 return "mn"; /* Ambiguous: could be "mn_CN" or "mn_MN". */
2125 case SUBLANG_NEPALI_NEPAL: return "ne_NP";
2126 case SUBLANG_NEPALI_INDIA: return "ne_IN";
2129 case LANG_NORWEGIAN:
2132 case 0x1f: return "nb";
2133 case SUBLANG_NORWEGIAN_BOKMAL: return "nb_NO";
2134 case 0x1e: return "nn";
2135 case SUBLANG_NORWEGIAN_NYNORSK: return "nn_NO";
2141 case SUBLANG_OCCITAN_FRANCE: return "oc_FR";
2147 case SUBLANG_ORIYA_INDIA: return "or_IN";
2153 case SUBLANG_DEFAULT: return "om_ET";
2156 case LANG_PAPIAMENTU:
2159 case SUBLANG_DEFAULT: return "pap_AN";
2165 case SUBLANG_PASHTO_AFGHANISTAN: return "ps_AF";
2167 return "ps"; /* Ambiguous: could be "ps_PK" or "ps_AF". */
2171 case SUBLANG_POLISH_POLAND: return "pl_PL";
2174 case LANG_PORTUGUESE:
2177 /* Hmm. SUBLANG_PORTUGUESE_BRAZILIAN == SUBLANG_DEFAULT.
2178 Same phenomenon as SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. */
2179 case SUBLANG_PORTUGUESE_BRAZILIAN: return "pt_BR";
2180 case SUBLANG_PORTUGUESE: return "pt_PT";
2186 case SUBLANG_PUNJABI_INDIA: return "pa_IN"; /* Gurmukhi script */
2187 case SUBLANG_PUNJABI_PAKISTAN: return "pa_PK"; /* Arabic script */
2191 /* Note: Microsoft uses the non-ISO language code "quz". */
2194 case SUBLANG_QUECHUA_BOLIVIA: return "qu_BO";
2195 case SUBLANG_QUECHUA_ECUADOR: return "qu_EC";
2196 case SUBLANG_QUECHUA_PERU: return "qu_PE";
2202 case SUBLANG_ROMANIAN_ROMANIA: return "ro_RO";
2203 case SUBLANG_ROMANIAN_MOLDOVA: return "ro_MD";
2209 case SUBLANG_ROMANSH_SWITZERLAND: return "rm_CH";
2215 case SUBLANG_RUSSIAN_RUSSIA: return "ru_RU";
2216 case SUBLANG_RUSSIAN_MOLDAVIA: return "ru_MD";
2218 return "ru"; /* Ambiguous: could be "ru_RU" or "ru_UA" or "ru_MD". */
2223 case 0x00: return "se";
2224 case SUBLANG_SAMI_NORTHERN_NORWAY: return "se_NO";
2225 case SUBLANG_SAMI_NORTHERN_SWEDEN: return "se_SE";
2226 case SUBLANG_SAMI_NORTHERN_FINLAND: return "se_FI";
2228 case 0x1f: return "smj";
2229 case SUBLANG_SAMI_LULE_NORWAY: return "smj_NO";
2230 case SUBLANG_SAMI_LULE_SWEDEN: return "smj_SE";
2232 case 0x1e: return "sma";
2233 case SUBLANG_SAMI_SOUTHERN_NORWAY: return "sma_NO";
2234 case SUBLANG_SAMI_SOUTHERN_SWEDEN: return "sma_SE";
2236 case 0x1d: return "sms";
2237 case SUBLANG_SAMI_SKOLT_FINLAND: return "sms_FI";
2239 case 0x1c: return "smn";
2240 case SUBLANG_SAMI_INARI_FINLAND: return "smn_FI";
2242 return "se"; /* or "smi"? */
2246 case SUBLANG_SANSKRIT_INDIA: return "sa_IN";
2249 case LANG_SCOTTISH_GAELIC:
2252 case SUBLANG_DEFAULT: return "gd_GB";
2258 case SUBLANG_SINDHI_INDIA: return "sd_IN";
2259 case SUBLANG_SINDHI_PAKISTAN: return "sd_PK";
2260 /*case SUBLANG_SINDHI_AFGHANISTAN: return "sd_AF";*/
2263 case LANG_SINHALESE:
2266 case SUBLANG_SINHALESE_SRI_LANKA: return "si_LK";
2272 case SUBLANG_SLOVAK_SLOVAKIA: return "sk_SK";
2275 case LANG_SLOVENIAN:
2278 case SUBLANG_SLOVENIAN_SLOVENIA: return "sl_SI";
2284 case SUBLANG_DEFAULT: return "so_SO";
2288 /* FIXME: Adjust this when such locales appear on Unix. */
2292 case 0x00: return "hsb";
2293 case SUBLANG_UPPER_SORBIAN_GERMANY: return "hsb_DE";
2295 case 0x1f: return "dsb";
2296 case SUBLANG_LOWER_SORBIAN_GERMANY: return "dsb_DE";
2300 /* <https://docs.microsoft.com/en-us/windows/desktop/Intl/language-identifier-constants-and-strings>
2301 calls it "Sesotho sa Leboa"; according to
2302 <https://www.ethnologue.com/show_language.asp?code=nso>
2303 <https://www.ethnologue.com/show_language.asp?code=sot>
2304 it's the same as Northern Sotho. */
2307 case SUBLANG_SOTHO_SOUTH_AFRICA: return "nso_ZA";
2313 case SUBLANG_SPANISH: return "es_ES";
2314 case SUBLANG_SPANISH_MEXICAN: return "es_MX";
2315 case SUBLANG_SPANISH_MODERN:
2316 return "es_ES@modern"; /* not seen on Unix */
2317 case SUBLANG_SPANISH_GUATEMALA: return "es_GT";
2318 case SUBLANG_SPANISH_COSTA_RICA: return "es_CR";
2319 case SUBLANG_SPANISH_PANAMA: return "es_PA";
2320 case SUBLANG_SPANISH_DOMINICAN_REPUBLIC: return "es_DO";
2321 case SUBLANG_SPANISH_VENEZUELA: return "es_VE";
2322 case SUBLANG_SPANISH_COLOMBIA: return "es_CO";
2323 case SUBLANG_SPANISH_PERU: return "es_PE";
2324 case SUBLANG_SPANISH_ARGENTINA: return "es_AR";
2325 case SUBLANG_SPANISH_ECUADOR: return "es_EC";
2326 case SUBLANG_SPANISH_CHILE: return "es_CL";
2327 case SUBLANG_SPANISH_URUGUAY: return "es_UY";
2328 case SUBLANG_SPANISH_PARAGUAY: return "es_PY";
2329 case SUBLANG_SPANISH_BOLIVIA: return "es_BO";
2330 case SUBLANG_SPANISH_EL_SALVADOR: return "es_SV";
2331 case SUBLANG_SPANISH_HONDURAS: return "es_HN";
2332 case SUBLANG_SPANISH_NICARAGUA: return "es_NI";
2333 case SUBLANG_SPANISH_PUERTO_RICO: return "es_PR";
2334 case SUBLANG_SPANISH_US: return "es_US";
2340 case SUBLANG_DEFAULT: return "bnt_TZ"; /* or "st_LS" or "nso_ZA"? */
2346 case SUBLANG_SWAHILI_KENYA: return "sw_KE";
2352 case SUBLANG_SWEDISH_SWEDEN: return "sv_SE";
2353 case SUBLANG_SWEDISH_FINLAND: return "sv_FI";
2359 case SUBLANG_SYRIAC_SYRIA: return "syr_SY"; /* An extinct language. */
2365 case SUBLANG_TAGALOG_PHILIPPINES: return "tl_PH"; /* or "fil_PH"? */
2367 return "tl"; /* or "fil"? */
2371 case 0x1f: return "tg";
2372 case SUBLANG_TAJIK_TAJIKISTAN: return "tg_TJ";
2375 case LANG_TAMAZIGHT:
2376 /* Note: Microsoft uses the non-ISO language code "tmz". */
2379 /* FIXME: Adjust this when Tamazight locales appear on Unix. */
2380 case SUBLANG_TAMAZIGHT_ARABIC: return "ber_MA@arabic";
2381 case 0x1f: return "ber@latin";
2382 case SUBLANG_TAMAZIGHT_ALGERIA_LATIN: return "ber_DZ@latin";
2388 case SUBLANG_TAMIL_INDIA: return "ta_IN";
2390 return "ta"; /* Ambiguous: could be "ta_IN" or "ta_LK" or "ta_SG". */
2394 case SUBLANG_TATAR_RUSSIA: return "tt_RU";
2400 case SUBLANG_TELUGU_INDIA: return "te_IN";
2406 case SUBLANG_THAI_THAILAND: return "th_TH";
2412 case SUBLANG_TIBETAN_PRC:
2413 /* Most Tibetans would not like "bo_CN". But Tibet does not yet
2414 have a country code of its own. */
2416 case SUBLANG_TIBETAN_BHUTAN: return "bo_BT";
2422 case SUBLANG_TIGRINYA_ETHIOPIA: return "ti_ET";
2423 case SUBLANG_TIGRINYA_ERITREA: return "ti_ER";
2429 case SUBLANG_DEFAULT: return "ts_ZA";
2433 /* Spoken in South Africa, Botswana. */
2436 case SUBLANG_TSWANA_SOUTH_AFRICA: return "tn_ZA";
2442 case SUBLANG_TURKISH_TURKEY: return "tr_TR";
2448 case SUBLANG_TURKMEN_TURKMENISTAN: return "tk_TM";
2454 case SUBLANG_UIGHUR_PRC: return "ug_CN";
2457 case LANG_UKRAINIAN:
2460 case SUBLANG_UKRAINIAN_UKRAINE: return "uk_UA";
2466 case SUBLANG_URDU_PAKISTAN: return "ur_PK";
2467 case SUBLANG_URDU_INDIA: return "ur_IN";
2473 case 0x1f: return "uz";
2474 case SUBLANG_UZBEK_LATIN: return "uz_UZ";
2475 case 0x1e: return "uz@cyrillic";
2476 case SUBLANG_UZBEK_CYRILLIC: return "uz_UZ@cyrillic";
2482 case SUBLANG_DEFAULT: return "ve_ZA";
2485 case LANG_VIETNAMESE:
2488 case SUBLANG_VIETNAMESE_VIETNAM: return "vi_VN";
2494 case SUBLANG_WELSH_UNITED_KINGDOM: return "cy_GB";
2500 case SUBLANG_WOLOF_SENEGAL: return "wo_SN";
2506 case SUBLANG_XHOSA_SOUTH_AFRICA: return "xh_ZA";
2512 case SUBLANG_YAKUT_RUSSIA: return "sah_RU";
2518 case SUBLANG_YI_PRC: return "ii_CN";
2524 case SUBLANG_DEFAULT: return "yi_IL";
2530 case SUBLANG_YORUBA_NIGERIA: return "yo_NG";
2536 case SUBLANG_ZULU_SOUTH_AFRICA: return "zu_ZA";
2539 default: return "C";
2544 # if !defined IN_LIBINTL
2548 gl_locale_name_from_win32_LCID (LCID lcid)
2552 /* Strip off the sorting rules, keep only the language part. */
2553 langid = LANGIDFROMLCID (lcid);
2555 return gl_locale_name_from_win32_LANGID (langid);
2558 # ifdef WINDOWS_NATIVE
2560 /* Two variables to interface between get_lcid and the EnumLocales
2561 callback function below. */
2562 static LCID found_lcid;
2563 static char lname[LC_MAX * (LOCALE_NAME_MAX_LENGTH + 1) + 1];
2565 /* Callback function for EnumLocales. */
2566 static BOOL CALLBACK
2567 enum_locales_fn (LPSTR locale_num_str)
2570 char locval[2 * LOCALE_NAME_MAX_LENGTH + 1 + 1];
2571 LCID try_lcid = strtoul (locale_num_str, &endp, 16);
2573 if (GetLocaleInfo (try_lcid, LOCALE_SENGLANGUAGE,
2574 locval, LOCALE_NAME_MAX_LENGTH))
2576 strcat (locval, "_");
2577 if (GetLocaleInfo (try_lcid, LOCALE_SENGCOUNTRY,
2578 locval + strlen (locval), LOCALE_NAME_MAX_LENGTH))
2580 size_t locval_len = strlen (locval);
2582 if (strncmp (locval, lname, locval_len) == 0
2583 && (lname[locval_len] == '.'
2584 || lname[locval_len] == '\0'))
2586 found_lcid = try_lcid;
2594 /* This lock protects the get_lcid against multiple simultaneous calls. */
2595 gl_lock_define_initialized(static, get_lcid_lock)
2597 /* Return the Locale ID (LCID) number given the locale's name, a
2598 string, in LOCALE_NAME. This works by enumerating all the locales
2599 supported by the system, until we find one whose name matches
2602 get_lcid (const char *locale_name)
2604 /* A simple cache. */
2605 static LCID last_lcid;
2606 static char last_locale[1000];
2608 /* Lock while looking for an LCID, to protect access to static
2609 variables: last_lcid, last_locale, found_lcid, and lname. */
2610 gl_lock_lock (get_lcid_lock);
2611 if (last_lcid > 0 && strcmp (locale_name, last_locale) == 0)
2613 gl_lock_unlock (get_lcid_lock);
2616 strncpy (lname, locale_name, sizeof (lname) - 1);
2617 lname[sizeof (lname) - 1] = '\0';
2619 EnumSystemLocales (enum_locales_fn, LCID_SUPPORTED);
2622 last_lcid = found_lcid;
2623 strcpy (last_locale, locale_name);
2625 gl_lock_unlock (get_lcid_lock);
2633 #if HAVE_GOOD_USELOCALE /* glibc, Mac OS X, FreeBSD >= 9.1, Cygwin >= 2.6,
2634 Solaris 11 OpenIndiana, or Solaris >= 11.4 */
2636 /* Simple hash set of strings. We don't want to drag in lots of hash table
2639 # define SIZE_BITS (sizeof (size_t) * CHAR_BIT)
2641 /* A hash function for NUL-terminated char* strings using
2642 the method described by Bruno Haible.
2643 See https://www.haible.de/bruno/hashfunc.html. */
2644 static size_t _GL_ATTRIBUTE_PURE
2645 string_hash (const void *x)
2647 const char *s = (const char *) x;
2651 h = *s + ((h << 9) | (h >> (SIZE_BITS - 9)));
2656 /* A hash table of fixed size. Multiple threads can access it read-only
2657 simultaneously, but only one thread can insert into it at the same time. */
2659 /* A node in a hash bucket collision list. */
2660 struct struniq_hash_node
2662 struct struniq_hash_node * volatile next;
2663 char contents[FLEXIBLE_ARRAY_MEMBER];
2666 # define STRUNIQ_HASH_TABLE_SIZE 257
2667 static struct struniq_hash_node * volatile struniq_hash_table[STRUNIQ_HASH_TABLE_SIZE]
2668 /* = { NULL, ..., NULL } */;
2670 /* This lock protects the struniq_hash_table against multiple simultaneous
2672 gl_lock_define_initialized(static, struniq_lock)
2674 /* Store a copy of the given string in a string pool with indefinite extent.
2675 Return a pointer to this copy. */
2677 struniq (const char *string)
2679 size_t hashcode = string_hash (string);
2680 size_t slot = hashcode % STRUNIQ_HASH_TABLE_SIZE;
2682 struct struniq_hash_node *new_node;
2683 struct struniq_hash_node *p;
2684 for (p = struniq_hash_table[slot]; p != NULL; p = p->next)
2685 if (strcmp (p->contents, string) == 0)
2687 size = strlen (string) + 1;
2689 (struct struniq_hash_node *)
2690 malloc (FLEXSIZEOF (struct struniq_hash_node, contents, size));
2691 if (new_node == NULL)
2692 /* Out of memory. Return a statically allocated string. */
2694 memcpy (new_node->contents, string, size);
2696 bool mt = gl_multithreaded ();
2697 /* Lock while inserting new_node. */
2698 if (mt) gl_lock_lock (struniq_lock);
2699 /* Check whether another thread already added the string while we were
2700 waiting on the lock. */
2701 for (p = struniq_hash_table[slot]; p != NULL; p = p->next)
2702 if (strcmp (p->contents, string) == 0)
2708 /* Really insert new_node into the hash table. Fill new_node entirely
2709 first, because other threads may be iterating over the linked list. */
2710 new_node->next = struniq_hash_table[slot];
2711 struniq_hash_table[slot] = new_node;
2713 /* Unlock after new_node is inserted. */
2714 if (mt) gl_lock_unlock (struniq_lock);
2716 return new_node->contents;
2722 #if LOCALENAME_ENHANCE_LOCALE_FUNCS
2724 /* The 'locale_t' object does not contain the names of the locale categories.
2725 We have to associate them with the object through a hash table.
2726 The hash table is defined in localename-table.[hc]. */
2728 /* Returns the name of a given locale category in a given locale_t object,
2729 allocated as a string with indefinite extent. */
2731 get_locale_t_name (int category, locale_t locale)
2733 if (locale == LC_GLOBAL_LOCALE)
2735 /* Query the global locale. */
2736 const char *name = setlocale_null (category);
2738 return struniq (name);
2740 /* Should normally not happen. */
2745 /* Look up the names in the hash table. */
2746 size_t hashcode = locale_hash_function (locale);
2747 size_t slot = hashcode % LOCALE_HASH_TABLE_SIZE;
2748 /* If the locale was not found in the table, return "". This can
2749 happen if the application uses the original newlocale()/duplocale()
2750 functions instead of the overridden ones. */
2751 const char *name = "";
2752 struct locale_hash_node *p;
2753 /* Lock while looking up the hash node. */
2754 gl_rwlock_rdlock (locale_lock);
2755 for (p = locale_hash_table[slot]; p != NULL; p = p->next)
2756 if (p->locale == locale)
2758 name = p->names.category_name[category];
2761 gl_rwlock_unlock (locale_lock);
2766 # if !(defined newlocale && defined duplocale && defined freelocale)
2767 # error "newlocale, duplocale, freelocale not being replaced as expected!"
2770 /* newlocale() override. */
2772 newlocale (int category_mask, const char *name, locale_t base)
2775 struct locale_categories_names names;
2776 struct locale_hash_node *node;
2779 /* Make sure name has indefinite extent. */
2780 if (((LC_CTYPE_MASK | LC_NUMERIC_MASK | LC_TIME_MASK | LC_COLLATE_MASK
2781 | LC_MONETARY_MASK | LC_MESSAGES_MASK)
2782 & category_mask) != 0)
2783 name = struniq (name);
2785 /* Determine the category names of the result. */
2786 if (((LC_CTYPE_MASK | LC_NUMERIC_MASK | LC_TIME_MASK | LC_COLLATE_MASK
2787 | LC_MONETARY_MASK | LC_MESSAGES_MASK)
2788 & ~category_mask) == 0)
2790 /* Use name, ignore base. */
2793 name = struniq (name);
2794 for (category = 0; category < 6; category++)
2795 names.category_name[category] = name;
2799 /* Use base, possibly also name. */
2804 for (category = 0; category < 6; category++)
2811 mask = LC_CTYPE_MASK;
2814 mask = LC_NUMERIC_MASK;
2817 mask = LC_TIME_MASK;
2820 mask = LC_COLLATE_MASK;
2823 mask = LC_MONETARY_MASK;
2826 mask = LC_MESSAGES_MASK;
2831 names.category_name[category] =
2832 ((mask & category_mask) != 0 ? name : "C");
2835 else if (base == LC_GLOBAL_LOCALE)
2839 for (category = 0; category < 6; category++)
2846 mask = LC_CTYPE_MASK;
2849 mask = LC_NUMERIC_MASK;
2852 mask = LC_TIME_MASK;
2855 mask = LC_COLLATE_MASK;
2858 mask = LC_MONETARY_MASK;
2861 mask = LC_MESSAGES_MASK;
2866 names.category_name[category] =
2867 ((mask & category_mask) != 0
2869 : get_locale_t_name (category, LC_GLOBAL_LOCALE));
2874 /* Look up the names of base in the hash table. Like multiple calls
2875 of get_locale_t_name, but locking only once. */
2876 struct locale_hash_node *p;
2879 /* Lock while looking up the hash node. */
2880 gl_rwlock_rdlock (locale_lock);
2881 for (p = locale_hash_table[locale_hash_function (base) % LOCALE_HASH_TABLE_SIZE];
2884 if (p->locale == base)
2887 for (category = 0; category < 6; category++)
2894 mask = LC_CTYPE_MASK;
2897 mask = LC_NUMERIC_MASK;
2900 mask = LC_TIME_MASK;
2903 mask = LC_COLLATE_MASK;
2906 mask = LC_MONETARY_MASK;
2909 mask = LC_MESSAGES_MASK;
2914 names.category_name[category] =
2915 ((mask & category_mask) != 0
2917 : (p != NULL ? p->names.category_name[category] : ""));
2920 gl_rwlock_unlock (locale_lock);
2924 node = (struct locale_hash_node *) malloc (sizeof (struct locale_hash_node));
2926 /* errno is set to ENOMEM. */
2929 result = newlocale (category_mask, name, base);
2936 /* Fill the hash node. */
2937 node->locale = result;
2938 node->names = names;
2940 /* Insert it in the hash table. */
2942 size_t hashcode = locale_hash_function (result);
2943 size_t slot = hashcode % LOCALE_HASH_TABLE_SIZE;
2944 struct locale_hash_node *p;
2946 /* Lock while inserting the new node. */
2947 gl_rwlock_wrlock (locale_lock);
2948 for (p = locale_hash_table[slot]; p != NULL; p = p->next)
2949 if (p->locale == result)
2951 /* This can happen if the application uses the original freelocale()
2952 function instead of the overridden one. */
2953 p->names = node->names;
2958 node->next = locale_hash_table[slot];
2959 locale_hash_table[slot] = node;
2962 gl_rwlock_unlock (locale_lock);
2971 /* duplocale() override. */
2973 duplocale (locale_t locale)
2976 struct locale_hash_node *node;
2980 /* Invalid argument. */
2983 node = (struct locale_hash_node *) malloc (sizeof (struct locale_hash_node));
2985 /* errno is set to ENOMEM. */
2988 result = duplocale (locale);
2995 /* Fill the hash node. */
2996 node->locale = result;
2997 if (locale == LC_GLOBAL_LOCALE)
3001 for (category = 0; category < 6; category++)
3002 node->names.category_name[category] =
3003 get_locale_t_name (category, LC_GLOBAL_LOCALE);
3005 /* Lock before inserting the new node. */
3006 gl_rwlock_wrlock (locale_lock);
3010 struct locale_hash_node *p;
3012 /* Lock once, for the lookup and the insertion. */
3013 gl_rwlock_wrlock (locale_lock);
3015 for (p = locale_hash_table[locale_hash_function (locale) % LOCALE_HASH_TABLE_SIZE];
3018 if (p->locale == locale)
3021 node->names = p->names;
3024 /* This can happen if the application uses the original
3025 newlocale()/duplocale() functions instead of the overridden
3029 for (category = 0; category < 6; category++)
3030 node->names.category_name[category] = "";
3034 /* Insert it in the hash table. */
3036 size_t hashcode = locale_hash_function (result);
3037 size_t slot = hashcode % LOCALE_HASH_TABLE_SIZE;
3038 struct locale_hash_node *p;
3040 for (p = locale_hash_table[slot]; p != NULL; p = p->next)
3041 if (p->locale == result)
3043 /* This can happen if the application uses the original freelocale()
3044 function instead of the overridden one. */
3045 p->names = node->names;
3050 node->next = locale_hash_table[slot];
3051 locale_hash_table[slot] = node;
3054 gl_rwlock_unlock (locale_lock);
3063 /* freelocale() override. */
3065 freelocale (locale_t locale)
3068 if (locale == NULL || locale == LC_GLOBAL_LOCALE)
3069 /* Invalid argument. */
3073 size_t hashcode = locale_hash_function (locale);
3074 size_t slot = hashcode % LOCALE_HASH_TABLE_SIZE;
3075 struct locale_hash_node *found;
3076 struct locale_hash_node **p;
3079 /* Lock while removing the hash node. */
3080 gl_rwlock_wrlock (locale_lock);
3081 for (p = &locale_hash_table[slot]; *p != NULL; p = &(*p)->next)
3082 if ((*p)->locale == locale)
3088 gl_rwlock_unlock (locale_lock);
3092 freelocale (locale);
3098 #if defined IN_LIBINTL || HAVE_GOOD_USELOCALE
3100 /* Like gl_locale_name_thread, except that the result is not in storage of
3101 indefinite extent. */
3102 # if !defined IN_LIBINTL
3106 gl_locale_name_thread_unsafe (int category, const char *categoryname _GL_UNUSED)
3108 # if HAVE_GOOD_USELOCALE
3110 locale_t thread_locale = uselocale (NULL);
3111 if (thread_locale != LC_GLOBAL_LOCALE)
3113 # if __GLIBC__ >= 2 && !defined __UCLIBC__
3114 /* Work around an incorrect definition of the _NL_LOCALE_NAME macro in
3116 See <https://sourceware.org/bugzilla/show_bug.cgi?id=10968>. */
3118 nl_langinfo (_NL_ITEM ((category), _NL_ITEM_INDEX (-1)));
3119 if (name[0] == '\0')
3120 /* Fallback code for glibc < 2.4, which did not implement
3121 nl_langinfo (_NL_LOCALE_NAME (category)). */
3122 name = thread_locale->__names[category];
3124 # elif defined __linux__ && HAVE_LANGINFO_H && defined NL_LOCALE_NAME
3126 return nl_langinfo_l (NL_LOCALE_NAME (category), thread_locale);
3127 # elif (defined __FreeBSD__ || defined __DragonFly__) || (defined __APPLE__ && defined __MACH__)
3128 /* FreeBSD, Mac OS X */
3134 mask = LC_CTYPE_MASK;
3137 mask = LC_NUMERIC_MASK;
3140 mask = LC_TIME_MASK;
3143 mask = LC_COLLATE_MASK;
3146 mask = LC_MONETARY_MASK;
3149 mask = LC_MESSAGES_MASK;
3151 default: /* We shouldn't get here. */
3154 return querylocale (mask, thread_locale);
3155 # elif defined __sun
3156 # if HAVE_GETLOCALENAME_L
3157 /* Solaris >= 12. */
3158 return getlocalename_l (category, thread_locale);
3159 # elif HAVE_SOLARIS114_LOCALES
3160 /* Solaris >= 11.4. */
3161 void *lcp = (*thread_locale)->core.data->lcp;
3171 return ((const char * const *) lcp)[category];
3172 default: /* We shouldn't get here. */
3175 # elif HAVE_NAMELESS_LOCALES
3176 return get_locale_t_name (category, thread_locale);
3178 /* Solaris 11 OpenIndiana.
3179 For the internal structure of locale objects, see
3180 https://github.com/OpenIndiana/illumos-gate/blob/master/usr/src/lib/libc/port/locale/localeimpl.h */
3189 return ((const char * const *) thread_locale)[category];
3190 default: /* We shouldn't get here. */
3194 # elif defined _AIX && HAVE_NAMELESS_LOCALES
3195 return get_locale_t_name (category, thread_locale);
3196 # elif defined __CYGWIN__
3197 /* Cygwin < 2.6 lacks uselocale and thread-local locales altogether.
3198 Cygwin <= 2.6.1 lacks NL_LOCALE_NAME, requiring peeking inside
3199 an opaque struct. */
3200 # ifdef NL_LOCALE_NAME
3201 return nl_langinfo_l (NL_LOCALE_NAME (category), thread_locale);
3203 /* FIXME: Remove when we can assume new-enough Cygwin. */
3205 char categories[7][32];
3207 return ((struct __locale_t *) thread_locale)->categories[category];
3209 # elif defined __ANDROID__
3210 return MB_CUR_MAX == 4 ? "C.UTF-8" : "C";
3221 gl_locale_name_thread (int category, const char *categoryname _GL_UNUSED)
3223 #if HAVE_GOOD_USELOCALE
3224 const char *name = gl_locale_name_thread_unsafe (category, categoryname);
3226 return struniq (name);
3228 /* On WINDOWS_NATIVE, don't use GetThreadLocale() here, because when
3229 SetThreadLocale has not been called - which is a very frequent case -
3230 the value of GetThreadLocale() ignores past calls to 'setlocale'. */
3234 /* XPG3 defines the result of 'setlocale (category, NULL)' as:
3235 "Directs 'setlocale()' to query 'category' and return the current
3236 setting of 'local'."
3237 However it does not specify the exact format. Neither do SUSV2 and
3238 ISO C 99. So we can use this feature only on selected systems (e.g.
3239 those using GNU C Library). */
3240 #if defined _LIBC || ((defined __GLIBC__ && __GLIBC__ >= 2) && !defined __UCLIBC__)
3241 # define HAVE_LOCALE_NULL
3245 gl_locale_name_posix (int category, const char *categoryname _GL_UNUSED)
3247 #if defined WINDOWS_NATIVE
3248 if (LC_MIN <= category && category <= LC_MAX)
3250 const char *locname =
3251 /* setlocale_null (category) is identical to setlocale (category, NULL)
3252 on this platform. */
3253 setlocale (category, NULL);
3255 /* Convert locale name to LCID. We don't want to use
3256 LocaleNameToLCID because (a) it is only available since Vista,
3257 and (b) it doesn't accept locale names returned by 'setlocale'. */
3258 LCID lcid = get_lcid (locname);
3261 return gl_locale_name_from_win32_LCID (lcid);
3265 const char *locname;
3267 /* Use the POSIX methods of looking to 'LC_ALL', 'LC_xxx', and 'LANG'.
3268 On some systems this can be done by the 'setlocale' function itself. */
3269 #if defined HAVE_LC_MESSAGES && defined HAVE_LOCALE_NULL
3270 locname = setlocale_null (category);
3272 /* On other systems we ignore what setlocale reports and instead look at the
3273 environment variables directly. This is necessary
3274 1. on systems which have a facility for customizing the default locale
3275 (Mac OS X, native Windows, Cygwin) and where the system's setlocale()
3276 function ignores this default locale (Mac OS X, Cygwin), in two cases:
3277 a. when the user missed to use the setlocale() override from libintl
3278 (for example by not including <libintl.h>),
3279 b. when setlocale supports only the "C" locale, such as on Cygwin
3280 1.5.x. In this case even the override from libintl cannot help.
3281 2. on all systems where setlocale supports only the "C" locale. */
3282 /* Strictly speaking, it is a POSIX violation to look at the environment
3283 variables regardless whether setlocale has been called or not. POSIX
3285 "For C-language programs, the POSIX locale shall be the
3286 default locale when the setlocale() function is not called."
3287 But we assume that all programs that use internationalized APIs call
3288 setlocale (LC_ALL, ""). */
3289 locname = gl_locale_name_environ (category, categoryname);
3291 /* Convert the locale name from the format returned by setlocale() or found
3292 in the environment variables to the XPG syntax. */
3293 #if defined WINDOWS_NATIVE
3294 if (locname != NULL)
3296 /* Convert locale name to LCID. We don't want to use
3297 LocaleNameToLCID because (a) it is only available since Vista,
3298 and (b) it doesn't accept locale names returned by 'setlocale'. */
3299 LCID lcid = get_lcid (locname);
3302 return gl_locale_name_from_win32_LCID (lcid);
3310 gl_locale_name_environ (int category _GL_UNUSED, const char *categoryname)
3314 /* Setting of LC_ALL overrides all other. */
3315 retval = getenv ("LC_ALL");
3316 if (retval != NULL && retval[0] != '\0')
3318 /* Next comes the name of the desired category. */
3319 retval = getenv (categoryname);
3320 if (retval != NULL && retval[0] != '\0')
3322 /* Last possibility is the LANG environment variable. */
3323 retval = getenv ("LANG");
3324 if (retval != NULL && retval[0] != '\0')
3326 #if HAVE_CFPREFERENCESCOPYAPPVALUE
3327 /* Mac OS X 10.2 or newer.
3328 Ignore invalid LANG value set by the Terminal application. */
3329 if (strcmp (retval, "UTF-8") != 0)
3331 #if defined __CYGWIN__
3333 Ignore dummy LANG value set by ~/.profile. */
3334 if (strcmp (retval, "C.UTF-8") != 0)
3343 gl_locale_name_default (void)
3346 "All implementations shall define a locale as the default locale, to be
3347 invoked when no environment variables are set, or set to the empty
3348 string. This default locale can be the POSIX locale or any other
3349 implementation-defined locale. Some implementations may provide
3350 facilities for local installation administrators to set the default
3351 locale, customizing it for each location. POSIX:2001 does not require
3354 The systems with such a facility are Mac OS X and Windows: They provide a
3355 GUI that allows the user to choose a locale.
3356 - On Mac OS X, by default, none of LC_* or LANG are set. Starting with
3357 Mac OS X 10.4 or 10.5, LANG is set for processes launched by the
3358 'Terminal' application (but sometimes to an incorrect value "UTF-8").
3359 When no environment variable is set, setlocale (LC_ALL, "") uses the
3361 - On native Windows, by default, none of LC_* or LANG are set.
3362 When no environment variable is set, setlocale (LC_ALL, "") uses the
3363 locale chosen by the user.
3364 - On Cygwin 1.5.x, by default, none of LC_* or LANG are set.
3365 When no environment variable is set, setlocale (LC_ALL, "") uses the
3367 - On Cygwin 1.7, by default, LANG is set to "C.UTF-8" when the default
3368 ~/.profile is executed.
3369 When no environment variable is set, setlocale (LC_ALL, "") uses the
3370 "C.UTF-8" locale, which operates in the same way as the "C" locale.
3373 #if !(HAVE_CFPREFERENCESCOPYAPPVALUE || defined WINDOWS_NATIVE || defined __CYGWIN__)
3375 /* The system does not have a way of setting the locale, other than the
3376 POSIX specified environment variables. We use C as default locale. */
3381 /* Return an XPG style locale name language[_territory][@modifier].
3382 Don't even bother determining the codeset; it's not useful in this
3383 context, because message catalogs are not specific to a single
3386 # if HAVE_CFPREFERENCESCOPYAPPVALUE
3387 /* Mac OS X 10.4 or newer */
3388 /* Don't use the API introduced in Mac OS X 10.5, CFLocaleCopyCurrent,
3389 because in macOS 10.13.4 it has the following behaviour:
3390 When two or more languages are specified in the
3391 "System Preferences > Language & Region > Preferred Languages" panel,
3392 it returns en_CC where CC is the territory (even when English is not among
3393 the preferred languages!). What we want instead is what
3394 CFLocaleCopyCurrent returned in earlier macOS releases and what
3395 CFPreferencesCopyAppValue still returns, namely ll_CC where ll is the
3396 first among the preferred languages and CC is the territory. */
3398 /* Cache the locale name, since CoreFoundation calls are expensive. */
3399 static const char *cached_localename;
3401 if (cached_localename == NULL)
3405 CFPreferencesCopyAppValue (CFSTR ("AppleLocale"),
3406 kCFPreferencesCurrentApplication);
3407 if (value != NULL && CFGetTypeID (value) == CFStringGetTypeID ())
3409 CFStringRef name = (CFStringRef)value;
3411 if (CFStringGetCString (name, namebuf, sizeof (namebuf),
3412 kCFStringEncodingASCII))
3414 gl_locale_name_canonicalize (namebuf);
3415 cached_localename = strdup (namebuf);
3418 if (cached_localename == NULL)
3419 cached_localename = "C";
3421 return cached_localename;
3426 # if defined WINDOWS_NATIVE || defined __CYGWIN__ /* Native Windows or Cygwin */
3430 /* Use native Windows API locale ID. */
3431 lcid = GetThreadLocale ();
3433 return gl_locale_name_from_win32_LCID (lcid);
3439 /* Determine the current locale's name, and canonicalize it into XPG syntax
3440 language[_territory][.codeset][@modifier]
3441 The codeset part in the result is not reliable; the locale_charset()
3442 should be used for codeset information instead.
3443 The result must not be freed; it is statically allocated. */
3446 gl_locale_name (int category, const char *categoryname)
3450 retval = gl_locale_name_thread (category, categoryname);
3454 retval = gl_locale_name_posix (category, categoryname);
3458 return gl_locale_name_default ();