1 /* Determine name of the currently selected locale.
2 Copyright (C) 1995-2020 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>. */
25 # include "gettextP.h"
27 # include "localename.h"
37 #include "flexmember.h"
38 #include "setlocale_null.h"
39 #include "thread-optim.h"
41 /* We cannot support uselocale() on platforms where the locale_t type is fake.
42 See intl-thread-locale.m4 for details. */
43 #if HAVE_WORKING_USELOCALE && !HAVE_FAKE_LOCALES
44 # define HAVE_GOOD_USELOCALE 1
47 #if HAVE_GOOD_USELOCALE
48 /* Mac OS X 10.5 defines the locale_t type in <xlocale.h>. */
49 # if defined __APPLE__ && defined __MACH__
52 # if (__GLIBC__ >= 2 && !defined __UCLIBC__) || (defined __linux__ && HAVE_LANGINFO_H) || defined __CYGWIN__
53 # include <langinfo.h>
55 # if !defined IN_LIBINTL
56 # include "glthread/lock.h"
59 # if HAVE_GETLOCALENAME_L
61 extern char * getlocalename_l(int, locale_t
);
62 # elif HAVE_SOLARIS114_LOCALES
63 # include <sys/localedef.h>
66 # if HAVE_NAMELESS_LOCALES
68 # include "localename-table.h"
72 #if HAVE_CFPREFERENCESCOPYAPPVALUE
73 # include <CoreFoundation/CFString.h>
74 # include <CoreFoundation/CFPreferences.h>
77 #if defined _WIN32 && !defined __CYGWIN__
78 # define WINDOWS_NATIVE
79 # if !defined IN_LIBINTL
80 # include "glthread/lock.h"
84 #if defined WINDOWS_NATIVE || defined __CYGWIN__ /* Native Windows or Cygwin */
85 # define WIN32_LEAN_AND_MEAN
88 /* List of language codes, sorted by value:
114 0x1a LANG_CROATIAN == LANG_SERBIAN
196 0x6e LANG_LUXEMBOURGISH
197 0x6f LANG_GREENLANDIC
216 0x87 LANG_KINYARWANDA
219 0x91 LANG_SCOTTISH_GAELIC
221 /* Mingw headers don't have latest language and sublanguage codes. */
222 # ifndef LANG_AFRIKAANS
223 # define LANG_AFRIKAANS 0x36
225 # ifndef LANG_ALBANIAN
226 # define LANG_ALBANIAN 0x1c
228 # ifndef LANG_ALSATIAN
229 # define LANG_ALSATIAN 0x84
231 # ifndef LANG_AMHARIC
232 # define LANG_AMHARIC 0x5e
235 # define LANG_ARABIC 0x01
237 # ifndef LANG_ARMENIAN
238 # define LANG_ARMENIAN 0x2b
240 # ifndef LANG_ASSAMESE
241 # define LANG_ASSAMESE 0x4d
244 # define LANG_AZERI 0x2c
246 # ifndef LANG_BASHKIR
247 # define LANG_BASHKIR 0x6d
250 # define LANG_BASQUE 0x2d
252 # ifndef LANG_BELARUSIAN
253 # define LANG_BELARUSIAN 0x23
255 # ifndef LANG_BENGALI
256 # define LANG_BENGALI 0x45
259 # define LANG_BRETON 0x7e
261 # ifndef LANG_BURMESE
262 # define LANG_BURMESE 0x55
264 # ifndef LANG_CAMBODIAN
265 # define LANG_CAMBODIAN 0x53
267 # ifndef LANG_CATALAN
268 # define LANG_CATALAN 0x03
270 # ifndef LANG_CHEROKEE
271 # define LANG_CHEROKEE 0x5c
273 # ifndef LANG_CORSICAN
274 # define LANG_CORSICAN 0x83
277 # define LANG_DARI 0x8c
280 # define LANG_DIVEHI 0x65
283 # define LANG_EDO 0x66
285 # ifndef LANG_ESTONIAN
286 # define LANG_ESTONIAN 0x25
288 # ifndef LANG_FAEROESE
289 # define LANG_FAEROESE 0x38
292 # define LANG_FARSI 0x29
294 # ifndef LANG_FRISIAN
295 # define LANG_FRISIAN 0x62
297 # ifndef LANG_FULFULDE
298 # define LANG_FULFULDE 0x67
301 # define LANG_GAELIC 0x3c
303 # ifndef LANG_GALICIAN
304 # define LANG_GALICIAN 0x56
306 # ifndef LANG_GEORGIAN
307 # define LANG_GEORGIAN 0x37
309 # ifndef LANG_GREENLANDIC
310 # define LANG_GREENLANDIC 0x6f
312 # ifndef LANG_GUARANI
313 # define LANG_GUARANI 0x74
315 # ifndef LANG_GUJARATI
316 # define LANG_GUJARATI 0x47
319 # define LANG_HAUSA 0x68
321 # ifndef LANG_HAWAIIAN
322 # define LANG_HAWAIIAN 0x75
325 # define LANG_HEBREW 0x0d
328 # define LANG_HINDI 0x39
331 # define LANG_IBIBIO 0x69
334 # define LANG_IGBO 0x70
336 # ifndef LANG_INDONESIAN
337 # define LANG_INDONESIAN 0x21
339 # ifndef LANG_INUKTITUT
340 # define LANG_INUKTITUT 0x5d
342 # ifndef LANG_KANNADA
343 # define LANG_KANNADA 0x4b
346 # define LANG_KANURI 0x71
348 # ifndef LANG_KASHMIRI
349 # define LANG_KASHMIRI 0x60
352 # define LANG_KAZAK 0x3f
355 # define LANG_KICHE 0x86
357 # ifndef LANG_KINYARWANDA
358 # define LANG_KINYARWANDA 0x87
360 # ifndef LANG_KONKANI
361 # define LANG_KONKANI 0x57
364 # define LANG_KYRGYZ 0x40
367 # define LANG_LAO 0x54
370 # define LANG_LATIN 0x76
372 # ifndef LANG_LATVIAN
373 # define LANG_LATVIAN 0x26
375 # ifndef LANG_LITHUANIAN
376 # define LANG_LITHUANIAN 0x27
378 # ifndef LANG_LUXEMBOURGISH
379 # define LANG_LUXEMBOURGISH 0x6e
381 # ifndef LANG_MACEDONIAN
382 # define LANG_MACEDONIAN 0x2f
385 # define LANG_MALAY 0x3e
387 # ifndef LANG_MALAYALAM
388 # define LANG_MALAYALAM 0x4c
390 # ifndef LANG_MALTESE
391 # define LANG_MALTESE 0x3a
393 # ifndef LANG_MANIPURI
394 # define LANG_MANIPURI 0x58
397 # define LANG_MAORI 0x81
399 # ifndef LANG_MAPUDUNGUN
400 # define LANG_MAPUDUNGUN 0x7a
402 # ifndef LANG_MARATHI
403 # define LANG_MARATHI 0x4e
406 # define LANG_MOHAWK 0x7c
408 # ifndef LANG_MONGOLIAN
409 # define LANG_MONGOLIAN 0x50
412 # define LANG_NEPALI 0x61
414 # ifndef LANG_OCCITAN
415 # define LANG_OCCITAN 0x82
418 # define LANG_ORIYA 0x48
421 # define LANG_OROMO 0x72
423 # ifndef LANG_PAPIAMENTU
424 # define LANG_PAPIAMENTU 0x79
427 # define LANG_PASHTO 0x63
429 # ifndef LANG_PUNJABI
430 # define LANG_PUNJABI 0x46
432 # ifndef LANG_QUECHUA
433 # define LANG_QUECHUA 0x6b
435 # ifndef LANG_ROMANSH
436 # define LANG_ROMANSH 0x17
439 # define LANG_SAMI 0x3b
441 # ifndef LANG_SANSKRIT
442 # define LANG_SANSKRIT 0x4f
444 # ifndef LANG_SCOTTISH_GAELIC
445 # define LANG_SCOTTISH_GAELIC 0x91
447 # ifndef LANG_SERBIAN
448 # define LANG_SERBIAN 0x1a
451 # define LANG_SINDHI 0x59
453 # ifndef LANG_SINHALESE
454 # define LANG_SINHALESE 0x5b
457 # define LANG_SLOVAK 0x1b
460 # define LANG_SOMALI 0x77
462 # ifndef LANG_SORBIAN
463 # define LANG_SORBIAN 0x2e
466 # define LANG_SOTHO 0x6c
469 # define LANG_SUTU 0x30
471 # ifndef LANG_SWAHILI
472 # define LANG_SWAHILI 0x41
475 # define LANG_SYRIAC 0x5a
477 # ifndef LANG_TAGALOG
478 # define LANG_TAGALOG 0x64
481 # define LANG_TAJIK 0x28
483 # ifndef LANG_TAMAZIGHT
484 # define LANG_TAMAZIGHT 0x5f
487 # define LANG_TAMIL 0x49
490 # define LANG_TATAR 0x44
493 # define LANG_TELUGU 0x4a
496 # define LANG_THAI 0x1e
498 # ifndef LANG_TIBETAN
499 # define LANG_TIBETAN 0x51
501 # ifndef LANG_TIGRINYA
502 # define LANG_TIGRINYA 0x73
505 # define LANG_TSONGA 0x31
508 # define LANG_TSWANA 0x32
510 # ifndef LANG_TURKMEN
511 # define LANG_TURKMEN 0x42
514 # define LANG_UIGHUR 0x80
516 # ifndef LANG_UKRAINIAN
517 # define LANG_UKRAINIAN 0x22
520 # define LANG_URDU 0x20
523 # define LANG_UZBEK 0x43
526 # define LANG_VENDA 0x33
528 # ifndef LANG_VIETNAMESE
529 # define LANG_VIETNAMESE 0x2a
532 # define LANG_WELSH 0x52
535 # define LANG_WOLOF 0x88
538 # define LANG_XHOSA 0x34
541 # define LANG_YAKUT 0x85
544 # define LANG_YI 0x78
546 # ifndef LANG_YIDDISH
547 # define LANG_YIDDISH 0x3d
550 # define LANG_YORUBA 0x6a
553 # define LANG_ZULU 0x35
555 # ifndef SUBLANG_AFRIKAANS_SOUTH_AFRICA
556 # define SUBLANG_AFRIKAANS_SOUTH_AFRICA 0x01
558 # ifndef SUBLANG_ALBANIAN_ALBANIA
559 # define SUBLANG_ALBANIAN_ALBANIA 0x01
561 # ifndef SUBLANG_ALSATIAN_FRANCE
562 # define SUBLANG_ALSATIAN_FRANCE 0x01
564 # ifndef SUBLANG_AMHARIC_ETHIOPIA
565 # define SUBLANG_AMHARIC_ETHIOPIA 0x01
567 # ifndef SUBLANG_ARABIC_SAUDI_ARABIA
568 # define SUBLANG_ARABIC_SAUDI_ARABIA 0x01
570 # ifndef SUBLANG_ARABIC_IRAQ
571 # define SUBLANG_ARABIC_IRAQ 0x02
573 # ifndef SUBLANG_ARABIC_EGYPT
574 # define SUBLANG_ARABIC_EGYPT 0x03
576 # ifndef SUBLANG_ARABIC_LIBYA
577 # define SUBLANG_ARABIC_LIBYA 0x04
579 # ifndef SUBLANG_ARABIC_ALGERIA
580 # define SUBLANG_ARABIC_ALGERIA 0x05
582 # ifndef SUBLANG_ARABIC_MOROCCO
583 # define SUBLANG_ARABIC_MOROCCO 0x06
585 # ifndef SUBLANG_ARABIC_TUNISIA
586 # define SUBLANG_ARABIC_TUNISIA 0x07
588 # ifndef SUBLANG_ARABIC_OMAN
589 # define SUBLANG_ARABIC_OMAN 0x08
591 # ifndef SUBLANG_ARABIC_YEMEN
592 # define SUBLANG_ARABIC_YEMEN 0x09
594 # ifndef SUBLANG_ARABIC_SYRIA
595 # define SUBLANG_ARABIC_SYRIA 0x0a
597 # ifndef SUBLANG_ARABIC_JORDAN
598 # define SUBLANG_ARABIC_JORDAN 0x0b
600 # ifndef SUBLANG_ARABIC_LEBANON
601 # define SUBLANG_ARABIC_LEBANON 0x0c
603 # ifndef SUBLANG_ARABIC_KUWAIT
604 # define SUBLANG_ARABIC_KUWAIT 0x0d
606 # ifndef SUBLANG_ARABIC_UAE
607 # define SUBLANG_ARABIC_UAE 0x0e
609 # ifndef SUBLANG_ARABIC_BAHRAIN
610 # define SUBLANG_ARABIC_BAHRAIN 0x0f
612 # ifndef SUBLANG_ARABIC_QATAR
613 # define SUBLANG_ARABIC_QATAR 0x10
615 # ifndef SUBLANG_ARMENIAN_ARMENIA
616 # define SUBLANG_ARMENIAN_ARMENIA 0x01
618 # ifndef SUBLANG_ASSAMESE_INDIA
619 # define SUBLANG_ASSAMESE_INDIA 0x01
621 # ifndef SUBLANG_AZERI_LATIN
622 # define SUBLANG_AZERI_LATIN 0x01
624 # ifndef SUBLANG_AZERI_CYRILLIC
625 # define SUBLANG_AZERI_CYRILLIC 0x02
627 # ifndef SUBLANG_BASHKIR_RUSSIA
628 # define SUBLANG_BASHKIR_RUSSIA 0x01
630 # ifndef SUBLANG_BASQUE_BASQUE
631 # define SUBLANG_BASQUE_BASQUE 0x01
633 # ifndef SUBLANG_BELARUSIAN_BELARUS
634 # define SUBLANG_BELARUSIAN_BELARUS 0x01
636 # ifndef SUBLANG_BENGALI_INDIA
637 # define SUBLANG_BENGALI_INDIA 0x01
639 # ifndef SUBLANG_BENGALI_BANGLADESH
640 # define SUBLANG_BENGALI_BANGLADESH 0x02
642 # ifndef SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN
643 # define SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN 0x05
645 # ifndef SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC
646 # define SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC 0x08
648 # ifndef SUBLANG_BRETON_FRANCE
649 # define SUBLANG_BRETON_FRANCE 0x01
651 # ifndef SUBLANG_BULGARIAN_BULGARIA
652 # define SUBLANG_BULGARIAN_BULGARIA 0x01
654 # ifndef SUBLANG_CAMBODIAN_CAMBODIA
655 # define SUBLANG_CAMBODIAN_CAMBODIA 0x01
657 # ifndef SUBLANG_CATALAN_SPAIN
658 # define SUBLANG_CATALAN_SPAIN 0x01
660 # ifndef SUBLANG_CORSICAN_FRANCE
661 # define SUBLANG_CORSICAN_FRANCE 0x01
663 # ifndef SUBLANG_CROATIAN_CROATIA
664 # define SUBLANG_CROATIAN_CROATIA 0x01
666 # ifndef SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN
667 # define SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN 0x04
669 # ifndef SUBLANG_CHINESE_MACAU
670 # define SUBLANG_CHINESE_MACAU 0x05
672 # ifndef SUBLANG_CZECH_CZECH_REPUBLIC
673 # define SUBLANG_CZECH_CZECH_REPUBLIC 0x01
675 # ifndef SUBLANG_DANISH_DENMARK
676 # define SUBLANG_DANISH_DENMARK 0x01
678 # ifndef SUBLANG_DARI_AFGHANISTAN
679 # define SUBLANG_DARI_AFGHANISTAN 0x01
681 # ifndef SUBLANG_DIVEHI_MALDIVES
682 # define SUBLANG_DIVEHI_MALDIVES 0x01
684 # ifndef SUBLANG_DUTCH_SURINAM
685 # define SUBLANG_DUTCH_SURINAM 0x03
687 # ifndef SUBLANG_ENGLISH_SOUTH_AFRICA
688 # define SUBLANG_ENGLISH_SOUTH_AFRICA 0x07
690 # ifndef SUBLANG_ENGLISH_JAMAICA
691 # define SUBLANG_ENGLISH_JAMAICA 0x08
693 # ifndef SUBLANG_ENGLISH_CARIBBEAN
694 # define SUBLANG_ENGLISH_CARIBBEAN 0x09
696 # ifndef SUBLANG_ENGLISH_BELIZE
697 # define SUBLANG_ENGLISH_BELIZE 0x0a
699 # ifndef SUBLANG_ENGLISH_TRINIDAD
700 # define SUBLANG_ENGLISH_TRINIDAD 0x0b
702 # ifndef SUBLANG_ENGLISH_ZIMBABWE
703 # define SUBLANG_ENGLISH_ZIMBABWE 0x0c
705 # ifndef SUBLANG_ENGLISH_PHILIPPINES
706 # define SUBLANG_ENGLISH_PHILIPPINES 0x0d
708 # ifndef SUBLANG_ENGLISH_INDONESIA
709 # define SUBLANG_ENGLISH_INDONESIA 0x0e
711 # ifndef SUBLANG_ENGLISH_HONGKONG
712 # define SUBLANG_ENGLISH_HONGKONG 0x0f
714 # ifndef SUBLANG_ENGLISH_INDIA
715 # define SUBLANG_ENGLISH_INDIA 0x10
717 # ifndef SUBLANG_ENGLISH_MALAYSIA
718 # define SUBLANG_ENGLISH_MALAYSIA 0x11
720 # ifndef SUBLANG_ENGLISH_SINGAPORE
721 # define SUBLANG_ENGLISH_SINGAPORE 0x12
723 # ifndef SUBLANG_ESTONIAN_ESTONIA
724 # define SUBLANG_ESTONIAN_ESTONIA 0x01
726 # ifndef SUBLANG_FAEROESE_FAROE_ISLANDS
727 # define SUBLANG_FAEROESE_FAROE_ISLANDS 0x01
729 # ifndef SUBLANG_FARSI_IRAN
730 # define SUBLANG_FARSI_IRAN 0x01
732 # ifndef SUBLANG_FINNISH_FINLAND
733 # define SUBLANG_FINNISH_FINLAND 0x01
735 # ifndef SUBLANG_FRENCH_LUXEMBOURG
736 # define SUBLANG_FRENCH_LUXEMBOURG 0x05
738 # ifndef SUBLANG_FRENCH_MONACO
739 # define SUBLANG_FRENCH_MONACO 0x06
741 # ifndef SUBLANG_FRENCH_WESTINDIES
742 # define SUBLANG_FRENCH_WESTINDIES 0x07
744 # ifndef SUBLANG_FRENCH_REUNION
745 # define SUBLANG_FRENCH_REUNION 0x08
747 # ifndef SUBLANG_FRENCH_CONGO
748 # define SUBLANG_FRENCH_CONGO 0x09
750 # ifndef SUBLANG_FRENCH_SENEGAL
751 # define SUBLANG_FRENCH_SENEGAL 0x0a
753 # ifndef SUBLANG_FRENCH_CAMEROON
754 # define SUBLANG_FRENCH_CAMEROON 0x0b
756 # ifndef SUBLANG_FRENCH_COTEDIVOIRE
757 # define SUBLANG_FRENCH_COTEDIVOIRE 0x0c
759 # ifndef SUBLANG_FRENCH_MALI
760 # define SUBLANG_FRENCH_MALI 0x0d
762 # ifndef SUBLANG_FRENCH_MOROCCO
763 # define SUBLANG_FRENCH_MOROCCO 0x0e
765 # ifndef SUBLANG_FRENCH_HAITI
766 # define SUBLANG_FRENCH_HAITI 0x0f
768 # ifndef SUBLANG_FRISIAN_NETHERLANDS
769 # define SUBLANG_FRISIAN_NETHERLANDS 0x01
771 # ifndef SUBLANG_GALICIAN_SPAIN
772 # define SUBLANG_GALICIAN_SPAIN 0x01
774 # ifndef SUBLANG_GEORGIAN_GEORGIA
775 # define SUBLANG_GEORGIAN_GEORGIA 0x01
777 # ifndef SUBLANG_GERMAN_LUXEMBOURG
778 # define SUBLANG_GERMAN_LUXEMBOURG 0x04
780 # ifndef SUBLANG_GERMAN_LIECHTENSTEIN
781 # define SUBLANG_GERMAN_LIECHTENSTEIN 0x05
783 # ifndef SUBLANG_GREEK_GREECE
784 # define SUBLANG_GREEK_GREECE 0x01
786 # ifndef SUBLANG_GREENLANDIC_GREENLAND
787 # define SUBLANG_GREENLANDIC_GREENLAND 0x01
789 # ifndef SUBLANG_GUJARATI_INDIA
790 # define SUBLANG_GUJARATI_INDIA 0x01
792 # ifndef SUBLANG_HAUSA_NIGERIA_LATIN
793 # define SUBLANG_HAUSA_NIGERIA_LATIN 0x01
795 # ifndef SUBLANG_HEBREW_ISRAEL
796 # define SUBLANG_HEBREW_ISRAEL 0x01
798 # ifndef SUBLANG_HINDI_INDIA
799 # define SUBLANG_HINDI_INDIA 0x01
801 # ifndef SUBLANG_HUNGARIAN_HUNGARY
802 # define SUBLANG_HUNGARIAN_HUNGARY 0x01
804 # ifndef SUBLANG_ICELANDIC_ICELAND
805 # define SUBLANG_ICELANDIC_ICELAND 0x01
807 # ifndef SUBLANG_IGBO_NIGERIA
808 # define SUBLANG_IGBO_NIGERIA 0x01
810 # ifndef SUBLANG_INDONESIAN_INDONESIA
811 # define SUBLANG_INDONESIAN_INDONESIA 0x01
813 # ifndef SUBLANG_INUKTITUT_CANADA
814 # define SUBLANG_INUKTITUT_CANADA 0x01
816 # undef SUBLANG_INUKTITUT_CANADA_LATIN
817 # define SUBLANG_INUKTITUT_CANADA_LATIN 0x02
818 # undef SUBLANG_IRISH_IRELAND
819 # define SUBLANG_IRISH_IRELAND 0x02
820 # ifndef SUBLANG_JAPANESE_JAPAN
821 # define SUBLANG_JAPANESE_JAPAN 0x01
823 # ifndef SUBLANG_KANNADA_INDIA
824 # define SUBLANG_KANNADA_INDIA 0x01
826 # ifndef SUBLANG_KASHMIRI_INDIA
827 # define SUBLANG_KASHMIRI_INDIA 0x02
829 # ifndef SUBLANG_KAZAK_KAZAKHSTAN
830 # define SUBLANG_KAZAK_KAZAKHSTAN 0x01
832 # ifndef SUBLANG_KICHE_GUATEMALA
833 # define SUBLANG_KICHE_GUATEMALA 0x01
835 # ifndef SUBLANG_KINYARWANDA_RWANDA
836 # define SUBLANG_KINYARWANDA_RWANDA 0x01
838 # ifndef SUBLANG_KONKANI_INDIA
839 # define SUBLANG_KONKANI_INDIA 0x01
841 # ifndef SUBLANG_KYRGYZ_KYRGYZSTAN
842 # define SUBLANG_KYRGYZ_KYRGYZSTAN 0x01
844 # ifndef SUBLANG_LAO_LAOS
845 # define SUBLANG_LAO_LAOS 0x01
847 # ifndef SUBLANG_LATVIAN_LATVIA
848 # define SUBLANG_LATVIAN_LATVIA 0x01
850 # ifndef SUBLANG_LITHUANIAN_LITHUANIA
851 # define SUBLANG_LITHUANIAN_LITHUANIA 0x01
853 # undef SUBLANG_LOWER_SORBIAN_GERMANY
854 # define SUBLANG_LOWER_SORBIAN_GERMANY 0x02
855 # ifndef SUBLANG_LUXEMBOURGISH_LUXEMBOURG
856 # define SUBLANG_LUXEMBOURGISH_LUXEMBOURG 0x01
858 # ifndef SUBLANG_MACEDONIAN_MACEDONIA
859 # define SUBLANG_MACEDONIAN_MACEDONIA 0x01
861 # ifndef SUBLANG_MALAY_MALAYSIA
862 # define SUBLANG_MALAY_MALAYSIA 0x01
864 # ifndef SUBLANG_MALAY_BRUNEI_DARUSSALAM
865 # define SUBLANG_MALAY_BRUNEI_DARUSSALAM 0x02
867 # ifndef SUBLANG_MALAYALAM_INDIA
868 # define SUBLANG_MALAYALAM_INDIA 0x01
870 # ifndef SUBLANG_MALTESE_MALTA
871 # define SUBLANG_MALTESE_MALTA 0x01
873 # ifndef SUBLANG_MAORI_NEW_ZEALAND
874 # define SUBLANG_MAORI_NEW_ZEALAND 0x01
876 # ifndef SUBLANG_MAPUDUNGUN_CHILE
877 # define SUBLANG_MAPUDUNGUN_CHILE 0x01
879 # ifndef SUBLANG_MARATHI_INDIA
880 # define SUBLANG_MARATHI_INDIA 0x01
882 # ifndef SUBLANG_MOHAWK_CANADA
883 # define SUBLANG_MOHAWK_CANADA 0x01
885 # ifndef SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA
886 # define SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA 0x01
888 # ifndef SUBLANG_MONGOLIAN_PRC
889 # define SUBLANG_MONGOLIAN_PRC 0x02
891 # ifndef SUBLANG_NEPALI_NEPAL
892 # define SUBLANG_NEPALI_NEPAL 0x01
894 # ifndef SUBLANG_NEPALI_INDIA
895 # define SUBLANG_NEPALI_INDIA 0x02
897 # ifndef SUBLANG_OCCITAN_FRANCE
898 # define SUBLANG_OCCITAN_FRANCE 0x01
900 # ifndef SUBLANG_ORIYA_INDIA
901 # define SUBLANG_ORIYA_INDIA 0x01
903 # ifndef SUBLANG_PASHTO_AFGHANISTAN
904 # define SUBLANG_PASHTO_AFGHANISTAN 0x01
906 # ifndef SUBLANG_POLISH_POLAND
907 # define SUBLANG_POLISH_POLAND 0x01
909 # ifndef SUBLANG_PUNJABI_INDIA
910 # define SUBLANG_PUNJABI_INDIA 0x01
912 # ifndef SUBLANG_PUNJABI_PAKISTAN
913 # define SUBLANG_PUNJABI_PAKISTAN 0x02
915 # ifndef SUBLANG_QUECHUA_BOLIVIA
916 # define SUBLANG_QUECHUA_BOLIVIA 0x01
918 # ifndef SUBLANG_QUECHUA_ECUADOR
919 # define SUBLANG_QUECHUA_ECUADOR 0x02
921 # ifndef SUBLANG_QUECHUA_PERU
922 # define SUBLANG_QUECHUA_PERU 0x03
924 # ifndef SUBLANG_ROMANIAN_ROMANIA
925 # define SUBLANG_ROMANIAN_ROMANIA 0x01
927 # ifndef SUBLANG_ROMANIAN_MOLDOVA
928 # define SUBLANG_ROMANIAN_MOLDOVA 0x02
930 # ifndef SUBLANG_ROMANSH_SWITZERLAND
931 # define SUBLANG_ROMANSH_SWITZERLAND 0x01
933 # ifndef SUBLANG_RUSSIAN_RUSSIA
934 # define SUBLANG_RUSSIAN_RUSSIA 0x01
936 # ifndef SUBLANG_RUSSIAN_MOLDAVIA
937 # define SUBLANG_RUSSIAN_MOLDAVIA 0x02
939 # ifndef SUBLANG_SAMI_NORTHERN_NORWAY
940 # define SUBLANG_SAMI_NORTHERN_NORWAY 0x01
942 # ifndef SUBLANG_SAMI_NORTHERN_SWEDEN
943 # define SUBLANG_SAMI_NORTHERN_SWEDEN 0x02
945 # ifndef SUBLANG_SAMI_NORTHERN_FINLAND
946 # define SUBLANG_SAMI_NORTHERN_FINLAND 0x03
948 # ifndef SUBLANG_SAMI_LULE_NORWAY
949 # define SUBLANG_SAMI_LULE_NORWAY 0x04
951 # ifndef SUBLANG_SAMI_LULE_SWEDEN
952 # define SUBLANG_SAMI_LULE_SWEDEN 0x05
954 # ifndef SUBLANG_SAMI_SOUTHERN_NORWAY
955 # define SUBLANG_SAMI_SOUTHERN_NORWAY 0x06
957 # ifndef SUBLANG_SAMI_SOUTHERN_SWEDEN
958 # define SUBLANG_SAMI_SOUTHERN_SWEDEN 0x07
960 # undef SUBLANG_SAMI_SKOLT_FINLAND
961 # define SUBLANG_SAMI_SKOLT_FINLAND 0x08
962 # undef SUBLANG_SAMI_INARI_FINLAND
963 # define SUBLANG_SAMI_INARI_FINLAND 0x09
964 # ifndef SUBLANG_SANSKRIT_INDIA
965 # define SUBLANG_SANSKRIT_INDIA 0x01
967 # ifndef SUBLANG_SERBIAN_LATIN
968 # define SUBLANG_SERBIAN_LATIN 0x02
970 # ifndef SUBLANG_SERBIAN_CYRILLIC
971 # define SUBLANG_SERBIAN_CYRILLIC 0x03
973 # ifndef SUBLANG_SINDHI_INDIA
974 # define SUBLANG_SINDHI_INDIA 0x01
976 # undef SUBLANG_SINDHI_PAKISTAN
977 # define SUBLANG_SINDHI_PAKISTAN 0x02
978 # ifndef SUBLANG_SINDHI_AFGHANISTAN
979 # define SUBLANG_SINDHI_AFGHANISTAN 0x02
981 # ifndef SUBLANG_SINHALESE_SRI_LANKA
982 # define SUBLANG_SINHALESE_SRI_LANKA 0x01
984 # ifndef SUBLANG_SLOVAK_SLOVAKIA
985 # define SUBLANG_SLOVAK_SLOVAKIA 0x01
987 # ifndef SUBLANG_SLOVENIAN_SLOVENIA
988 # define SUBLANG_SLOVENIAN_SLOVENIA 0x01
990 # ifndef SUBLANG_SOTHO_SOUTH_AFRICA
991 # define SUBLANG_SOTHO_SOUTH_AFRICA 0x01
993 # ifndef SUBLANG_SPANISH_GUATEMALA
994 # define SUBLANG_SPANISH_GUATEMALA 0x04
996 # ifndef SUBLANG_SPANISH_COSTA_RICA
997 # define SUBLANG_SPANISH_COSTA_RICA 0x05
999 # ifndef SUBLANG_SPANISH_PANAMA
1000 # define SUBLANG_SPANISH_PANAMA 0x06
1002 # ifndef SUBLANG_SPANISH_DOMINICAN_REPUBLIC
1003 # define SUBLANG_SPANISH_DOMINICAN_REPUBLIC 0x07
1005 # ifndef SUBLANG_SPANISH_VENEZUELA
1006 # define SUBLANG_SPANISH_VENEZUELA 0x08
1008 # ifndef SUBLANG_SPANISH_COLOMBIA
1009 # define SUBLANG_SPANISH_COLOMBIA 0x09
1011 # ifndef SUBLANG_SPANISH_PERU
1012 # define SUBLANG_SPANISH_PERU 0x0a
1014 # ifndef SUBLANG_SPANISH_ARGENTINA
1015 # define SUBLANG_SPANISH_ARGENTINA 0x0b
1017 # ifndef SUBLANG_SPANISH_ECUADOR
1018 # define SUBLANG_SPANISH_ECUADOR 0x0c
1020 # ifndef SUBLANG_SPANISH_CHILE
1021 # define SUBLANG_SPANISH_CHILE 0x0d
1023 # ifndef SUBLANG_SPANISH_URUGUAY
1024 # define SUBLANG_SPANISH_URUGUAY 0x0e
1026 # ifndef SUBLANG_SPANISH_PARAGUAY
1027 # define SUBLANG_SPANISH_PARAGUAY 0x0f
1029 # ifndef SUBLANG_SPANISH_BOLIVIA
1030 # define SUBLANG_SPANISH_BOLIVIA 0x10
1032 # ifndef SUBLANG_SPANISH_EL_SALVADOR
1033 # define SUBLANG_SPANISH_EL_SALVADOR 0x11
1035 # ifndef SUBLANG_SPANISH_HONDURAS
1036 # define SUBLANG_SPANISH_HONDURAS 0x12
1038 # ifndef SUBLANG_SPANISH_NICARAGUA
1039 # define SUBLANG_SPANISH_NICARAGUA 0x13
1041 # ifndef SUBLANG_SPANISH_PUERTO_RICO
1042 # define SUBLANG_SPANISH_PUERTO_RICO 0x14
1044 # ifndef SUBLANG_SPANISH_US
1045 # define SUBLANG_SPANISH_US 0x15
1047 # ifndef SUBLANG_SWAHILI_KENYA
1048 # define SUBLANG_SWAHILI_KENYA 0x01
1050 # ifndef SUBLANG_SWEDISH_SWEDEN
1051 # define SUBLANG_SWEDISH_SWEDEN 0x01
1053 # ifndef SUBLANG_SWEDISH_FINLAND
1054 # define SUBLANG_SWEDISH_FINLAND 0x02
1056 # ifndef SUBLANG_SYRIAC_SYRIA
1057 # define SUBLANG_SYRIAC_SYRIA 0x01
1059 # ifndef SUBLANG_TAGALOG_PHILIPPINES
1060 # define SUBLANG_TAGALOG_PHILIPPINES 0x01
1062 # ifndef SUBLANG_TAJIK_TAJIKISTAN
1063 # define SUBLANG_TAJIK_TAJIKISTAN 0x01
1065 # ifndef SUBLANG_TAMAZIGHT_ARABIC
1066 # define SUBLANG_TAMAZIGHT_ARABIC 0x01
1068 # ifndef SUBLANG_TAMAZIGHT_ALGERIA_LATIN
1069 # define SUBLANG_TAMAZIGHT_ALGERIA_LATIN 0x02
1071 # ifndef SUBLANG_TAMIL_INDIA
1072 # define SUBLANG_TAMIL_INDIA 0x01
1074 # ifndef SUBLANG_TATAR_RUSSIA
1075 # define SUBLANG_TATAR_RUSSIA 0x01
1077 # ifndef SUBLANG_TELUGU_INDIA
1078 # define SUBLANG_TELUGU_INDIA 0x01
1080 # ifndef SUBLANG_THAI_THAILAND
1081 # define SUBLANG_THAI_THAILAND 0x01
1083 # ifndef SUBLANG_TIBETAN_PRC
1084 # define SUBLANG_TIBETAN_PRC 0x01
1086 # undef SUBLANG_TIBETAN_BHUTAN
1087 # define SUBLANG_TIBETAN_BHUTAN 0x02
1088 # ifndef SUBLANG_TIGRINYA_ETHIOPIA
1089 # define SUBLANG_TIGRINYA_ETHIOPIA 0x01
1091 # ifndef SUBLANG_TIGRINYA_ERITREA
1092 # define SUBLANG_TIGRINYA_ERITREA 0x02
1094 # ifndef SUBLANG_TSWANA_SOUTH_AFRICA
1095 # define SUBLANG_TSWANA_SOUTH_AFRICA 0x01
1097 # ifndef SUBLANG_TURKISH_TURKEY
1098 # define SUBLANG_TURKISH_TURKEY 0x01
1100 # ifndef SUBLANG_TURKMEN_TURKMENISTAN
1101 # define SUBLANG_TURKMEN_TURKMENISTAN 0x01
1103 # ifndef SUBLANG_UIGHUR_PRC
1104 # define SUBLANG_UIGHUR_PRC 0x01
1106 # ifndef SUBLANG_UKRAINIAN_UKRAINE
1107 # define SUBLANG_UKRAINIAN_UKRAINE 0x01
1109 # ifndef SUBLANG_UPPER_SORBIAN_GERMANY
1110 # define SUBLANG_UPPER_SORBIAN_GERMANY 0x01
1112 # ifndef SUBLANG_URDU_PAKISTAN
1113 # define SUBLANG_URDU_PAKISTAN 0x01
1115 # ifndef SUBLANG_URDU_INDIA
1116 # define SUBLANG_URDU_INDIA 0x02
1118 # ifndef SUBLANG_UZBEK_LATIN
1119 # define SUBLANG_UZBEK_LATIN 0x01
1121 # ifndef SUBLANG_UZBEK_CYRILLIC
1122 # define SUBLANG_UZBEK_CYRILLIC 0x02
1124 # ifndef SUBLANG_VIETNAMESE_VIETNAM
1125 # define SUBLANG_VIETNAMESE_VIETNAM 0x01
1127 # ifndef SUBLANG_WELSH_UNITED_KINGDOM
1128 # define SUBLANG_WELSH_UNITED_KINGDOM 0x01
1130 # ifndef SUBLANG_WOLOF_SENEGAL
1131 # define SUBLANG_WOLOF_SENEGAL 0x01
1133 # ifndef SUBLANG_XHOSA_SOUTH_AFRICA
1134 # define SUBLANG_XHOSA_SOUTH_AFRICA 0x01
1136 # ifndef SUBLANG_YAKUT_RUSSIA
1137 # define SUBLANG_YAKUT_RUSSIA 0x01
1139 # ifndef SUBLANG_YI_PRC
1140 # define SUBLANG_YI_PRC 0x01
1142 # ifndef SUBLANG_YORUBA_NIGERIA
1143 # define SUBLANG_YORUBA_NIGERIA 0x01
1145 # ifndef SUBLANG_ZULU_SOUTH_AFRICA
1146 # define SUBLANG_ZULU_SOUTH_AFRICA 0x01
1148 /* GetLocaleInfoA operations. */
1149 # ifndef LOCALE_SNAME
1150 # define LOCALE_SNAME 0x5c
1152 # ifndef LOCALE_NAME_MAX_LENGTH
1153 # define LOCALE_NAME_MAX_LENGTH 85
1155 /* Don't assume that UNICODE is not defined. */
1156 # undef GetLocaleInfo
1157 # define GetLocaleInfo GetLocaleInfoA
1158 # undef EnumSystemLocales
1159 # define EnumSystemLocales EnumSystemLocalesA
1162 /* We want to use the system's setlocale() function here, not the gnulib
1167 #if HAVE_CFPREFERENCESCOPYAPPVALUE
1168 /* Mac OS X 10.4 or newer */
1170 /* Canonicalize a Mac OS X locale name to a Unix locale name.
1171 NAME is a sufficiently large buffer.
1172 On input, it contains the Mac OS X locale name.
1173 On output, it contains the Unix locale name. */
1174 # if !defined IN_LIBINTL
1178 gl_locale_name_canonicalize (char *name
)
1180 /* This conversion is based on a posting by
1181 Deborah GoldSmith <goldsmit@apple.com> on 2005-03-08,
1182 https://lists.apple.com/archives/carbon-dev/2005/Mar/msg00293.html */
1184 /* Convert legacy (NeXTstep inherited) English names to Unix (ISO 639 and
1185 ISO 3166) names. Prior to Mac OS X 10.3, there is no API for doing this.
1186 Therefore we do it ourselves, using a table based on the results of the
1187 Mac OS X 10.3.8 function
1188 CFLocaleCreateCanonicalLocaleIdentifierFromString(). */
1189 typedef struct { const char legacy
[21+1]; const char unixy
[5+1]; }
1191 static const legacy_entry legacy_table
[] = {
1192 { "Afrikaans", "af" },
1193 { "Albanian", "sq" },
1194 { "Amharic", "am" },
1196 { "Armenian", "hy" },
1197 { "Assamese", "as" },
1199 { "Azerbaijani", "az" },
1201 { "Belarusian", "be" },
1202 { "Belorussian", "be" },
1203 { "Bengali", "bn" },
1204 { "Brazilian Portugese", "pt_BR" },
1205 { "Brazilian Portuguese", "pt_BR" },
1207 { "Bulgarian", "bg" },
1208 { "Burmese", "my" },
1209 { "Byelorussian", "be" },
1210 { "Catalan", "ca" },
1212 { "Chichewa", "ny" },
1213 { "Chinese", "zh" },
1214 { "Chinese, Simplified", "zh_CN" },
1215 { "Chinese, Traditional", "zh_TW" },
1216 { "Chinese, Tradtional", "zh_TW" },
1217 { "Croatian", "hr" },
1221 { "Dzongkha", "dz" },
1222 { "English", "en" },
1223 { "Esperanto", "eo" },
1224 { "Estonian", "et" },
1225 { "Faroese", "fo" },
1227 { "Finnish", "fi" },
1228 { "Flemish", "nl_BE" },
1230 { "Galician", "gl" },
1231 { "Gallegan", "gl" },
1232 { "Georgian", "ka" },
1235 { "Greenlandic", "kl" },
1236 { "Guarani", "gn" },
1237 { "Gujarati", "gu" },
1238 { "Hawaiian", "haw" }, /* Yes, "haw", not "cpe". */
1241 { "Hungarian", "hu" },
1242 { "Icelandic", "is" },
1243 { "Indonesian", "id" },
1244 { "Inuktitut", "iu" },
1246 { "Italian", "it" },
1247 { "Japanese", "ja" },
1248 { "Javanese", "jv" },
1249 { "Kalaallisut", "kl" },
1250 { "Kannada", "kn" },
1251 { "Kashmiri", "ks" },
1254 { "Kinyarwanda", "rw" },
1255 { "Kirghiz", "ky" },
1257 { "Kurdish", "ku" },
1259 { "Latvian", "lv" },
1260 { "Lithuanian", "lt" },
1261 { "Macedonian", "mk" },
1262 { "Malagasy", "mg" },
1264 { "Malayalam", "ml" },
1265 { "Maltese", "mt" },
1267 { "Marathi", "mr" },
1268 { "Moldavian", "mo" },
1269 { "Mongolian", "mn" },
1271 { "Norwegian", "nb" }, /* Yes, "nb", not the obsolete "no". */
1273 { "Nynorsk", "nn" },
1276 { "Panjabi", "pa" },
1278 { "Persian", "fa" },
1280 { "Portuguese", "pt" },
1281 { "Portuguese, Brazilian", "pt_BR" },
1282 { "Punjabi", "pa" },
1284 { "Quechua", "qu" },
1285 { "Romanian", "ro" },
1288 { "Russian", "ru" },
1289 { "Sami", "se_NO" }, /* Not just "se". */
1290 { "Sanskrit", "sa" },
1291 { "Scottish", "gd" },
1292 { "Serbian", "sr" },
1293 { "Simplified Chinese", "zh_CN" },
1295 { "Sinhalese", "si" },
1297 { "Slovenian", "sl" },
1299 { "Spanish", "es" },
1300 { "Sundanese", "su" },
1301 { "Swahili", "sw" },
1302 { "Swedish", "sv" },
1303 { "Tagalog", "tl" },
1310 { "Tibetan", "bo" },
1311 { "Tigrinya", "ti" },
1313 { "Traditional Chinese", "zh_TW" },
1314 { "Turkish", "tr" },
1315 { "Turkmen", "tk" },
1317 { "Ukrainian", "uk" },
1320 { "Vietnamese", "vi" },
1325 /* Convert new-style locale names with language tags (ISO 639 and ISO 15924)
1326 to Unix (ISO 639 and ISO 3166) names. */
1327 typedef struct { const char langtag
[7+1]; const char unixy
[12+1]; }
1329 static const langtag_entry langtag_table
[] = {
1330 /* Mac OS X has "az-Arab", "az-Cyrl", "az-Latn".
1331 The default script for az on Unix is Latin. */
1332 { "az-Latn", "az" },
1333 /* Mac OS X has "bs-Cyrl", "bs-Latn".
1334 The default script for bs on Unix is Latin. */
1335 { "bs-Latn", "bs" },
1336 /* Mac OS X has "ga-dots". Does not yet exist on Unix. */
1337 { "ga-dots", "ga" },
1338 /* Mac OS X has "kk-Cyrl".
1339 The default script for kk on Unix is Cyrillic. */
1340 { "kk-Cyrl", "kk" },
1341 /* Mac OS X has "mn-Cyrl", "mn-Mong".
1342 The default script for mn on Unix is Cyrillic. */
1343 { "mn-Cyrl", "mn" },
1344 /* Mac OS X has "ms-Arab", "ms-Latn".
1345 The default script for ms on Unix is Latin. */
1346 { "ms-Latn", "ms" },
1347 /* Mac OS X has "pa-Arab", "pa-Guru".
1348 Country codes are used to distinguish these on Unix. */
1349 { "pa-Arab", "pa_PK" },
1350 { "pa-Guru", "pa_IN" },
1351 /* Mac OS X has "shi-Latn", "shi-Tfng". Does not yet exist on Unix. */
1352 /* Mac OS X has "sr-Cyrl", "sr-Latn".
1353 The default script for sr on Unix is Cyrillic. */
1354 { "sr-Cyrl", "sr" },
1355 /* Mac OS X has "tg-Cyrl".
1356 The default script for tg on Unix is Cyrillic. */
1357 { "tg-Cyrl", "tg" },
1358 /* Mac OS X has "tk-Cyrl".
1359 The default script for tk on Unix is Cyrillic. */
1360 { "tk-Cyrl", "tk" },
1361 /* Mac OS X has "tt-Cyrl".
1362 The default script for tt on Unix is Cyrillic. */
1363 { "tt-Cyrl", "tt" },
1364 /* Mac OS X has "uz-Arab", "uz-Cyrl", "uz-Latn".
1365 The default script for uz on Unix is Latin. */
1366 { "uz-Latn", "uz" },
1367 /* Mac OS X has "vai-Latn", "vai-Vaii". Does not yet exist on Unix. */
1368 /* Mac OS X has "yue-Hans", "yue-Hant".
1369 The default script for yue on Unix is Simplified Han. */
1370 { "yue-Hans", "yue" },
1371 /* Mac OS X has "zh-Hans", "zh-Hant".
1372 Country codes are used to distinguish these on Unix. */
1373 { "zh-Hans", "zh_CN" },
1374 { "zh-Hant", "zh_TW" }
1377 /* Convert script names (ISO 15924) to Unix conventions.
1378 See https://www.unicode.org/iso15924/iso15924-codes.html */
1379 typedef struct { const char script
[4+1]; const char unixy
[9+1]; }
1381 static const script_entry script_table
[] = {
1382 { "Arab", "arabic" },
1383 { "Cyrl", "cyrillic" },
1384 { "Latn", "latin" },
1385 { "Mong", "mongolian" }
1388 /* Step 1: Convert using legacy_table. */
1389 if (name
[0] >= 'A' && name
[0] <= 'Z')
1391 unsigned int i1
, i2
;
1393 i2
= sizeof (legacy_table
) / sizeof (legacy_entry
);
1396 /* At this point we know that if name occurs in legacy_table,
1397 its index must be >= i1 and < i2. */
1398 unsigned int i
= (i1
+ i2
) >> 1;
1399 const legacy_entry
*p
= &legacy_table
[i
];
1400 if (strcmp (name
, p
->legacy
) < 0)
1405 if (strcmp (name
, legacy_table
[i1
].legacy
) == 0)
1407 strcpy (name
, legacy_table
[i1
].unixy
);
1412 /* Step 2: Convert using langtag_table and script_table. */
1413 if (strlen (name
) == 7 && name
[2] == '-')
1415 unsigned int i1
, i2
;
1417 i2
= sizeof (langtag_table
) / sizeof (langtag_entry
);
1420 /* At this point we know that if name occurs in langtag_table,
1421 its index must be >= i1 and < i2. */
1422 unsigned int i
= (i1
+ i2
) >> 1;
1423 const langtag_entry
*p
= &langtag_table
[i
];
1424 if (strcmp (name
, p
->langtag
) < 0)
1429 if (strcmp (name
, langtag_table
[i1
].langtag
) == 0)
1431 strcpy (name
, langtag_table
[i1
].unixy
);
1436 i2
= sizeof (script_table
) / sizeof (script_entry
);
1439 /* At this point we know that if (name + 3) occurs in script_table,
1440 its index must be >= i1 and < i2. */
1441 unsigned int i
= (i1
+ i2
) >> 1;
1442 const script_entry
*p
= &script_table
[i
];
1443 if (strcmp (name
+ 3, p
->script
) < 0)
1448 if (strcmp (name
+ 3, script_table
[i1
].script
) == 0)
1451 strcpy (name
+ 3, script_table
[i1
].unixy
);
1456 /* Step 3: Convert new-style dash to Unix underscore. */
1459 for (p
= name
; *p
!= '\0'; p
++)
1468 #if defined WINDOWS_NATIVE || defined __CYGWIN__ /* Native Windows or Cygwin */
1470 /* Canonicalize a Windows native locale name to a Unix locale name.
1471 NAME is a sufficiently large buffer.
1472 On input, it contains the Windows locale name.
1473 On output, it contains the Unix locale name. */
1474 # if !defined IN_LIBINTL
1478 gl_locale_name_canonicalize (char *name
)
1480 /* FIXME: This is probably incomplete: it does not handle "zh-Hans" and
1484 for (p
= name
; *p
!= '\0'; p
++)
1489 for (; *p
!= '\0'; p
++)
1491 if (*p
>= 'a' && *p
<= 'z')
1503 # if !defined IN_LIBINTL
1507 gl_locale_name_from_win32_LANGID (LANGID langid
)
1509 /* Activate the new code only when the GETTEXT_MUI environment variable is
1510 set, for the time being, since the new code is not well tested. */
1511 if (getenv ("GETTEXT_MUI") != NULL
)
1513 static char namebuf
[256];
1515 /* Query the system's notion of locale name.
1516 On Windows95/98/ME, GetLocaleInfoA returns some incorrect results.
1517 But we don't need to support systems that are so old. */
1518 if (GetLocaleInfoA (MAKELCID (langid
, SORT_DEFAULT
), LOCALE_SNAME
,
1519 namebuf
, sizeof (namebuf
) - 1))
1521 /* Convert it to a Unix locale name. */
1522 gl_locale_name_canonicalize (namebuf
);
1526 /* Internet Explorer has an LCID to RFC3066 name mapping stored in
1527 HKEY_CLASSES_ROOT\Mime\Database\Rfc1766. But we better don't use that
1528 since IE's i18n subsystem is known to be inconsistent with the native
1529 Windows base (e.g. they have different character conversion facilities
1530 that produce different results). */
1531 /* Use our own table. */
1535 /* Split into language and territory part. */
1536 primary
= PRIMARYLANGID (langid
);
1537 sub
= SUBLANGID (langid
);
1539 /* Dispatch on language.
1540 See also https://www.unicode.org/unicode/onlinedat/languages.html .
1541 For details about languages, see https://www.ethnologue.com/ . */
1544 case LANG_AFRIKAANS
:
1547 case SUBLANG_AFRIKAANS_SOUTH_AFRICA
: return "af_ZA";
1553 case SUBLANG_ALBANIAN_ALBANIA
: return "sq_AL";
1559 case SUBLANG_ALSATIAN_FRANCE
: return "gsw_FR";
1565 case SUBLANG_AMHARIC_ETHIOPIA
: return "am_ET";
1571 case SUBLANG_ARABIC_SAUDI_ARABIA
: return "ar_SA";
1572 case SUBLANG_ARABIC_IRAQ
: return "ar_IQ";
1573 case SUBLANG_ARABIC_EGYPT
: return "ar_EG";
1574 case SUBLANG_ARABIC_LIBYA
: return "ar_LY";
1575 case SUBLANG_ARABIC_ALGERIA
: return "ar_DZ";
1576 case SUBLANG_ARABIC_MOROCCO
: return "ar_MA";
1577 case SUBLANG_ARABIC_TUNISIA
: return "ar_TN";
1578 case SUBLANG_ARABIC_OMAN
: return "ar_OM";
1579 case SUBLANG_ARABIC_YEMEN
: return "ar_YE";
1580 case SUBLANG_ARABIC_SYRIA
: return "ar_SY";
1581 case SUBLANG_ARABIC_JORDAN
: return "ar_JO";
1582 case SUBLANG_ARABIC_LEBANON
: return "ar_LB";
1583 case SUBLANG_ARABIC_KUWAIT
: return "ar_KW";
1584 case SUBLANG_ARABIC_UAE
: return "ar_AE";
1585 case SUBLANG_ARABIC_BAHRAIN
: return "ar_BH";
1586 case SUBLANG_ARABIC_QATAR
: return "ar_QA";
1592 case SUBLANG_ARMENIAN_ARMENIA
: return "hy_AM";
1598 case SUBLANG_ASSAMESE_INDIA
: return "as_IN";
1604 /* FIXME: Adjust this when Azerbaijani locales appear on Unix. */
1605 case 0x1e: return "az@latin";
1606 case SUBLANG_AZERI_LATIN
: return "az_AZ@latin";
1607 case 0x1d: return "az@cyrillic";
1608 case SUBLANG_AZERI_CYRILLIC
: return "az_AZ@cyrillic";
1614 case SUBLANG_BASHKIR_RUSSIA
: return "ba_RU";
1620 case SUBLANG_BASQUE_BASQUE
: return "eu_ES";
1622 return "eu"; /* Ambiguous: could be "eu_ES" or "eu_FR". */
1623 case LANG_BELARUSIAN
:
1626 case SUBLANG_BELARUSIAN_BELARUS
: return "be_BY";
1632 case SUBLANG_BENGALI_INDIA
: return "bn_IN";
1633 case SUBLANG_BENGALI_BANGLADESH
: return "bn_BD";
1639 case SUBLANG_BRETON_FRANCE
: return "br_FR";
1642 case LANG_BULGARIAN
:
1645 case SUBLANG_BULGARIAN_BULGARIA
: return "bg_BG";
1651 case SUBLANG_DEFAULT
: return "my_MM";
1654 case LANG_CAMBODIAN
:
1657 case SUBLANG_CAMBODIAN_CAMBODIA
: return "km_KH";
1663 case SUBLANG_CATALAN_SPAIN
: return "ca_ES";
1669 case SUBLANG_DEFAULT
: return "chr_US";
1675 case SUBLANG_CHINESE_TRADITIONAL
: case 0x1f: return "zh_TW";
1676 case SUBLANG_CHINESE_SIMPLIFIED
: case 0x00: return "zh_CN";
1677 case SUBLANG_CHINESE_HONGKONG
: return "zh_HK"; /* traditional */
1678 case SUBLANG_CHINESE_SINGAPORE
: return "zh_SG"; /* simplified */
1679 case SUBLANG_CHINESE_MACAU
: return "zh_MO"; /* traditional */
1685 case SUBLANG_CORSICAN_FRANCE
: return "co_FR";
1688 case LANG_CROATIAN
: /* LANG_CROATIAN == LANG_SERBIAN == LANG_BOSNIAN
1689 * What used to be called Serbo-Croatian
1690 * should really now be two separate
1691 * languages because of political reasons.
1692 * (Says tml, who knows nothing about Serbian
1694 * (I can feel those flames coming already.)
1699 case 0x00: return "hr";
1700 case SUBLANG_CROATIAN_CROATIA
: return "hr_HR";
1701 case SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN
: return "hr_BA";
1703 case 0x1f: return "sr";
1704 case 0x1c: return "sr"; /* latin */
1705 case SUBLANG_SERBIAN_LATIN
: return "sr_CS"; /* latin */
1706 case 0x09: return "sr_RS"; /* latin */
1707 case 0x0b: return "sr_ME"; /* latin */
1708 case 0x06: return "sr_BA"; /* latin */
1709 case 0x1b: return "sr@cyrillic";
1710 case SUBLANG_SERBIAN_CYRILLIC
: return "sr_CS@cyrillic";
1711 case 0x0a: return "sr_RS@cyrillic";
1712 case 0x0c: return "sr_ME@cyrillic";
1713 case 0x07: return "sr_BA@cyrillic";
1715 case 0x1e: return "bs";
1716 case 0x1a: return "bs"; /* latin */
1717 case SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN
: return "bs_BA"; /* latin */
1718 case 0x19: return "bs@cyrillic";
1719 case SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC
: return "bs_BA@cyrillic";
1725 case SUBLANG_CZECH_CZECH_REPUBLIC
: return "cs_CZ";
1731 case SUBLANG_DANISH_DENMARK
: return "da_DK";
1735 /* FIXME: Adjust this when such locales appear on Unix. */
1738 case SUBLANG_DARI_AFGHANISTAN
: return "prs_AF";
1744 case SUBLANG_DIVEHI_MALDIVES
: return "dv_MV";
1750 case SUBLANG_DUTCH
: return "nl_NL";
1751 case SUBLANG_DUTCH_BELGIAN
: /* FLEMISH, VLAAMS */ return "nl_BE";
1752 case SUBLANG_DUTCH_SURINAM
: return "nl_SR";
1758 case SUBLANG_DEFAULT
: return "bin_NG";
1764 /* SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. Heh. I thought
1765 * English was the language spoken in England.
1768 case SUBLANG_ENGLISH_US
: return "en_US";
1769 case SUBLANG_ENGLISH_UK
: return "en_GB";
1770 case SUBLANG_ENGLISH_AUS
: return "en_AU";
1771 case SUBLANG_ENGLISH_CAN
: return "en_CA";
1772 case SUBLANG_ENGLISH_NZ
: return "en_NZ";
1773 case SUBLANG_ENGLISH_EIRE
: return "en_IE";
1774 case SUBLANG_ENGLISH_SOUTH_AFRICA
: return "en_ZA";
1775 case SUBLANG_ENGLISH_JAMAICA
: return "en_JM";
1776 case SUBLANG_ENGLISH_CARIBBEAN
: return "en_GD"; /* Grenada? */
1777 case SUBLANG_ENGLISH_BELIZE
: return "en_BZ";
1778 case SUBLANG_ENGLISH_TRINIDAD
: return "en_TT";
1779 case SUBLANG_ENGLISH_ZIMBABWE
: return "en_ZW";
1780 case SUBLANG_ENGLISH_PHILIPPINES
: return "en_PH";
1781 case SUBLANG_ENGLISH_INDONESIA
: return "en_ID";
1782 case SUBLANG_ENGLISH_HONGKONG
: return "en_HK";
1783 case SUBLANG_ENGLISH_INDIA
: return "en_IN";
1784 case SUBLANG_ENGLISH_MALAYSIA
: return "en_MY";
1785 case SUBLANG_ENGLISH_SINGAPORE
: return "en_SG";
1791 case SUBLANG_ESTONIAN_ESTONIA
: return "et_EE";
1797 case SUBLANG_FAEROESE_FAROE_ISLANDS
: return "fo_FO";
1803 case SUBLANG_FARSI_IRAN
: return "fa_IR";
1809 case SUBLANG_FINNISH_FINLAND
: return "fi_FI";
1815 case SUBLANG_FRENCH
: return "fr_FR";
1816 case SUBLANG_FRENCH_BELGIAN
: /* WALLOON */ return "fr_BE";
1817 case SUBLANG_FRENCH_CANADIAN
: return "fr_CA";
1818 case SUBLANG_FRENCH_SWISS
: return "fr_CH";
1819 case SUBLANG_FRENCH_LUXEMBOURG
: return "fr_LU";
1820 case SUBLANG_FRENCH_MONACO
: return "fr_MC";
1821 case SUBLANG_FRENCH_WESTINDIES
: return "fr"; /* Caribbean? */
1822 case SUBLANG_FRENCH_REUNION
: return "fr_RE";
1823 case SUBLANG_FRENCH_CONGO
: return "fr_CG";
1824 case SUBLANG_FRENCH_SENEGAL
: return "fr_SN";
1825 case SUBLANG_FRENCH_CAMEROON
: return "fr_CM";
1826 case SUBLANG_FRENCH_COTEDIVOIRE
: return "fr_CI";
1827 case SUBLANG_FRENCH_MALI
: return "fr_ML";
1828 case SUBLANG_FRENCH_MOROCCO
: return "fr_MA";
1829 case SUBLANG_FRENCH_HAITI
: return "fr_HT";
1835 case SUBLANG_FRISIAN_NETHERLANDS
: return "fy_NL";
1839 /* Spoken in Nigeria, Guinea, Senegal, Mali, Niger, Cameroon, Benin. */
1842 case SUBLANG_DEFAULT
: return "ff_NG";
1848 case 0x01: /* SCOTTISH */
1849 /* old, superseded by LANG_SCOTTISH_GAELIC */
1851 case SUBLANG_IRISH_IRELAND
: return "ga_IE";
1857 case SUBLANG_GALICIAN_SPAIN
: return "gl_ES";
1863 case SUBLANG_GEORGIAN_GEORGIA
: return "ka_GE";
1869 case SUBLANG_GERMAN
: return "de_DE";
1870 case SUBLANG_GERMAN_SWISS
: return "de_CH";
1871 case SUBLANG_GERMAN_AUSTRIAN
: return "de_AT";
1872 case SUBLANG_GERMAN_LUXEMBOURG
: return "de_LU";
1873 case SUBLANG_GERMAN_LIECHTENSTEIN
: return "de_LI";
1879 case SUBLANG_GREEK_GREECE
: return "el_GR";
1882 case LANG_GREENLANDIC
:
1885 case SUBLANG_GREENLANDIC_GREENLAND
: return "kl_GL";
1891 case SUBLANG_DEFAULT
: return "gn_PY";
1897 case SUBLANG_GUJARATI_INDIA
: return "gu_IN";
1903 case 0x1f: return "ha";
1904 case SUBLANG_HAUSA_NIGERIA_LATIN
: return "ha_NG";
1908 /* FIXME: Do they mean Hawaiian ("haw_US", 1000 speakers)
1909 or Hawaii Creole English ("cpe_US", 600000 speakers)? */
1912 case SUBLANG_DEFAULT
: return "cpe_US";
1918 case SUBLANG_HEBREW_ISRAEL
: return "he_IL";
1924 case SUBLANG_HINDI_INDIA
: return "hi_IN";
1927 case LANG_HUNGARIAN
:
1930 case SUBLANG_HUNGARIAN_HUNGARY
: return "hu_HU";
1936 case SUBLANG_DEFAULT
: return "nic_NG";
1939 case LANG_ICELANDIC
:
1942 case SUBLANG_ICELANDIC_ICELAND
: return "is_IS";
1948 case SUBLANG_IGBO_NIGERIA
: return "ig_NG";
1951 case LANG_INDONESIAN
:
1954 case SUBLANG_INDONESIAN_INDONESIA
: return "id_ID";
1957 case LANG_INUKTITUT
:
1960 case 0x1e: return "iu"; /* syllabic */
1961 case SUBLANG_INUKTITUT_CANADA
: return "iu_CA"; /* syllabic */
1962 case 0x1f: return "iu@latin";
1963 case SUBLANG_INUKTITUT_CANADA_LATIN
: return "iu_CA@latin";
1969 case SUBLANG_ITALIAN
: return "it_IT";
1970 case SUBLANG_ITALIAN_SWISS
: return "it_CH";
1976 case SUBLANG_JAPANESE_JAPAN
: return "ja_JP";
1982 case SUBLANG_KANNADA_INDIA
: return "kn_IN";
1988 case SUBLANG_DEFAULT
: return "kr_NG";
1994 case SUBLANG_DEFAULT
: return "ks_PK";
1995 case SUBLANG_KASHMIRI_INDIA
: return "ks_IN";
2001 case SUBLANG_KAZAK_KAZAKHSTAN
: return "kk_KZ";
2005 /* FIXME: Adjust this when such locales appear on Unix. */
2008 case SUBLANG_KICHE_GUATEMALA
: return "qut_GT";
2011 case LANG_KINYARWANDA
:
2014 case SUBLANG_KINYARWANDA_RWANDA
: return "rw_RW";
2018 /* FIXME: Adjust this when such locales appear on Unix. */
2021 case SUBLANG_KONKANI_INDIA
: return "kok_IN";
2027 case SUBLANG_DEFAULT
: return "ko_KR";
2033 case SUBLANG_KYRGYZ_KYRGYZSTAN
: return "ky_KG";
2039 case SUBLANG_LAO_LAOS
: return "lo_LA";
2045 case SUBLANG_DEFAULT
: return "la_VA";
2051 case SUBLANG_LATVIAN_LATVIA
: return "lv_LV";
2054 case LANG_LITHUANIAN
:
2057 case SUBLANG_LITHUANIAN_LITHUANIA
: return "lt_LT";
2060 case LANG_LUXEMBOURGISH
:
2063 case SUBLANG_LUXEMBOURGISH_LUXEMBOURG
: return "lb_LU";
2066 case LANG_MACEDONIAN
:
2069 case SUBLANG_MACEDONIAN_MACEDONIA
: return "mk_MK";
2075 case SUBLANG_MALAY_MALAYSIA
: return "ms_MY";
2076 case SUBLANG_MALAY_BRUNEI_DARUSSALAM
: return "ms_BN";
2079 case LANG_MALAYALAM
:
2082 case SUBLANG_MALAYALAM_INDIA
: return "ml_IN";
2088 case SUBLANG_MALTESE_MALTA
: return "mt_MT";
2092 /* FIXME: Adjust this when such locales appear on Unix. */
2095 case SUBLANG_DEFAULT
: return "mni_IN";
2101 case SUBLANG_MAORI_NEW_ZEALAND
: return "mi_NZ";
2104 case LANG_MAPUDUNGUN
:
2107 case SUBLANG_MAPUDUNGUN_CHILE
: return "arn_CL";
2113 case SUBLANG_MARATHI_INDIA
: return "mr_IN";
2119 case SUBLANG_MOHAWK_CANADA
: return "moh_CA";
2122 case LANG_MONGOLIAN
:
2125 case SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA
: case 0x1e: return "mn_MN";
2126 case SUBLANG_MONGOLIAN_PRC
: case 0x1f: return "mn_CN";
2128 return "mn"; /* Ambiguous: could be "mn_CN" or "mn_MN". */
2132 case SUBLANG_NEPALI_NEPAL
: return "ne_NP";
2133 case SUBLANG_NEPALI_INDIA
: return "ne_IN";
2136 case LANG_NORWEGIAN
:
2139 case 0x1f: return "nb";
2140 case SUBLANG_NORWEGIAN_BOKMAL
: return "nb_NO";
2141 case 0x1e: return "nn";
2142 case SUBLANG_NORWEGIAN_NYNORSK
: return "nn_NO";
2148 case SUBLANG_OCCITAN_FRANCE
: return "oc_FR";
2154 case SUBLANG_ORIYA_INDIA
: return "or_IN";
2160 case SUBLANG_DEFAULT
: return "om_ET";
2163 case LANG_PAPIAMENTU
:
2166 case SUBLANG_DEFAULT
: return "pap_AN";
2172 case SUBLANG_PASHTO_AFGHANISTAN
: return "ps_AF";
2174 return "ps"; /* Ambiguous: could be "ps_PK" or "ps_AF". */
2178 case SUBLANG_POLISH_POLAND
: return "pl_PL";
2181 case LANG_PORTUGUESE
:
2184 /* Hmm. SUBLANG_PORTUGUESE_BRAZILIAN == SUBLANG_DEFAULT.
2185 Same phenomenon as SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. */
2186 case SUBLANG_PORTUGUESE_BRAZILIAN
: return "pt_BR";
2187 case SUBLANG_PORTUGUESE
: return "pt_PT";
2193 case SUBLANG_PUNJABI_INDIA
: return "pa_IN"; /* Gurmukhi script */
2194 case SUBLANG_PUNJABI_PAKISTAN
: return "pa_PK"; /* Arabic script */
2198 /* Note: Microsoft uses the non-ISO language code "quz". */
2201 case SUBLANG_QUECHUA_BOLIVIA
: return "qu_BO";
2202 case SUBLANG_QUECHUA_ECUADOR
: return "qu_EC";
2203 case SUBLANG_QUECHUA_PERU
: return "qu_PE";
2209 case SUBLANG_ROMANIAN_ROMANIA
: return "ro_RO";
2210 case SUBLANG_ROMANIAN_MOLDOVA
: return "ro_MD";
2216 case SUBLANG_ROMANSH_SWITZERLAND
: return "rm_CH";
2222 case SUBLANG_RUSSIAN_RUSSIA
: return "ru_RU";
2223 case SUBLANG_RUSSIAN_MOLDAVIA
: return "ru_MD";
2225 return "ru"; /* Ambiguous: could be "ru_RU" or "ru_UA" or "ru_MD". */
2230 case 0x00: return "se";
2231 case SUBLANG_SAMI_NORTHERN_NORWAY
: return "se_NO";
2232 case SUBLANG_SAMI_NORTHERN_SWEDEN
: return "se_SE";
2233 case SUBLANG_SAMI_NORTHERN_FINLAND
: return "se_FI";
2235 case 0x1f: return "smj";
2236 case SUBLANG_SAMI_LULE_NORWAY
: return "smj_NO";
2237 case SUBLANG_SAMI_LULE_SWEDEN
: return "smj_SE";
2239 case 0x1e: return "sma";
2240 case SUBLANG_SAMI_SOUTHERN_NORWAY
: return "sma_NO";
2241 case SUBLANG_SAMI_SOUTHERN_SWEDEN
: return "sma_SE";
2243 case 0x1d: return "sms";
2244 case SUBLANG_SAMI_SKOLT_FINLAND
: return "sms_FI";
2246 case 0x1c: return "smn";
2247 case SUBLANG_SAMI_INARI_FINLAND
: return "smn_FI";
2249 return "se"; /* or "smi"? */
2253 case SUBLANG_SANSKRIT_INDIA
: return "sa_IN";
2256 case LANG_SCOTTISH_GAELIC
:
2259 case SUBLANG_DEFAULT
: return "gd_GB";
2265 case SUBLANG_SINDHI_INDIA
: return "sd_IN";
2266 case SUBLANG_SINDHI_PAKISTAN
: return "sd_PK";
2267 /*case SUBLANG_SINDHI_AFGHANISTAN: return "sd_AF";*/
2270 case LANG_SINHALESE
:
2273 case SUBLANG_SINHALESE_SRI_LANKA
: return "si_LK";
2279 case SUBLANG_SLOVAK_SLOVAKIA
: return "sk_SK";
2282 case LANG_SLOVENIAN
:
2285 case SUBLANG_SLOVENIAN_SLOVENIA
: return "sl_SI";
2291 case SUBLANG_DEFAULT
: return "so_SO";
2295 /* FIXME: Adjust this when such locales appear on Unix. */
2299 case 0x00: return "hsb";
2300 case SUBLANG_UPPER_SORBIAN_GERMANY
: return "hsb_DE";
2302 case 0x1f: return "dsb";
2303 case SUBLANG_LOWER_SORBIAN_GERMANY
: return "dsb_DE";
2307 /* <https://docs.microsoft.com/en-us/windows/desktop/Intl/language-identifier-constants-and-strings>
2308 calls it "Sesotho sa Leboa"; according to
2309 <https://www.ethnologue.com/show_language.asp?code=nso>
2310 <https://www.ethnologue.com/show_language.asp?code=sot>
2311 it's the same as Northern Sotho. */
2314 case SUBLANG_SOTHO_SOUTH_AFRICA
: return "nso_ZA";
2320 case SUBLANG_SPANISH
: return "es_ES";
2321 case SUBLANG_SPANISH_MEXICAN
: return "es_MX";
2322 case SUBLANG_SPANISH_MODERN
:
2323 return "es_ES@modern"; /* not seen on Unix */
2324 case SUBLANG_SPANISH_GUATEMALA
: return "es_GT";
2325 case SUBLANG_SPANISH_COSTA_RICA
: return "es_CR";
2326 case SUBLANG_SPANISH_PANAMA
: return "es_PA";
2327 case SUBLANG_SPANISH_DOMINICAN_REPUBLIC
: return "es_DO";
2328 case SUBLANG_SPANISH_VENEZUELA
: return "es_VE";
2329 case SUBLANG_SPANISH_COLOMBIA
: return "es_CO";
2330 case SUBLANG_SPANISH_PERU
: return "es_PE";
2331 case SUBLANG_SPANISH_ARGENTINA
: return "es_AR";
2332 case SUBLANG_SPANISH_ECUADOR
: return "es_EC";
2333 case SUBLANG_SPANISH_CHILE
: return "es_CL";
2334 case SUBLANG_SPANISH_URUGUAY
: return "es_UY";
2335 case SUBLANG_SPANISH_PARAGUAY
: return "es_PY";
2336 case SUBLANG_SPANISH_BOLIVIA
: return "es_BO";
2337 case SUBLANG_SPANISH_EL_SALVADOR
: return "es_SV";
2338 case SUBLANG_SPANISH_HONDURAS
: return "es_HN";
2339 case SUBLANG_SPANISH_NICARAGUA
: return "es_NI";
2340 case SUBLANG_SPANISH_PUERTO_RICO
: return "es_PR";
2341 case SUBLANG_SPANISH_US
: return "es_US";
2347 case SUBLANG_DEFAULT
: return "bnt_TZ"; /* or "st_LS" or "nso_ZA"? */
2353 case SUBLANG_SWAHILI_KENYA
: return "sw_KE";
2359 case SUBLANG_SWEDISH_SWEDEN
: return "sv_SE";
2360 case SUBLANG_SWEDISH_FINLAND
: return "sv_FI";
2366 case SUBLANG_SYRIAC_SYRIA
: return "syr_SY"; /* An extinct language. */
2372 case SUBLANG_TAGALOG_PHILIPPINES
: return "tl_PH"; /* or "fil_PH"? */
2374 return "tl"; /* or "fil"? */
2378 case 0x1f: return "tg";
2379 case SUBLANG_TAJIK_TAJIKISTAN
: return "tg_TJ";
2382 case LANG_TAMAZIGHT
:
2383 /* Note: Microsoft uses the non-ISO language code "tmz". */
2386 /* FIXME: Adjust this when Tamazight locales appear on Unix. */
2387 case SUBLANG_TAMAZIGHT_ARABIC
: return "ber_MA@arabic";
2388 case 0x1f: return "ber@latin";
2389 case SUBLANG_TAMAZIGHT_ALGERIA_LATIN
: return "ber_DZ@latin";
2395 case SUBLANG_TAMIL_INDIA
: return "ta_IN";
2397 return "ta"; /* Ambiguous: could be "ta_IN" or "ta_LK" or "ta_SG". */
2401 case SUBLANG_TATAR_RUSSIA
: return "tt_RU";
2407 case SUBLANG_TELUGU_INDIA
: return "te_IN";
2413 case SUBLANG_THAI_THAILAND
: return "th_TH";
2419 case SUBLANG_TIBETAN_PRC
:
2420 /* Most Tibetans would not like "bo_CN". But Tibet does not yet
2421 have a country code of its own. */
2423 case SUBLANG_TIBETAN_BHUTAN
: return "bo_BT";
2429 case SUBLANG_TIGRINYA_ETHIOPIA
: return "ti_ET";
2430 case SUBLANG_TIGRINYA_ERITREA
: return "ti_ER";
2436 case SUBLANG_DEFAULT
: return "ts_ZA";
2440 /* Spoken in South Africa, Botswana. */
2443 case SUBLANG_TSWANA_SOUTH_AFRICA
: return "tn_ZA";
2449 case SUBLANG_TURKISH_TURKEY
: return "tr_TR";
2455 case SUBLANG_TURKMEN_TURKMENISTAN
: return "tk_TM";
2461 case SUBLANG_UIGHUR_PRC
: return "ug_CN";
2464 case LANG_UKRAINIAN
:
2467 case SUBLANG_UKRAINIAN_UKRAINE
: return "uk_UA";
2473 case SUBLANG_URDU_PAKISTAN
: return "ur_PK";
2474 case SUBLANG_URDU_INDIA
: return "ur_IN";
2480 case 0x1f: return "uz";
2481 case SUBLANG_UZBEK_LATIN
: return "uz_UZ";
2482 case 0x1e: return "uz@cyrillic";
2483 case SUBLANG_UZBEK_CYRILLIC
: return "uz_UZ@cyrillic";
2489 case SUBLANG_DEFAULT
: return "ve_ZA";
2492 case LANG_VIETNAMESE
:
2495 case SUBLANG_VIETNAMESE_VIETNAM
: return "vi_VN";
2501 case SUBLANG_WELSH_UNITED_KINGDOM
: return "cy_GB";
2507 case SUBLANG_WOLOF_SENEGAL
: return "wo_SN";
2513 case SUBLANG_XHOSA_SOUTH_AFRICA
: return "xh_ZA";
2519 case SUBLANG_YAKUT_RUSSIA
: return "sah_RU";
2525 case SUBLANG_YI_PRC
: return "ii_CN";
2531 case SUBLANG_DEFAULT
: return "yi_IL";
2537 case SUBLANG_YORUBA_NIGERIA
: return "yo_NG";
2543 case SUBLANG_ZULU_SOUTH_AFRICA
: return "zu_ZA";
2546 default: return "C";
2551 # if !defined IN_LIBINTL
2555 gl_locale_name_from_win32_LCID (LCID lcid
)
2559 /* Strip off the sorting rules, keep only the language part. */
2560 langid
= LANGIDFROMLCID (lcid
);
2562 return gl_locale_name_from_win32_LANGID (langid
);
2565 # ifdef WINDOWS_NATIVE
2567 /* Two variables to interface between get_lcid and the EnumLocales
2568 callback function below. */
2569 static LCID found_lcid
;
2570 static char lname
[LC_MAX
* (LOCALE_NAME_MAX_LENGTH
+ 1) + 1];
2572 /* Callback function for EnumLocales. */
2573 static BOOL CALLBACK
2574 enum_locales_fn (LPSTR locale_num_str
)
2577 char locval
[2 * LOCALE_NAME_MAX_LENGTH
+ 1 + 1];
2578 LCID try_lcid
= strtoul (locale_num_str
, &endp
, 16);
2580 if (GetLocaleInfo (try_lcid
, LOCALE_SENGLANGUAGE
,
2581 locval
, LOCALE_NAME_MAX_LENGTH
))
2583 strcat (locval
, "_");
2584 if (GetLocaleInfo (try_lcid
, LOCALE_SENGCOUNTRY
,
2585 locval
+ strlen (locval
), LOCALE_NAME_MAX_LENGTH
))
2587 size_t locval_len
= strlen (locval
);
2589 if (strncmp (locval
, lname
, locval_len
) == 0
2590 && (lname
[locval_len
] == '.'
2591 || lname
[locval_len
] == '\0'))
2593 found_lcid
= try_lcid
;
2601 /* This lock protects the get_lcid against multiple simultaneous calls. */
2602 gl_lock_define_initialized(static, get_lcid_lock
)
2604 /* Return the Locale ID (LCID) number given the locale's name, a
2605 string, in LOCALE_NAME. This works by enumerating all the locales
2606 supported by the system, until we find one whose name matches
2609 get_lcid (const char *locale_name
)
2611 /* A simple cache. */
2612 static LCID last_lcid
;
2613 static char last_locale
[1000];
2615 /* Lock while looking for an LCID, to protect access to static
2616 variables: last_lcid, last_locale, found_lcid, and lname. */
2617 gl_lock_lock (get_lcid_lock
);
2618 if (last_lcid
> 0 && strcmp (locale_name
, last_locale
) == 0)
2620 gl_lock_unlock (get_lcid_lock
);
2623 strncpy (lname
, locale_name
, sizeof (lname
) - 1);
2624 lname
[sizeof (lname
) - 1] = '\0';
2626 EnumSystemLocales (enum_locales_fn
, LCID_SUPPORTED
);
2629 last_lcid
= found_lcid
;
2630 strcpy (last_locale
, locale_name
);
2632 gl_lock_unlock (get_lcid_lock
);
2640 #if HAVE_GOOD_USELOCALE /* glibc, Mac OS X, FreeBSD >= 9.1, Cygwin >= 2.6,
2641 Solaris 11 OpenIndiana, or Solaris >= 11.4 */
2643 /* Simple hash set of strings. We don't want to drag in lots of hash table
2646 # define SIZE_BITS (sizeof (size_t) * CHAR_BIT)
2648 /* A hash function for NUL-terminated char* strings using
2649 the method described by Bruno Haible.
2650 See https://www.haible.de/bruno/hashfunc.html. */
2651 static size_t _GL_ATTRIBUTE_PURE
2652 string_hash (const void *x
)
2654 const char *s
= (const char *) x
;
2658 h
= *s
+ ((h
<< 9) | (h
>> (SIZE_BITS
- 9)));
2663 /* A hash table of fixed size. Multiple threads can access it read-only
2664 simultaneously, but only one thread can insert into it at the same time. */
2666 /* A node in a hash bucket collision list. */
2667 struct struniq_hash_node
2669 struct struniq_hash_node
* volatile next
;
2670 char contents
[FLEXIBLE_ARRAY_MEMBER
];
2673 # define STRUNIQ_HASH_TABLE_SIZE 257
2674 static struct struniq_hash_node
* volatile struniq_hash_table
[STRUNIQ_HASH_TABLE_SIZE
]
2675 /* = { NULL, ..., NULL } */;
2677 /* This lock protects the struniq_hash_table against multiple simultaneous
2679 gl_lock_define_initialized(static, struniq_lock
)
2681 /* Store a copy of the given string in a string pool with indefinite extent.
2682 Return a pointer to this copy. */
2684 struniq (const char *string
)
2686 size_t hashcode
= string_hash (string
);
2687 size_t slot
= hashcode
% STRUNIQ_HASH_TABLE_SIZE
;
2689 struct struniq_hash_node
*new_node
;
2690 struct struniq_hash_node
*p
;
2691 for (p
= struniq_hash_table
[slot
]; p
!= NULL
; p
= p
->next
)
2692 if (strcmp (p
->contents
, string
) == 0)
2694 size
= strlen (string
) + 1;
2696 (struct struniq_hash_node
*)
2697 malloc (FLEXSIZEOF (struct struniq_hash_node
, contents
, size
));
2698 if (new_node
== NULL
)
2699 /* Out of memory. Return a statically allocated string. */
2701 memcpy (new_node
->contents
, string
, size
);
2703 bool mt
= gl_multithreaded ();
2704 /* Lock while inserting new_node. */
2705 if (mt
) gl_lock_lock (struniq_lock
);
2706 /* Check whether another thread already added the string while we were
2707 waiting on the lock. */
2708 for (p
= struniq_hash_table
[slot
]; p
!= NULL
; p
= p
->next
)
2709 if (strcmp (p
->contents
, string
) == 0)
2715 /* Really insert new_node into the hash table. Fill new_node entirely
2716 first, because other threads may be iterating over the linked list. */
2717 new_node
->next
= struniq_hash_table
[slot
];
2718 struniq_hash_table
[slot
] = new_node
;
2720 /* Unlock after new_node is inserted. */
2721 if (mt
) gl_lock_unlock (struniq_lock
);
2723 return new_node
->contents
;
2729 #if HAVE_GOOD_USELOCALE && HAVE_NAMELESS_LOCALES
2731 /* The 'locale_t' object does not contain the names of the locale categories.
2732 We have to associate them with the object through a hash table.
2733 The hash table is defined in localename-table.[hc]. */
2735 /* Returns the name of a given locale category in a given locale_t object,
2736 allocated as a string with indefinite extent. */
2738 get_locale_t_name (int category
, locale_t locale
)
2740 if (locale
== LC_GLOBAL_LOCALE
)
2742 /* Query the global locale. */
2743 const char *name
= setlocale_null (category
);
2745 return struniq (name
);
2747 /* Should normally not happen. */
2752 /* Look up the names in the hash table. */
2753 size_t hashcode
= locale_hash_function (locale
);
2754 size_t slot
= hashcode
% LOCALE_HASH_TABLE_SIZE
;
2755 /* If the locale was not found in the table, return "". This can
2756 happen if the application uses the original newlocale()/duplocale()
2757 functions instead of the overridden ones. */
2758 const char *name
= "";
2759 struct locale_hash_node
*p
;
2760 /* Lock while looking up the hash node. */
2761 gl_rwlock_rdlock (locale_lock
);
2762 for (p
= locale_hash_table
[slot
]; p
!= NULL
; p
= p
->next
)
2763 if (p
->locale
== locale
)
2765 name
= p
->names
.category_name
[category
];
2768 gl_rwlock_unlock (locale_lock
);
2773 # if !(defined newlocale && defined duplocale && defined freelocale)
2774 # error "newlocale, duplocale, freelocale not being replaced as expected!"
2777 /* newlocale() override. */
2779 newlocale (int category_mask
, const char *name
, locale_t base
)
2782 struct locale_categories_names names
;
2783 struct locale_hash_node
*node
;
2786 /* Make sure name has indefinite extent. */
2787 if (((LC_CTYPE_MASK
| LC_NUMERIC_MASK
| LC_TIME_MASK
| LC_COLLATE_MASK
2788 | LC_MONETARY_MASK
| LC_MESSAGES_MASK
)
2789 & category_mask
) != 0)
2790 name
= struniq (name
);
2792 /* Determine the category names of the result. */
2793 if (((LC_CTYPE_MASK
| LC_NUMERIC_MASK
| LC_TIME_MASK
| LC_COLLATE_MASK
2794 | LC_MONETARY_MASK
| LC_MESSAGES_MASK
)
2795 & ~category_mask
) == 0)
2797 /* Use name, ignore base. */
2800 name
= struniq (name
);
2801 for (category
= 0; category
< 6; category
++)
2802 names
.category_name
[category
] = name
;
2806 /* Use base, possibly also name. */
2811 for (category
= 0; category
< 6; category
++)
2818 mask
= LC_CTYPE_MASK
;
2821 mask
= LC_NUMERIC_MASK
;
2824 mask
= LC_TIME_MASK
;
2827 mask
= LC_COLLATE_MASK
;
2830 mask
= LC_MONETARY_MASK
;
2833 mask
= LC_MESSAGES_MASK
;
2838 names
.category_name
[category
] =
2839 ((mask
& category_mask
) != 0 ? name
: "C");
2842 else if (base
== LC_GLOBAL_LOCALE
)
2846 for (category
= 0; category
< 6; category
++)
2853 mask
= LC_CTYPE_MASK
;
2856 mask
= LC_NUMERIC_MASK
;
2859 mask
= LC_TIME_MASK
;
2862 mask
= LC_COLLATE_MASK
;
2865 mask
= LC_MONETARY_MASK
;
2868 mask
= LC_MESSAGES_MASK
;
2873 names
.category_name
[category
] =
2874 ((mask
& category_mask
) != 0
2876 : get_locale_t_name (category
, LC_GLOBAL_LOCALE
));
2881 /* Look up the names of base in the hash table. Like multiple calls
2882 of get_locale_t_name, but locking only once. */
2883 struct locale_hash_node
*p
;
2886 /* Lock while looking up the hash node. */
2887 gl_rwlock_rdlock (locale_lock
);
2888 for (p
= locale_hash_table
[locale_hash_function (base
) % LOCALE_HASH_TABLE_SIZE
];
2891 if (p
->locale
== base
)
2894 for (category
= 0; category
< 6; category
++)
2901 mask
= LC_CTYPE_MASK
;
2904 mask
= LC_NUMERIC_MASK
;
2907 mask
= LC_TIME_MASK
;
2910 mask
= LC_COLLATE_MASK
;
2913 mask
= LC_MONETARY_MASK
;
2916 mask
= LC_MESSAGES_MASK
;
2921 names
.category_name
[category
] =
2922 ((mask
& category_mask
) != 0
2924 : (p
!= NULL
? p
->names
.category_name
[category
] : ""));
2927 gl_rwlock_unlock (locale_lock
);
2931 node
= (struct locale_hash_node
*) malloc (sizeof (struct locale_hash_node
));
2933 /* errno is set to ENOMEM. */
2936 result
= newlocale (category_mask
, name
, base
);
2939 int saved_errno
= errno
;
2941 errno
= saved_errno
;
2945 /* Fill the hash node. */
2946 node
->locale
= result
;
2947 node
->names
= names
;
2949 /* Insert it in the hash table. */
2951 size_t hashcode
= locale_hash_function (result
);
2952 size_t slot
= hashcode
% LOCALE_HASH_TABLE_SIZE
;
2953 struct locale_hash_node
*p
;
2955 /* Lock while inserting the new node. */
2956 gl_rwlock_wrlock (locale_lock
);
2957 for (p
= locale_hash_table
[slot
]; p
!= NULL
; p
= p
->next
)
2958 if (p
->locale
== result
)
2960 /* This can happen if the application uses the original freelocale()
2961 function instead of the overridden one. */
2962 p
->names
= node
->names
;
2967 node
->next
= locale_hash_table
[slot
];
2968 locale_hash_table
[slot
] = node
;
2971 gl_rwlock_unlock (locale_lock
);
2980 /* duplocale() override. */
2982 duplocale (locale_t locale
)
2985 struct locale_hash_node
*node
;
2989 /* Invalid argument. */
2992 node
= (struct locale_hash_node
*) malloc (sizeof (struct locale_hash_node
));
2994 /* errno is set to ENOMEM. */
2997 result
= duplocale (locale
);
3000 int saved_errno
= errno
;
3002 errno
= saved_errno
;
3006 /* Fill the hash node. */
3007 node
->locale
= result
;
3008 if (locale
== LC_GLOBAL_LOCALE
)
3012 for (category
= 0; category
< 6; category
++)
3013 node
->names
.category_name
[category
] =
3014 get_locale_t_name (category
, LC_GLOBAL_LOCALE
);
3016 /* Lock before inserting the new node. */
3017 gl_rwlock_wrlock (locale_lock
);
3021 struct locale_hash_node
*p
;
3023 /* Lock once, for the lookup and the insertion. */
3024 gl_rwlock_wrlock (locale_lock
);
3026 for (p
= locale_hash_table
[locale_hash_function (locale
) % LOCALE_HASH_TABLE_SIZE
];
3029 if (p
->locale
== locale
)
3032 node
->names
= p
->names
;
3035 /* This can happen if the application uses the original
3036 newlocale()/duplocale() functions instead of the overridden
3040 for (category
= 0; category
< 6; category
++)
3041 node
->names
.category_name
[category
] = "";
3045 /* Insert it in the hash table. */
3047 size_t hashcode
= locale_hash_function (result
);
3048 size_t slot
= hashcode
% LOCALE_HASH_TABLE_SIZE
;
3049 struct locale_hash_node
*p
;
3051 for (p
= locale_hash_table
[slot
]; p
!= NULL
; p
= p
->next
)
3052 if (p
->locale
== result
)
3054 /* This can happen if the application uses the original freelocale()
3055 function instead of the overridden one. */
3056 p
->names
= node
->names
;
3061 node
->next
= locale_hash_table
[slot
];
3062 locale_hash_table
[slot
] = node
;
3065 gl_rwlock_unlock (locale_lock
);
3074 /* freelocale() override. */
3076 freelocale (locale_t locale
)
3079 if (locale
== NULL
|| locale
== LC_GLOBAL_LOCALE
)
3080 /* Invalid argument. */
3084 size_t hashcode
= locale_hash_function (locale
);
3085 size_t slot
= hashcode
% LOCALE_HASH_TABLE_SIZE
;
3086 struct locale_hash_node
*found
;
3087 struct locale_hash_node
**p
;
3090 /* Lock while removing the hash node. */
3091 gl_rwlock_wrlock (locale_lock
);
3092 for (p
= &locale_hash_table
[slot
]; *p
!= NULL
; p
= &(*p
)->next
)
3093 if ((*p
)->locale
== locale
)
3099 gl_rwlock_unlock (locale_lock
);
3103 freelocale (locale
);
3109 #if defined IN_LIBINTL || HAVE_GOOD_USELOCALE
3111 /* Like gl_locale_name_thread, except that the result is not in storage of
3112 indefinite extent. */
3113 # if !defined IN_LIBINTL
3117 gl_locale_name_thread_unsafe (int category
, const char *categoryname _GL_UNUSED
)
3119 # if HAVE_GOOD_USELOCALE
3121 locale_t thread_locale
= uselocale (NULL
);
3122 if (thread_locale
!= LC_GLOBAL_LOCALE
)
3124 # if __GLIBC__ >= 2 && !defined __UCLIBC__
3125 /* Work around an incorrect definition of the _NL_LOCALE_NAME macro in
3127 See <https://sourceware.org/bugzilla/show_bug.cgi?id=10968>. */
3129 nl_langinfo (_NL_ITEM ((category
), _NL_ITEM_INDEX (-1)));
3130 if (name
[0] == '\0')
3131 /* Fallback code for glibc < 2.4, which did not implement
3132 nl_langinfo (_NL_LOCALE_NAME (category)). */
3133 name
= thread_locale
->__names
[category
];
3135 # elif defined __linux__ && HAVE_LANGINFO_H && defined NL_LOCALE_NAME
3137 return nl_langinfo_l (NL_LOCALE_NAME (category
), thread_locale
);
3138 # elif (defined __FreeBSD__ || defined __DragonFly__) || (defined __APPLE__ && defined __MACH__)
3139 /* FreeBSD, Mac OS X */
3145 mask
= LC_CTYPE_MASK
;
3148 mask
= LC_NUMERIC_MASK
;
3151 mask
= LC_TIME_MASK
;
3154 mask
= LC_COLLATE_MASK
;
3157 mask
= LC_MONETARY_MASK
;
3160 mask
= LC_MESSAGES_MASK
;
3162 default: /* We shouldn't get here. */
3165 return querylocale (mask
, thread_locale
);
3166 # elif defined __sun
3167 # if HAVE_GETLOCALENAME_L
3168 /* Solaris >= 12. */
3169 return getlocalename_l (category
, thread_locale
);
3170 # elif HAVE_SOLARIS114_LOCALES
3171 /* Solaris >= 11.4. */
3172 void *lcp
= (*thread_locale
)->core
.data
->lcp
;
3182 return ((const char * const *) lcp
)[category
];
3183 default: /* We shouldn't get here. */
3186 # elif HAVE_NAMELESS_LOCALES
3187 return get_locale_t_name (category
, thread_locale
);
3189 /* Solaris 11 OpenIndiana.
3190 For the internal structure of locale objects, see
3191 https://github.com/OpenIndiana/illumos-gate/blob/master/usr/src/lib/libc/port/locale/localeimpl.h */
3200 return ((const char * const *) thread_locale
)[category
];
3201 default: /* We shouldn't get here. */
3205 # elif defined _AIX && HAVE_NAMELESS_LOCALES
3206 return get_locale_t_name (category
, thread_locale
);
3207 # elif defined __CYGWIN__
3208 /* Cygwin < 2.6 lacks uselocale and thread-local locales altogether.
3209 Cygwin <= 2.6.1 lacks NL_LOCALE_NAME, requiring peeking inside
3210 an opaque struct. */
3211 # ifdef NL_LOCALE_NAME
3212 return nl_langinfo_l (NL_LOCALE_NAME (category
), thread_locale
);
3214 /* FIXME: Remove when we can assume new-enough Cygwin. */
3216 char categories
[7][32];
3218 return ((struct __locale_t
*) thread_locale
)->categories
[category
];
3220 # elif defined __ANDROID__
3221 return MB_CUR_MAX
== 4 ? "C.UTF-8" : "C";
3232 gl_locale_name_thread (int category
, const char *categoryname _GL_UNUSED
)
3234 #if HAVE_GOOD_USELOCALE
3235 const char *name
= gl_locale_name_thread_unsafe (category
, categoryname
);
3237 return struniq (name
);
3239 /* On WINDOWS_NATIVE, don't use GetThreadLocale() here, because when
3240 SetThreadLocale has not been called - which is a very frequent case -
3241 the value of GetThreadLocale() ignores past calls to 'setlocale'. */
3245 /* XPG3 defines the result of 'setlocale (category, NULL)' as:
3246 "Directs 'setlocale()' to query 'category' and return the current
3247 setting of 'local'."
3248 However it does not specify the exact format. Neither do SUSV2 and
3249 ISO C 99. So we can use this feature only on selected systems (e.g.
3250 those using GNU C Library). */
3251 #if defined _LIBC || ((defined __GLIBC__ && __GLIBC__ >= 2) && !defined __UCLIBC__)
3252 # define HAVE_LOCALE_NULL
3256 gl_locale_name_posix (int category
, const char *categoryname _GL_UNUSED
)
3258 #if defined WINDOWS_NATIVE
3259 if (LC_MIN
<= category
&& category
<= LC_MAX
)
3261 const char *locname
=
3262 /* setlocale_null (category) is identical to setlocale (category, NULL)
3263 on this platform. */
3264 setlocale (category
, NULL
);
3266 /* Convert locale name to LCID. We don't want to use
3267 LocaleNameToLCID because (a) it is only available since Vista,
3268 and (b) it doesn't accept locale names returned by 'setlocale'. */
3269 LCID lcid
= get_lcid (locname
);
3272 return gl_locale_name_from_win32_LCID (lcid
);
3276 const char *locname
;
3278 /* Use the POSIX methods of looking to 'LC_ALL', 'LC_xxx', and 'LANG'.
3279 On some systems this can be done by the 'setlocale' function itself. */
3280 #if defined HAVE_LC_MESSAGES && defined HAVE_LOCALE_NULL
3281 locname
= setlocale_null (category
);
3283 /* On other systems we ignore what setlocale reports and instead look at the
3284 environment variables directly. This is necessary
3285 1. on systems which have a facility for customizing the default locale
3286 (Mac OS X, native Windows, Cygwin) and where the system's setlocale()
3287 function ignores this default locale (Mac OS X, Cygwin), in two cases:
3288 a. when the user missed to use the setlocale() override from libintl
3289 (for example by not including <libintl.h>),
3290 b. when setlocale supports only the "C" locale, such as on Cygwin
3291 1.5.x. In this case even the override from libintl cannot help.
3292 2. on all systems where setlocale supports only the "C" locale. */
3293 /* Strictly speaking, it is a POSIX violation to look at the environment
3294 variables regardless whether setlocale has been called or not. POSIX
3296 "For C-language programs, the POSIX locale shall be the
3297 default locale when the setlocale() function is not called."
3298 But we assume that all programs that use internationalized APIs call
3299 setlocale (LC_ALL, ""). */
3300 locname
= gl_locale_name_environ (category
, categoryname
);
3302 /* Convert the locale name from the format returned by setlocale() or found
3303 in the environment variables to the XPG syntax. */
3304 #if defined WINDOWS_NATIVE
3305 if (locname
!= NULL
)
3307 /* Convert locale name to LCID. We don't want to use
3308 LocaleNameToLCID because (a) it is only available since Vista,
3309 and (b) it doesn't accept locale names returned by 'setlocale'. */
3310 LCID lcid
= get_lcid (locname
);
3313 return gl_locale_name_from_win32_LCID (lcid
);
3321 gl_locale_name_environ (int category _GL_UNUSED
, const char *categoryname
)
3325 /* Setting of LC_ALL overrides all other. */
3326 retval
= getenv ("LC_ALL");
3327 if (retval
!= NULL
&& retval
[0] != '\0')
3329 /* Next comes the name of the desired category. */
3330 retval
= getenv (categoryname
);
3331 if (retval
!= NULL
&& retval
[0] != '\0')
3333 /* Last possibility is the LANG environment variable. */
3334 retval
= getenv ("LANG");
3335 if (retval
!= NULL
&& retval
[0] != '\0')
3337 #if HAVE_CFPREFERENCESCOPYAPPVALUE
3338 /* Mac OS X 10.2 or newer.
3339 Ignore invalid LANG value set by the Terminal application. */
3340 if (strcmp (retval
, "UTF-8") != 0)
3342 #if defined __CYGWIN__
3344 Ignore dummy LANG value set by ~/.profile. */
3345 if (strcmp (retval
, "C.UTF-8") != 0)
3354 gl_locale_name_default (void)
3357 "All implementations shall define a locale as the default locale, to be
3358 invoked when no environment variables are set, or set to the empty
3359 string. This default locale can be the POSIX locale or any other
3360 implementation-defined locale. Some implementations may provide
3361 facilities for local installation administrators to set the default
3362 locale, customizing it for each location. POSIX:2001 does not require
3365 The systems with such a facility are Mac OS X and Windows: They provide a
3366 GUI that allows the user to choose a locale.
3367 - On Mac OS X, by default, none of LC_* or LANG are set. Starting with
3368 Mac OS X 10.4 or 10.5, LANG is set for processes launched by the
3369 'Terminal' application (but sometimes to an incorrect value "UTF-8").
3370 When no environment variable is set, setlocale (LC_ALL, "") uses the
3372 - On native Windows, by default, none of LC_* or LANG are set.
3373 When no environment variable is set, setlocale (LC_ALL, "") uses the
3374 locale chosen by the user.
3375 - On Cygwin 1.5.x, by default, none of LC_* or LANG are set.
3376 When no environment variable is set, setlocale (LC_ALL, "") uses the
3378 - On Cygwin 1.7, by default, LANG is set to "C.UTF-8" when the default
3379 ~/.profile is executed.
3380 When no environment variable is set, setlocale (LC_ALL, "") uses the
3381 "C.UTF-8" locale, which operates in the same way as the "C" locale.
3384 #if !(HAVE_CFPREFERENCESCOPYAPPVALUE || defined WINDOWS_NATIVE || defined __CYGWIN__)
3386 /* The system does not have a way of setting the locale, other than the
3387 POSIX specified environment variables. We use C as default locale. */
3392 /* Return an XPG style locale name language[_territory][@modifier].
3393 Don't even bother determining the codeset; it's not useful in this
3394 context, because message catalogs are not specific to a single
3397 # if HAVE_CFPREFERENCESCOPYAPPVALUE
3398 /* Mac OS X 10.4 or newer */
3399 /* Don't use the API introduced in Mac OS X 10.5, CFLocaleCopyCurrent,
3400 because in macOS 10.13.4 it has the following behaviour:
3401 When two or more languages are specified in the
3402 "System Preferences > Language & Region > Preferred Languages" panel,
3403 it returns en_CC where CC is the territory (even when English is not among
3404 the preferred languages!). What we want instead is what
3405 CFLocaleCopyCurrent returned in earlier macOS releases and what
3406 CFPreferencesCopyAppValue still returns, namely ll_CC where ll is the
3407 first among the preferred languages and CC is the territory. */
3409 /* Cache the locale name, since CoreFoundation calls are expensive. */
3410 static const char *cached_localename
;
3412 if (cached_localename
== NULL
)
3416 CFPreferencesCopyAppValue (CFSTR ("AppleLocale"),
3417 kCFPreferencesCurrentApplication
);
3418 if (value
!= NULL
&& CFGetTypeID (value
) == CFStringGetTypeID ())
3420 CFStringRef name
= (CFStringRef
)value
;
3422 if (CFStringGetCString (name
, namebuf
, sizeof (namebuf
),
3423 kCFStringEncodingASCII
))
3425 gl_locale_name_canonicalize (namebuf
);
3426 cached_localename
= strdup (namebuf
);
3429 if (cached_localename
== NULL
)
3430 cached_localename
= "C";
3432 return cached_localename
;
3437 # if defined WINDOWS_NATIVE || defined __CYGWIN__ /* Native Windows or Cygwin */
3441 /* Use native Windows API locale ID. */
3442 lcid
= GetThreadLocale ();
3444 return gl_locale_name_from_win32_LCID (lcid
);
3450 /* Determine the current locale's name, and canonicalize it into XPG syntax
3451 language[_territory][.codeset][@modifier]
3452 The codeset part in the result is not reliable; the locale_charset()
3453 should be used for codeset information instead.
3454 The result must not be freed; it is statically allocated. */
3457 gl_locale_name (int category
, const char *categoryname
)
3461 retval
= gl_locale_name_thread (category
, categoryname
);
3465 retval
= gl_locale_name_posix (category
, categoryname
);
3469 return gl_locale_name_default ();