1 /* Determine name of the currently selected locale.
2 Copyright (C) 1995-2018 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation; either version 2.1 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
17 /* Written by Ulrich Drepper <drepper@gnu.org>, 1995. */
18 /* Native Windows code written by Tor Lillqvist <tml@iki.fi>. */
19 /* Mac OS X code written by Bruno Haible <bruno@clisp.org>. */
25 # include "gettextP.h"
27 # include "localename.h"
36 #include "flexmember.h"
39 /* Mac OS X 10.5 defines the locale_t type in <xlocale.h>. */
40 # if defined __APPLE__ && defined __MACH__
43 # if (__GLIBC__ >= 2 && !defined __UCLIBC__) || (defined __linux__ && HAVE_LANGINFO_H) || defined __CYGWIN__
44 # include <langinfo.h>
46 # if !defined IN_LIBINTL
47 # include "glthread/lock.h"
50 # if HAVE_GETLOCALENAME_L
52 extern char * getlocalename_l(int, locale_t
);
53 # elif HAVE_SOLARIS114_LOCALES
54 # include <sys/localedef.h>
57 # if HAVE_NAMELESS_LOCALES
59 # include "localename-table.h"
63 #if HAVE_CFLOCALECOPYCURRENT || HAVE_CFPREFERENCESCOPYAPPVALUE
64 # include <CoreFoundation/CFString.h>
65 # if HAVE_CFLOCALECOPYCURRENT
66 # include <CoreFoundation/CFLocale.h>
67 # elif HAVE_CFPREFERENCESCOPYAPPVALUE
68 # include <CoreFoundation/CFPreferences.h>
72 #if defined _WIN32 && !defined __CYGWIN__
73 # define WINDOWS_NATIVE
74 # if !defined IN_LIBINTL
75 # include "glthread/lock.h"
79 #if defined WINDOWS_NATIVE || defined __CYGWIN__ /* Native Windows or Cygwin */
80 # define WIN32_LEAN_AND_MEAN
83 /* List of language codes, sorted by value:
109 0x1a LANG_CROATIAN == LANG_SERBIAN
191 0x6e LANG_LUXEMBOURGISH
192 0x6f LANG_GREENLANDIC
211 0x87 LANG_KINYARWANDA
214 0x91 LANG_SCOTTISH_GAELIC
216 /* Mingw headers don't have latest language and sublanguage codes. */
217 # ifndef LANG_AFRIKAANS
218 # define LANG_AFRIKAANS 0x36
220 # ifndef LANG_ALBANIAN
221 # define LANG_ALBANIAN 0x1c
223 # ifndef LANG_ALSATIAN
224 # define LANG_ALSATIAN 0x84
226 # ifndef LANG_AMHARIC
227 # define LANG_AMHARIC 0x5e
230 # define LANG_ARABIC 0x01
232 # ifndef LANG_ARMENIAN
233 # define LANG_ARMENIAN 0x2b
235 # ifndef LANG_ASSAMESE
236 # define LANG_ASSAMESE 0x4d
239 # define LANG_AZERI 0x2c
241 # ifndef LANG_BASHKIR
242 # define LANG_BASHKIR 0x6d
245 # define LANG_BASQUE 0x2d
247 # ifndef LANG_BELARUSIAN
248 # define LANG_BELARUSIAN 0x23
250 # ifndef LANG_BENGALI
251 # define LANG_BENGALI 0x45
254 # define LANG_BRETON 0x7e
256 # ifndef LANG_BURMESE
257 # define LANG_BURMESE 0x55
259 # ifndef LANG_CAMBODIAN
260 # define LANG_CAMBODIAN 0x53
262 # ifndef LANG_CATALAN
263 # define LANG_CATALAN 0x03
265 # ifndef LANG_CHEROKEE
266 # define LANG_CHEROKEE 0x5c
268 # ifndef LANG_CORSICAN
269 # define LANG_CORSICAN 0x83
272 # define LANG_DARI 0x8c
275 # define LANG_DIVEHI 0x65
278 # define LANG_EDO 0x66
280 # ifndef LANG_ESTONIAN
281 # define LANG_ESTONIAN 0x25
283 # ifndef LANG_FAEROESE
284 # define LANG_FAEROESE 0x38
287 # define LANG_FARSI 0x29
289 # ifndef LANG_FRISIAN
290 # define LANG_FRISIAN 0x62
292 # ifndef LANG_FULFULDE
293 # define LANG_FULFULDE 0x67
296 # define LANG_GAELIC 0x3c
298 # ifndef LANG_GALICIAN
299 # define LANG_GALICIAN 0x56
301 # ifndef LANG_GEORGIAN
302 # define LANG_GEORGIAN 0x37
304 # ifndef LANG_GREENLANDIC
305 # define LANG_GREENLANDIC 0x6f
307 # ifndef LANG_GUARANI
308 # define LANG_GUARANI 0x74
310 # ifndef LANG_GUJARATI
311 # define LANG_GUJARATI 0x47
314 # define LANG_HAUSA 0x68
316 # ifndef LANG_HAWAIIAN
317 # define LANG_HAWAIIAN 0x75
320 # define LANG_HEBREW 0x0d
323 # define LANG_HINDI 0x39
326 # define LANG_IBIBIO 0x69
329 # define LANG_IGBO 0x70
331 # ifndef LANG_INDONESIAN
332 # define LANG_INDONESIAN 0x21
334 # ifndef LANG_INUKTITUT
335 # define LANG_INUKTITUT 0x5d
337 # ifndef LANG_KANNADA
338 # define LANG_KANNADA 0x4b
341 # define LANG_KANURI 0x71
343 # ifndef LANG_KASHMIRI
344 # define LANG_KASHMIRI 0x60
347 # define LANG_KAZAK 0x3f
350 # define LANG_KICHE 0x86
352 # ifndef LANG_KINYARWANDA
353 # define LANG_KINYARWANDA 0x87
355 # ifndef LANG_KONKANI
356 # define LANG_KONKANI 0x57
359 # define LANG_KYRGYZ 0x40
362 # define LANG_LAO 0x54
365 # define LANG_LATIN 0x76
367 # ifndef LANG_LATVIAN
368 # define LANG_LATVIAN 0x26
370 # ifndef LANG_LITHUANIAN
371 # define LANG_LITHUANIAN 0x27
373 # ifndef LANG_LUXEMBOURGISH
374 # define LANG_LUXEMBOURGISH 0x6e
376 # ifndef LANG_MACEDONIAN
377 # define LANG_MACEDONIAN 0x2f
380 # define LANG_MALAY 0x3e
382 # ifndef LANG_MALAYALAM
383 # define LANG_MALAYALAM 0x4c
385 # ifndef LANG_MALTESE
386 # define LANG_MALTESE 0x3a
388 # ifndef LANG_MANIPURI
389 # define LANG_MANIPURI 0x58
392 # define LANG_MAORI 0x81
394 # ifndef LANG_MAPUDUNGUN
395 # define LANG_MAPUDUNGUN 0x7a
397 # ifndef LANG_MARATHI
398 # define LANG_MARATHI 0x4e
401 # define LANG_MOHAWK 0x7c
403 # ifndef LANG_MONGOLIAN
404 # define LANG_MONGOLIAN 0x50
407 # define LANG_NEPALI 0x61
409 # ifndef LANG_OCCITAN
410 # define LANG_OCCITAN 0x82
413 # define LANG_ORIYA 0x48
416 # define LANG_OROMO 0x72
418 # ifndef LANG_PAPIAMENTU
419 # define LANG_PAPIAMENTU 0x79
422 # define LANG_PASHTO 0x63
424 # ifndef LANG_PUNJABI
425 # define LANG_PUNJABI 0x46
427 # ifndef LANG_QUECHUA
428 # define LANG_QUECHUA 0x6b
430 # ifndef LANG_ROMANSH
431 # define LANG_ROMANSH 0x17
434 # define LANG_SAMI 0x3b
436 # ifndef LANG_SANSKRIT
437 # define LANG_SANSKRIT 0x4f
439 # ifndef LANG_SCOTTISH_GAELIC
440 # define LANG_SCOTTISH_GAELIC 0x91
442 # ifndef LANG_SERBIAN
443 # define LANG_SERBIAN 0x1a
446 # define LANG_SINDHI 0x59
448 # ifndef LANG_SINHALESE
449 # define LANG_SINHALESE 0x5b
452 # define LANG_SLOVAK 0x1b
455 # define LANG_SOMALI 0x77
457 # ifndef LANG_SORBIAN
458 # define LANG_SORBIAN 0x2e
461 # define LANG_SOTHO 0x6c
464 # define LANG_SUTU 0x30
466 # ifndef LANG_SWAHILI
467 # define LANG_SWAHILI 0x41
470 # define LANG_SYRIAC 0x5a
472 # ifndef LANG_TAGALOG
473 # define LANG_TAGALOG 0x64
476 # define LANG_TAJIK 0x28
478 # ifndef LANG_TAMAZIGHT
479 # define LANG_TAMAZIGHT 0x5f
482 # define LANG_TAMIL 0x49
485 # define LANG_TATAR 0x44
488 # define LANG_TELUGU 0x4a
491 # define LANG_THAI 0x1e
493 # ifndef LANG_TIBETAN
494 # define LANG_TIBETAN 0x51
496 # ifndef LANG_TIGRINYA
497 # define LANG_TIGRINYA 0x73
500 # define LANG_TSONGA 0x31
503 # define LANG_TSWANA 0x32
505 # ifndef LANG_TURKMEN
506 # define LANG_TURKMEN 0x42
509 # define LANG_UIGHUR 0x80
511 # ifndef LANG_UKRAINIAN
512 # define LANG_UKRAINIAN 0x22
515 # define LANG_URDU 0x20
518 # define LANG_UZBEK 0x43
521 # define LANG_VENDA 0x33
523 # ifndef LANG_VIETNAMESE
524 # define LANG_VIETNAMESE 0x2a
527 # define LANG_WELSH 0x52
530 # define LANG_WOLOF 0x88
533 # define LANG_XHOSA 0x34
536 # define LANG_YAKUT 0x85
539 # define LANG_YI 0x78
541 # ifndef LANG_YIDDISH
542 # define LANG_YIDDISH 0x3d
545 # define LANG_YORUBA 0x6a
548 # define LANG_ZULU 0x35
550 # ifndef SUBLANG_AFRIKAANS_SOUTH_AFRICA
551 # define SUBLANG_AFRIKAANS_SOUTH_AFRICA 0x01
553 # ifndef SUBLANG_ALBANIAN_ALBANIA
554 # define SUBLANG_ALBANIAN_ALBANIA 0x01
556 # ifndef SUBLANG_ALSATIAN_FRANCE
557 # define SUBLANG_ALSATIAN_FRANCE 0x01
559 # ifndef SUBLANG_AMHARIC_ETHIOPIA
560 # define SUBLANG_AMHARIC_ETHIOPIA 0x01
562 # ifndef SUBLANG_ARABIC_SAUDI_ARABIA
563 # define SUBLANG_ARABIC_SAUDI_ARABIA 0x01
565 # ifndef SUBLANG_ARABIC_IRAQ
566 # define SUBLANG_ARABIC_IRAQ 0x02
568 # ifndef SUBLANG_ARABIC_EGYPT
569 # define SUBLANG_ARABIC_EGYPT 0x03
571 # ifndef SUBLANG_ARABIC_LIBYA
572 # define SUBLANG_ARABIC_LIBYA 0x04
574 # ifndef SUBLANG_ARABIC_ALGERIA
575 # define SUBLANG_ARABIC_ALGERIA 0x05
577 # ifndef SUBLANG_ARABIC_MOROCCO
578 # define SUBLANG_ARABIC_MOROCCO 0x06
580 # ifndef SUBLANG_ARABIC_TUNISIA
581 # define SUBLANG_ARABIC_TUNISIA 0x07
583 # ifndef SUBLANG_ARABIC_OMAN
584 # define SUBLANG_ARABIC_OMAN 0x08
586 # ifndef SUBLANG_ARABIC_YEMEN
587 # define SUBLANG_ARABIC_YEMEN 0x09
589 # ifndef SUBLANG_ARABIC_SYRIA
590 # define SUBLANG_ARABIC_SYRIA 0x0a
592 # ifndef SUBLANG_ARABIC_JORDAN
593 # define SUBLANG_ARABIC_JORDAN 0x0b
595 # ifndef SUBLANG_ARABIC_LEBANON
596 # define SUBLANG_ARABIC_LEBANON 0x0c
598 # ifndef SUBLANG_ARABIC_KUWAIT
599 # define SUBLANG_ARABIC_KUWAIT 0x0d
601 # ifndef SUBLANG_ARABIC_UAE
602 # define SUBLANG_ARABIC_UAE 0x0e
604 # ifndef SUBLANG_ARABIC_BAHRAIN
605 # define SUBLANG_ARABIC_BAHRAIN 0x0f
607 # ifndef SUBLANG_ARABIC_QATAR
608 # define SUBLANG_ARABIC_QATAR 0x10
610 # ifndef SUBLANG_ARMENIAN_ARMENIA
611 # define SUBLANG_ARMENIAN_ARMENIA 0x01
613 # ifndef SUBLANG_ASSAMESE_INDIA
614 # define SUBLANG_ASSAMESE_INDIA 0x01
616 # ifndef SUBLANG_AZERI_LATIN
617 # define SUBLANG_AZERI_LATIN 0x01
619 # ifndef SUBLANG_AZERI_CYRILLIC
620 # define SUBLANG_AZERI_CYRILLIC 0x02
622 # ifndef SUBLANG_BASHKIR_RUSSIA
623 # define SUBLANG_BASHKIR_RUSSIA 0x01
625 # ifndef SUBLANG_BASQUE_BASQUE
626 # define SUBLANG_BASQUE_BASQUE 0x01
628 # ifndef SUBLANG_BELARUSIAN_BELARUS
629 # define SUBLANG_BELARUSIAN_BELARUS 0x01
631 # ifndef SUBLANG_BENGALI_INDIA
632 # define SUBLANG_BENGALI_INDIA 0x01
634 # ifndef SUBLANG_BENGALI_BANGLADESH
635 # define SUBLANG_BENGALI_BANGLADESH 0x02
637 # ifndef SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN
638 # define SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN 0x05
640 # ifndef SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC
641 # define SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC 0x08
643 # ifndef SUBLANG_BRETON_FRANCE
644 # define SUBLANG_BRETON_FRANCE 0x01
646 # ifndef SUBLANG_BULGARIAN_BULGARIA
647 # define SUBLANG_BULGARIAN_BULGARIA 0x01
649 # ifndef SUBLANG_CAMBODIAN_CAMBODIA
650 # define SUBLANG_CAMBODIAN_CAMBODIA 0x01
652 # ifndef SUBLANG_CATALAN_SPAIN
653 # define SUBLANG_CATALAN_SPAIN 0x01
655 # ifndef SUBLANG_CORSICAN_FRANCE
656 # define SUBLANG_CORSICAN_FRANCE 0x01
658 # ifndef SUBLANG_CROATIAN_CROATIA
659 # define SUBLANG_CROATIAN_CROATIA 0x01
661 # ifndef SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN
662 # define SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN 0x04
664 # ifndef SUBLANG_CHINESE_MACAU
665 # define SUBLANG_CHINESE_MACAU 0x05
667 # ifndef SUBLANG_CZECH_CZECH_REPUBLIC
668 # define SUBLANG_CZECH_CZECH_REPUBLIC 0x01
670 # ifndef SUBLANG_DANISH_DENMARK
671 # define SUBLANG_DANISH_DENMARK 0x01
673 # ifndef SUBLANG_DARI_AFGHANISTAN
674 # define SUBLANG_DARI_AFGHANISTAN 0x01
676 # ifndef SUBLANG_DIVEHI_MALDIVES
677 # define SUBLANG_DIVEHI_MALDIVES 0x01
679 # ifndef SUBLANG_DUTCH_SURINAM
680 # define SUBLANG_DUTCH_SURINAM 0x03
682 # ifndef SUBLANG_ENGLISH_SOUTH_AFRICA
683 # define SUBLANG_ENGLISH_SOUTH_AFRICA 0x07
685 # ifndef SUBLANG_ENGLISH_JAMAICA
686 # define SUBLANG_ENGLISH_JAMAICA 0x08
688 # ifndef SUBLANG_ENGLISH_CARIBBEAN
689 # define SUBLANG_ENGLISH_CARIBBEAN 0x09
691 # ifndef SUBLANG_ENGLISH_BELIZE
692 # define SUBLANG_ENGLISH_BELIZE 0x0a
694 # ifndef SUBLANG_ENGLISH_TRINIDAD
695 # define SUBLANG_ENGLISH_TRINIDAD 0x0b
697 # ifndef SUBLANG_ENGLISH_ZIMBABWE
698 # define SUBLANG_ENGLISH_ZIMBABWE 0x0c
700 # ifndef SUBLANG_ENGLISH_PHILIPPINES
701 # define SUBLANG_ENGLISH_PHILIPPINES 0x0d
703 # ifndef SUBLANG_ENGLISH_INDONESIA
704 # define SUBLANG_ENGLISH_INDONESIA 0x0e
706 # ifndef SUBLANG_ENGLISH_HONGKONG
707 # define SUBLANG_ENGLISH_HONGKONG 0x0f
709 # ifndef SUBLANG_ENGLISH_INDIA
710 # define SUBLANG_ENGLISH_INDIA 0x10
712 # ifndef SUBLANG_ENGLISH_MALAYSIA
713 # define SUBLANG_ENGLISH_MALAYSIA 0x11
715 # ifndef SUBLANG_ENGLISH_SINGAPORE
716 # define SUBLANG_ENGLISH_SINGAPORE 0x12
718 # ifndef SUBLANG_ESTONIAN_ESTONIA
719 # define SUBLANG_ESTONIAN_ESTONIA 0x01
721 # ifndef SUBLANG_FAEROESE_FAROE_ISLANDS
722 # define SUBLANG_FAEROESE_FAROE_ISLANDS 0x01
724 # ifndef SUBLANG_FARSI_IRAN
725 # define SUBLANG_FARSI_IRAN 0x01
727 # ifndef SUBLANG_FINNISH_FINLAND
728 # define SUBLANG_FINNISH_FINLAND 0x01
730 # ifndef SUBLANG_FRENCH_LUXEMBOURG
731 # define SUBLANG_FRENCH_LUXEMBOURG 0x05
733 # ifndef SUBLANG_FRENCH_MONACO
734 # define SUBLANG_FRENCH_MONACO 0x06
736 # ifndef SUBLANG_FRENCH_WESTINDIES
737 # define SUBLANG_FRENCH_WESTINDIES 0x07
739 # ifndef SUBLANG_FRENCH_REUNION
740 # define SUBLANG_FRENCH_REUNION 0x08
742 # ifndef SUBLANG_FRENCH_CONGO
743 # define SUBLANG_FRENCH_CONGO 0x09
745 # ifndef SUBLANG_FRENCH_SENEGAL
746 # define SUBLANG_FRENCH_SENEGAL 0x0a
748 # ifndef SUBLANG_FRENCH_CAMEROON
749 # define SUBLANG_FRENCH_CAMEROON 0x0b
751 # ifndef SUBLANG_FRENCH_COTEDIVOIRE
752 # define SUBLANG_FRENCH_COTEDIVOIRE 0x0c
754 # ifndef SUBLANG_FRENCH_MALI
755 # define SUBLANG_FRENCH_MALI 0x0d
757 # ifndef SUBLANG_FRENCH_MOROCCO
758 # define SUBLANG_FRENCH_MOROCCO 0x0e
760 # ifndef SUBLANG_FRENCH_HAITI
761 # define SUBLANG_FRENCH_HAITI 0x0f
763 # ifndef SUBLANG_FRISIAN_NETHERLANDS
764 # define SUBLANG_FRISIAN_NETHERLANDS 0x01
766 # ifndef SUBLANG_GALICIAN_SPAIN
767 # define SUBLANG_GALICIAN_SPAIN 0x01
769 # ifndef SUBLANG_GEORGIAN_GEORGIA
770 # define SUBLANG_GEORGIAN_GEORGIA 0x01
772 # ifndef SUBLANG_GERMAN_LUXEMBOURG
773 # define SUBLANG_GERMAN_LUXEMBOURG 0x04
775 # ifndef SUBLANG_GERMAN_LIECHTENSTEIN
776 # define SUBLANG_GERMAN_LIECHTENSTEIN 0x05
778 # ifndef SUBLANG_GREEK_GREECE
779 # define SUBLANG_GREEK_GREECE 0x01
781 # ifndef SUBLANG_GREENLANDIC_GREENLAND
782 # define SUBLANG_GREENLANDIC_GREENLAND 0x01
784 # ifndef SUBLANG_GUJARATI_INDIA
785 # define SUBLANG_GUJARATI_INDIA 0x01
787 # ifndef SUBLANG_HAUSA_NIGERIA_LATIN
788 # define SUBLANG_HAUSA_NIGERIA_LATIN 0x01
790 # ifndef SUBLANG_HEBREW_ISRAEL
791 # define SUBLANG_HEBREW_ISRAEL 0x01
793 # ifndef SUBLANG_HINDI_INDIA
794 # define SUBLANG_HINDI_INDIA 0x01
796 # ifndef SUBLANG_HUNGARIAN_HUNGARY
797 # define SUBLANG_HUNGARIAN_HUNGARY 0x01
799 # ifndef SUBLANG_ICELANDIC_ICELAND
800 # define SUBLANG_ICELANDIC_ICELAND 0x01
802 # ifndef SUBLANG_IGBO_NIGERIA
803 # define SUBLANG_IGBO_NIGERIA 0x01
805 # ifndef SUBLANG_INDONESIAN_INDONESIA
806 # define SUBLANG_INDONESIAN_INDONESIA 0x01
808 # ifndef SUBLANG_INUKTITUT_CANADA
809 # define SUBLANG_INUKTITUT_CANADA 0x01
811 # undef SUBLANG_INUKTITUT_CANADA_LATIN
812 # define SUBLANG_INUKTITUT_CANADA_LATIN 0x02
813 # undef SUBLANG_IRISH_IRELAND
814 # define SUBLANG_IRISH_IRELAND 0x02
815 # ifndef SUBLANG_JAPANESE_JAPAN
816 # define SUBLANG_JAPANESE_JAPAN 0x01
818 # ifndef SUBLANG_KANNADA_INDIA
819 # define SUBLANG_KANNADA_INDIA 0x01
821 # ifndef SUBLANG_KASHMIRI_INDIA
822 # define SUBLANG_KASHMIRI_INDIA 0x02
824 # ifndef SUBLANG_KAZAK_KAZAKHSTAN
825 # define SUBLANG_KAZAK_KAZAKHSTAN 0x01
827 # ifndef SUBLANG_KICHE_GUATEMALA
828 # define SUBLANG_KICHE_GUATEMALA 0x01
830 # ifndef SUBLANG_KINYARWANDA_RWANDA
831 # define SUBLANG_KINYARWANDA_RWANDA 0x01
833 # ifndef SUBLANG_KONKANI_INDIA
834 # define SUBLANG_KONKANI_INDIA 0x01
836 # ifndef SUBLANG_KYRGYZ_KYRGYZSTAN
837 # define SUBLANG_KYRGYZ_KYRGYZSTAN 0x01
839 # ifndef SUBLANG_LAO_LAOS
840 # define SUBLANG_LAO_LAOS 0x01
842 # ifndef SUBLANG_LATVIAN_LATVIA
843 # define SUBLANG_LATVIAN_LATVIA 0x01
845 # ifndef SUBLANG_LITHUANIAN_LITHUANIA
846 # define SUBLANG_LITHUANIAN_LITHUANIA 0x01
848 # undef SUBLANG_LOWER_SORBIAN_GERMANY
849 # define SUBLANG_LOWER_SORBIAN_GERMANY 0x02
850 # ifndef SUBLANG_LUXEMBOURGISH_LUXEMBOURG
851 # define SUBLANG_LUXEMBOURGISH_LUXEMBOURG 0x01
853 # ifndef SUBLANG_MACEDONIAN_MACEDONIA
854 # define SUBLANG_MACEDONIAN_MACEDONIA 0x01
856 # ifndef SUBLANG_MALAY_MALAYSIA
857 # define SUBLANG_MALAY_MALAYSIA 0x01
859 # ifndef SUBLANG_MALAY_BRUNEI_DARUSSALAM
860 # define SUBLANG_MALAY_BRUNEI_DARUSSALAM 0x02
862 # ifndef SUBLANG_MALAYALAM_INDIA
863 # define SUBLANG_MALAYALAM_INDIA 0x01
865 # ifndef SUBLANG_MALTESE_MALTA
866 # define SUBLANG_MALTESE_MALTA 0x01
868 # ifndef SUBLANG_MAORI_NEW_ZEALAND
869 # define SUBLANG_MAORI_NEW_ZEALAND 0x01
871 # ifndef SUBLANG_MAPUDUNGUN_CHILE
872 # define SUBLANG_MAPUDUNGUN_CHILE 0x01
874 # ifndef SUBLANG_MARATHI_INDIA
875 # define SUBLANG_MARATHI_INDIA 0x01
877 # ifndef SUBLANG_MOHAWK_CANADA
878 # define SUBLANG_MOHAWK_CANADA 0x01
880 # ifndef SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA
881 # define SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA 0x01
883 # ifndef SUBLANG_MONGOLIAN_PRC
884 # define SUBLANG_MONGOLIAN_PRC 0x02
886 # ifndef SUBLANG_NEPALI_NEPAL
887 # define SUBLANG_NEPALI_NEPAL 0x01
889 # ifndef SUBLANG_NEPALI_INDIA
890 # define SUBLANG_NEPALI_INDIA 0x02
892 # ifndef SUBLANG_OCCITAN_FRANCE
893 # define SUBLANG_OCCITAN_FRANCE 0x01
895 # ifndef SUBLANG_ORIYA_INDIA
896 # define SUBLANG_ORIYA_INDIA 0x01
898 # ifndef SUBLANG_PASHTO_AFGHANISTAN
899 # define SUBLANG_PASHTO_AFGHANISTAN 0x01
901 # ifndef SUBLANG_POLISH_POLAND
902 # define SUBLANG_POLISH_POLAND 0x01
904 # ifndef SUBLANG_PUNJABI_INDIA
905 # define SUBLANG_PUNJABI_INDIA 0x01
907 # ifndef SUBLANG_PUNJABI_PAKISTAN
908 # define SUBLANG_PUNJABI_PAKISTAN 0x02
910 # ifndef SUBLANG_QUECHUA_BOLIVIA
911 # define SUBLANG_QUECHUA_BOLIVIA 0x01
913 # ifndef SUBLANG_QUECHUA_ECUADOR
914 # define SUBLANG_QUECHUA_ECUADOR 0x02
916 # ifndef SUBLANG_QUECHUA_PERU
917 # define SUBLANG_QUECHUA_PERU 0x03
919 # ifndef SUBLANG_ROMANIAN_ROMANIA
920 # define SUBLANG_ROMANIAN_ROMANIA 0x01
922 # ifndef SUBLANG_ROMANIAN_MOLDOVA
923 # define SUBLANG_ROMANIAN_MOLDOVA 0x02
925 # ifndef SUBLANG_ROMANSH_SWITZERLAND
926 # define SUBLANG_ROMANSH_SWITZERLAND 0x01
928 # ifndef SUBLANG_RUSSIAN_RUSSIA
929 # define SUBLANG_RUSSIAN_RUSSIA 0x01
931 # ifndef SUBLANG_RUSSIAN_MOLDAVIA
932 # define SUBLANG_RUSSIAN_MOLDAVIA 0x02
934 # ifndef SUBLANG_SAMI_NORTHERN_NORWAY
935 # define SUBLANG_SAMI_NORTHERN_NORWAY 0x01
937 # ifndef SUBLANG_SAMI_NORTHERN_SWEDEN
938 # define SUBLANG_SAMI_NORTHERN_SWEDEN 0x02
940 # ifndef SUBLANG_SAMI_NORTHERN_FINLAND
941 # define SUBLANG_SAMI_NORTHERN_FINLAND 0x03
943 # ifndef SUBLANG_SAMI_LULE_NORWAY
944 # define SUBLANG_SAMI_LULE_NORWAY 0x04
946 # ifndef SUBLANG_SAMI_LULE_SWEDEN
947 # define SUBLANG_SAMI_LULE_SWEDEN 0x05
949 # ifndef SUBLANG_SAMI_SOUTHERN_NORWAY
950 # define SUBLANG_SAMI_SOUTHERN_NORWAY 0x06
952 # ifndef SUBLANG_SAMI_SOUTHERN_SWEDEN
953 # define SUBLANG_SAMI_SOUTHERN_SWEDEN 0x07
955 # undef SUBLANG_SAMI_SKOLT_FINLAND
956 # define SUBLANG_SAMI_SKOLT_FINLAND 0x08
957 # undef SUBLANG_SAMI_INARI_FINLAND
958 # define SUBLANG_SAMI_INARI_FINLAND 0x09
959 # ifndef SUBLANG_SANSKRIT_INDIA
960 # define SUBLANG_SANSKRIT_INDIA 0x01
962 # ifndef SUBLANG_SERBIAN_LATIN
963 # define SUBLANG_SERBIAN_LATIN 0x02
965 # ifndef SUBLANG_SERBIAN_CYRILLIC
966 # define SUBLANG_SERBIAN_CYRILLIC 0x03
968 # ifndef SUBLANG_SINDHI_INDIA
969 # define SUBLANG_SINDHI_INDIA 0x01
971 # undef SUBLANG_SINDHI_PAKISTAN
972 # define SUBLANG_SINDHI_PAKISTAN 0x02
973 # ifndef SUBLANG_SINDHI_AFGHANISTAN
974 # define SUBLANG_SINDHI_AFGHANISTAN 0x02
976 # ifndef SUBLANG_SINHALESE_SRI_LANKA
977 # define SUBLANG_SINHALESE_SRI_LANKA 0x01
979 # ifndef SUBLANG_SLOVAK_SLOVAKIA
980 # define SUBLANG_SLOVAK_SLOVAKIA 0x01
982 # ifndef SUBLANG_SLOVENIAN_SLOVENIA
983 # define SUBLANG_SLOVENIAN_SLOVENIA 0x01
985 # ifndef SUBLANG_SOTHO_SOUTH_AFRICA
986 # define SUBLANG_SOTHO_SOUTH_AFRICA 0x01
988 # ifndef SUBLANG_SPANISH_GUATEMALA
989 # define SUBLANG_SPANISH_GUATEMALA 0x04
991 # ifndef SUBLANG_SPANISH_COSTA_RICA
992 # define SUBLANG_SPANISH_COSTA_RICA 0x05
994 # ifndef SUBLANG_SPANISH_PANAMA
995 # define SUBLANG_SPANISH_PANAMA 0x06
997 # ifndef SUBLANG_SPANISH_DOMINICAN_REPUBLIC
998 # define SUBLANG_SPANISH_DOMINICAN_REPUBLIC 0x07
1000 # ifndef SUBLANG_SPANISH_VENEZUELA
1001 # define SUBLANG_SPANISH_VENEZUELA 0x08
1003 # ifndef SUBLANG_SPANISH_COLOMBIA
1004 # define SUBLANG_SPANISH_COLOMBIA 0x09
1006 # ifndef SUBLANG_SPANISH_PERU
1007 # define SUBLANG_SPANISH_PERU 0x0a
1009 # ifndef SUBLANG_SPANISH_ARGENTINA
1010 # define SUBLANG_SPANISH_ARGENTINA 0x0b
1012 # ifndef SUBLANG_SPANISH_ECUADOR
1013 # define SUBLANG_SPANISH_ECUADOR 0x0c
1015 # ifndef SUBLANG_SPANISH_CHILE
1016 # define SUBLANG_SPANISH_CHILE 0x0d
1018 # ifndef SUBLANG_SPANISH_URUGUAY
1019 # define SUBLANG_SPANISH_URUGUAY 0x0e
1021 # ifndef SUBLANG_SPANISH_PARAGUAY
1022 # define SUBLANG_SPANISH_PARAGUAY 0x0f
1024 # ifndef SUBLANG_SPANISH_BOLIVIA
1025 # define SUBLANG_SPANISH_BOLIVIA 0x10
1027 # ifndef SUBLANG_SPANISH_EL_SALVADOR
1028 # define SUBLANG_SPANISH_EL_SALVADOR 0x11
1030 # ifndef SUBLANG_SPANISH_HONDURAS
1031 # define SUBLANG_SPANISH_HONDURAS 0x12
1033 # ifndef SUBLANG_SPANISH_NICARAGUA
1034 # define SUBLANG_SPANISH_NICARAGUA 0x13
1036 # ifndef SUBLANG_SPANISH_PUERTO_RICO
1037 # define SUBLANG_SPANISH_PUERTO_RICO 0x14
1039 # ifndef SUBLANG_SPANISH_US
1040 # define SUBLANG_SPANISH_US 0x15
1042 # ifndef SUBLANG_SWAHILI_KENYA
1043 # define SUBLANG_SWAHILI_KENYA 0x01
1045 # ifndef SUBLANG_SWEDISH_SWEDEN
1046 # define SUBLANG_SWEDISH_SWEDEN 0x01
1048 # ifndef SUBLANG_SWEDISH_FINLAND
1049 # define SUBLANG_SWEDISH_FINLAND 0x02
1051 # ifndef SUBLANG_SYRIAC_SYRIA
1052 # define SUBLANG_SYRIAC_SYRIA 0x01
1054 # ifndef SUBLANG_TAGALOG_PHILIPPINES
1055 # define SUBLANG_TAGALOG_PHILIPPINES 0x01
1057 # ifndef SUBLANG_TAJIK_TAJIKISTAN
1058 # define SUBLANG_TAJIK_TAJIKISTAN 0x01
1060 # ifndef SUBLANG_TAMAZIGHT_ARABIC
1061 # define SUBLANG_TAMAZIGHT_ARABIC 0x01
1063 # ifndef SUBLANG_TAMAZIGHT_ALGERIA_LATIN
1064 # define SUBLANG_TAMAZIGHT_ALGERIA_LATIN 0x02
1066 # ifndef SUBLANG_TAMIL_INDIA
1067 # define SUBLANG_TAMIL_INDIA 0x01
1069 # ifndef SUBLANG_TATAR_RUSSIA
1070 # define SUBLANG_TATAR_RUSSIA 0x01
1072 # ifndef SUBLANG_TELUGU_INDIA
1073 # define SUBLANG_TELUGU_INDIA 0x01
1075 # ifndef SUBLANG_THAI_THAILAND
1076 # define SUBLANG_THAI_THAILAND 0x01
1078 # ifndef SUBLANG_TIBETAN_PRC
1079 # define SUBLANG_TIBETAN_PRC 0x01
1081 # undef SUBLANG_TIBETAN_BHUTAN
1082 # define SUBLANG_TIBETAN_BHUTAN 0x02
1083 # ifndef SUBLANG_TIGRINYA_ETHIOPIA
1084 # define SUBLANG_TIGRINYA_ETHIOPIA 0x01
1086 # ifndef SUBLANG_TIGRINYA_ERITREA
1087 # define SUBLANG_TIGRINYA_ERITREA 0x02
1089 # ifndef SUBLANG_TSWANA_SOUTH_AFRICA
1090 # define SUBLANG_TSWANA_SOUTH_AFRICA 0x01
1092 # ifndef SUBLANG_TURKISH_TURKEY
1093 # define SUBLANG_TURKISH_TURKEY 0x01
1095 # ifndef SUBLANG_TURKMEN_TURKMENISTAN
1096 # define SUBLANG_TURKMEN_TURKMENISTAN 0x01
1098 # ifndef SUBLANG_UIGHUR_PRC
1099 # define SUBLANG_UIGHUR_PRC 0x01
1101 # ifndef SUBLANG_UKRAINIAN_UKRAINE
1102 # define SUBLANG_UKRAINIAN_UKRAINE 0x01
1104 # ifndef SUBLANG_UPPER_SORBIAN_GERMANY
1105 # define SUBLANG_UPPER_SORBIAN_GERMANY 0x01
1107 # ifndef SUBLANG_URDU_PAKISTAN
1108 # define SUBLANG_URDU_PAKISTAN 0x01
1110 # ifndef SUBLANG_URDU_INDIA
1111 # define SUBLANG_URDU_INDIA 0x02
1113 # ifndef SUBLANG_UZBEK_LATIN
1114 # define SUBLANG_UZBEK_LATIN 0x01
1116 # ifndef SUBLANG_UZBEK_CYRILLIC
1117 # define SUBLANG_UZBEK_CYRILLIC 0x02
1119 # ifndef SUBLANG_VIETNAMESE_VIETNAM
1120 # define SUBLANG_VIETNAMESE_VIETNAM 0x01
1122 # ifndef SUBLANG_WELSH_UNITED_KINGDOM
1123 # define SUBLANG_WELSH_UNITED_KINGDOM 0x01
1125 # ifndef SUBLANG_WOLOF_SENEGAL
1126 # define SUBLANG_WOLOF_SENEGAL 0x01
1128 # ifndef SUBLANG_XHOSA_SOUTH_AFRICA
1129 # define SUBLANG_XHOSA_SOUTH_AFRICA 0x01
1131 # ifndef SUBLANG_YAKUT_RUSSIA
1132 # define SUBLANG_YAKUT_RUSSIA 0x01
1134 # ifndef SUBLANG_YI_PRC
1135 # define SUBLANG_YI_PRC 0x01
1137 # ifndef SUBLANG_YORUBA_NIGERIA
1138 # define SUBLANG_YORUBA_NIGERIA 0x01
1140 # ifndef SUBLANG_ZULU_SOUTH_AFRICA
1141 # define SUBLANG_ZULU_SOUTH_AFRICA 0x01
1143 /* GetLocaleInfoA operations. */
1144 # ifndef LOCALE_SNAME
1145 # define LOCALE_SNAME 0x5c
1147 # ifndef LOCALE_NAME_MAX_LENGTH
1148 # define LOCALE_NAME_MAX_LENGTH 85
1153 #if HAVE_CFLOCALECOPYCURRENT || HAVE_CFPREFERENCESCOPYAPPVALUE
1154 /* Mac OS X 10.4 or newer */
1156 /* Canonicalize a Mac OS X locale name to a Unix locale name.
1157 NAME is a sufficiently large buffer.
1158 On input, it contains the Mac OS X locale name.
1159 On output, it contains the Unix locale name. */
1160 # if !defined IN_LIBINTL
1164 gl_locale_name_canonicalize (char *name
)
1166 /* This conversion is based on a posting by
1167 Deborah GoldSmith <goldsmit@apple.com> on 2005-03-08,
1168 https://lists.apple.com/archives/carbon-dev/2005/Mar/msg00293.html */
1170 /* Convert legacy (NeXTstep inherited) English names to Unix (ISO 639 and
1171 ISO 3166) names. Prior to Mac OS X 10.3, there is no API for doing this.
1172 Therefore we do it ourselves, using a table based on the results of the
1173 Mac OS X 10.3.8 function
1174 CFLocaleCreateCanonicalLocaleIdentifierFromString(). */
1175 typedef struct { const char legacy
[21+1]; const char unixy
[5+1]; }
1177 static const legacy_entry legacy_table
[] = {
1178 { "Afrikaans", "af" },
1179 { "Albanian", "sq" },
1180 { "Amharic", "am" },
1182 { "Armenian", "hy" },
1183 { "Assamese", "as" },
1185 { "Azerbaijani", "az" },
1187 { "Belarusian", "be" },
1188 { "Belorussian", "be" },
1189 { "Bengali", "bn" },
1190 { "Brazilian Portugese", "pt_BR" },
1191 { "Brazilian Portuguese", "pt_BR" },
1193 { "Bulgarian", "bg" },
1194 { "Burmese", "my" },
1195 { "Byelorussian", "be" },
1196 { "Catalan", "ca" },
1198 { "Chichewa", "ny" },
1199 { "Chinese", "zh" },
1200 { "Chinese, Simplified", "zh_CN" },
1201 { "Chinese, Traditional", "zh_TW" },
1202 { "Chinese, Tradtional", "zh_TW" },
1203 { "Croatian", "hr" },
1207 { "Dzongkha", "dz" },
1208 { "English", "en" },
1209 { "Esperanto", "eo" },
1210 { "Estonian", "et" },
1211 { "Faroese", "fo" },
1213 { "Finnish", "fi" },
1214 { "Flemish", "nl_BE" },
1216 { "Galician", "gl" },
1217 { "Gallegan", "gl" },
1218 { "Georgian", "ka" },
1221 { "Greenlandic", "kl" },
1222 { "Guarani", "gn" },
1223 { "Gujarati", "gu" },
1224 { "Hawaiian", "haw" }, /* Yes, "haw", not "cpe". */
1227 { "Hungarian", "hu" },
1228 { "Icelandic", "is" },
1229 { "Indonesian", "id" },
1230 { "Inuktitut", "iu" },
1232 { "Italian", "it" },
1233 { "Japanese", "ja" },
1234 { "Javanese", "jv" },
1235 { "Kalaallisut", "kl" },
1236 { "Kannada", "kn" },
1237 { "Kashmiri", "ks" },
1240 { "Kinyarwanda", "rw" },
1241 { "Kirghiz", "ky" },
1243 { "Kurdish", "ku" },
1245 { "Latvian", "lv" },
1246 { "Lithuanian", "lt" },
1247 { "Macedonian", "mk" },
1248 { "Malagasy", "mg" },
1250 { "Malayalam", "ml" },
1251 { "Maltese", "mt" },
1253 { "Marathi", "mr" },
1254 { "Moldavian", "mo" },
1255 { "Mongolian", "mn" },
1257 { "Norwegian", "nb" }, /* Yes, "nb", not the obsolete "no". */
1259 { "Nynorsk", "nn" },
1262 { "Panjabi", "pa" },
1264 { "Persian", "fa" },
1266 { "Portuguese", "pt" },
1267 { "Portuguese, Brazilian", "pt_BR" },
1268 { "Punjabi", "pa" },
1270 { "Quechua", "qu" },
1271 { "Romanian", "ro" },
1274 { "Russian", "ru" },
1275 { "Sami", "se_NO" }, /* Not just "se". */
1276 { "Sanskrit", "sa" },
1277 { "Scottish", "gd" },
1278 { "Serbian", "sr" },
1279 { "Simplified Chinese", "zh_CN" },
1281 { "Sinhalese", "si" },
1283 { "Slovenian", "sl" },
1285 { "Spanish", "es" },
1286 { "Sundanese", "su" },
1287 { "Swahili", "sw" },
1288 { "Swedish", "sv" },
1289 { "Tagalog", "tl" },
1296 { "Tibetan", "bo" },
1297 { "Tigrinya", "ti" },
1299 { "Traditional Chinese", "zh_TW" },
1300 { "Turkish", "tr" },
1301 { "Turkmen", "tk" },
1303 { "Ukrainian", "uk" },
1306 { "Vietnamese", "vi" },
1311 /* Convert new-style locale names with language tags (ISO 639 and ISO 15924)
1312 to Unix (ISO 639 and ISO 3166) names. */
1313 typedef struct { const char langtag
[7+1]; const char unixy
[12+1]; }
1315 static const langtag_entry langtag_table
[] = {
1316 /* Mac OS X has "az-Arab", "az-Cyrl", "az-Latn".
1317 The default script for az on Unix is Latin. */
1318 { "az-Latn", "az" },
1319 /* Mac OS X has "bs-Cyrl", "bs-Latn".
1320 The default script for bs on Unix is Latin. */
1321 { "bs-Latn", "bs" },
1322 /* Mac OS X has "ga-dots". Does not yet exist on Unix. */
1323 { "ga-dots", "ga" },
1324 /* Mac OS X has "kk-Cyrl".
1325 The default script for kk on Unix is Cyrillic. */
1326 { "kk-Cyrl", "kk" },
1327 /* Mac OS X has "mn-Cyrl", "mn-Mong".
1328 The default script for mn on Unix is Cyrillic. */
1329 { "mn-Cyrl", "mn" },
1330 /* Mac OS X has "ms-Arab", "ms-Latn".
1331 The default script for ms on Unix is Latin. */
1332 { "ms-Latn", "ms" },
1333 /* Mac OS X has "pa-Arab", "pa-Guru".
1334 Country codes are used to distinguish these on Unix. */
1335 { "pa-Arab", "pa_PK" },
1336 { "pa-Guru", "pa_IN" },
1337 /* Mac OS X has "shi-Latn", "shi-Tfng". Does not yet exist on Unix. */
1338 /* Mac OS X has "sr-Cyrl", "sr-Latn".
1339 The default script for sr on Unix is Cyrillic. */
1340 { "sr-Cyrl", "sr" },
1341 /* Mac OS X has "tg-Cyrl".
1342 The default script for tg on Unix is Cyrillic. */
1343 { "tg-Cyrl", "tg" },
1344 /* Mac OS X has "tk-Cyrl".
1345 The default script for tk on Unix is Cyrillic. */
1346 { "tk-Cyrl", "tk" },
1347 /* Mac OS X has "tt-Cyrl".
1348 The default script for tt on Unix is Cyrillic. */
1349 { "tt-Cyrl", "tt" },
1350 /* Mac OS X has "uz-Arab", "uz-Cyrl", "uz-Latn".
1351 The default script for uz on Unix is Latin. */
1352 { "uz-Latn", "uz" },
1353 /* Mac OS X has "vai-Latn", "vai-Vaii". Does not yet exist on Unix. */
1354 /* Mac OS X has "yue-Hans", "yue-Hant".
1355 The default script for yue on Unix is Simplified Han. */
1356 { "yue-Hans", "yue" },
1357 /* Mac OS X has "zh-Hans", "zh-Hant".
1358 Country codes are used to distinguish these on Unix. */
1359 { "zh-Hans", "zh_CN" },
1360 { "zh-Hant", "zh_TW" }
1363 /* Convert script names (ISO 15924) to Unix conventions.
1364 See https://www.unicode.org/iso15924/iso15924-codes.html */
1365 typedef struct { const char script
[4+1]; const char unixy
[9+1]; }
1367 static const script_entry script_table
[] = {
1368 { "Arab", "arabic" },
1369 { "Cyrl", "cyrillic" },
1370 { "Latn", "latin" },
1371 { "Mong", "mongolian" }
1374 /* Step 1: Convert using legacy_table. */
1375 if (name
[0] >= 'A' && name
[0] <= 'Z')
1377 unsigned int i1
, i2
;
1379 i2
= sizeof (legacy_table
) / sizeof (legacy_entry
);
1382 /* At this point we know that if name occurs in legacy_table,
1383 its index must be >= i1 and < i2. */
1384 unsigned int i
= (i1
+ i2
) >> 1;
1385 const legacy_entry
*p
= &legacy_table
[i
];
1386 if (strcmp (name
, p
->legacy
) < 0)
1391 if (strcmp (name
, legacy_table
[i1
].legacy
) == 0)
1393 strcpy (name
, legacy_table
[i1
].unixy
);
1398 /* Step 2: Convert using langtag_table and script_table. */
1399 if (strlen (name
) == 7 && name
[2] == '-')
1401 unsigned int i1
, i2
;
1403 i2
= sizeof (langtag_table
) / sizeof (langtag_entry
);
1406 /* At this point we know that if name occurs in langtag_table,
1407 its index must be >= i1 and < i2. */
1408 unsigned int i
= (i1
+ i2
) >> 1;
1409 const langtag_entry
*p
= &langtag_table
[i
];
1410 if (strcmp (name
, p
->langtag
) < 0)
1415 if (strcmp (name
, langtag_table
[i1
].langtag
) == 0)
1417 strcpy (name
, langtag_table
[i1
].unixy
);
1422 i2
= sizeof (script_table
) / sizeof (script_entry
);
1425 /* At this point we know that if (name + 3) occurs in script_table,
1426 its index must be >= i1 and < i2. */
1427 unsigned int i
= (i1
+ i2
) >> 1;
1428 const script_entry
*p
= &script_table
[i
];
1429 if (strcmp (name
+ 3, p
->script
) < 0)
1434 if (strcmp (name
+ 3, script_table
[i1
].script
) == 0)
1437 strcpy (name
+ 3, script_table
[i1
].unixy
);
1442 /* Step 3: Convert new-style dash to Unix underscore. */
1445 for (p
= name
; *p
!= '\0'; p
++)
1454 #if defined WINDOWS_NATIVE || defined __CYGWIN__ /* Native Windows or Cygwin */
1456 /* Canonicalize a Windows native locale name to a Unix locale name.
1457 NAME is a sufficiently large buffer.
1458 On input, it contains the Windows locale name.
1459 On output, it contains the Unix locale name. */
1460 # if !defined IN_LIBINTL
1464 gl_locale_name_canonicalize (char *name
)
1466 /* FIXME: This is probably incomplete: it does not handle "zh-Hans" and
1470 for (p
= name
; *p
!= '\0'; p
++)
1475 for (; *p
!= '\0'; p
++)
1477 if (*p
>= 'a' && *p
<= 'z')
1489 # if !defined IN_LIBINTL
1493 gl_locale_name_from_win32_LANGID (LANGID langid
)
1495 /* Activate the new code only when the GETTEXT_MUI environment variable is
1496 set, for the time being, since the new code is not well tested. */
1497 if (getenv ("GETTEXT_MUI") != NULL
)
1499 static char namebuf
[256];
1501 /* Query the system's notion of locale name.
1502 On Windows95/98/ME, GetLocaleInfoA returns some incorrect results.
1503 But we don't need to support systems that are so old. */
1504 if (GetLocaleInfoA (MAKELCID (langid
, SORT_DEFAULT
), LOCALE_SNAME
,
1505 namebuf
, sizeof (namebuf
) - 1))
1507 /* Convert it to a Unix locale name. */
1508 gl_locale_name_canonicalize (namebuf
);
1512 /* Internet Explorer has an LCID to RFC3066 name mapping stored in
1513 HKEY_CLASSES_ROOT\Mime\Database\Rfc1766. But we better don't use that
1514 since IE's i18n subsystem is known to be inconsistent with the native
1515 Windows base (e.g. they have different character conversion facilities
1516 that produce different results). */
1517 /* Use our own table. */
1521 /* Split into language and territory part. */
1522 primary
= PRIMARYLANGID (langid
);
1523 sub
= SUBLANGID (langid
);
1525 /* Dispatch on language.
1526 See also https://www.unicode.org/unicode/onlinedat/languages.html .
1527 For details about languages, see https://www.ethnologue.com/ . */
1530 case LANG_AFRIKAANS
:
1533 case SUBLANG_AFRIKAANS_SOUTH_AFRICA
: return "af_ZA";
1539 case SUBLANG_ALBANIAN_ALBANIA
: return "sq_AL";
1545 case SUBLANG_ALSATIAN_FRANCE
: return "gsw_FR";
1551 case SUBLANG_AMHARIC_ETHIOPIA
: return "am_ET";
1557 case SUBLANG_ARABIC_SAUDI_ARABIA
: return "ar_SA";
1558 case SUBLANG_ARABIC_IRAQ
: return "ar_IQ";
1559 case SUBLANG_ARABIC_EGYPT
: return "ar_EG";
1560 case SUBLANG_ARABIC_LIBYA
: return "ar_LY";
1561 case SUBLANG_ARABIC_ALGERIA
: return "ar_DZ";
1562 case SUBLANG_ARABIC_MOROCCO
: return "ar_MA";
1563 case SUBLANG_ARABIC_TUNISIA
: return "ar_TN";
1564 case SUBLANG_ARABIC_OMAN
: return "ar_OM";
1565 case SUBLANG_ARABIC_YEMEN
: return "ar_YE";
1566 case SUBLANG_ARABIC_SYRIA
: return "ar_SY";
1567 case SUBLANG_ARABIC_JORDAN
: return "ar_JO";
1568 case SUBLANG_ARABIC_LEBANON
: return "ar_LB";
1569 case SUBLANG_ARABIC_KUWAIT
: return "ar_KW";
1570 case SUBLANG_ARABIC_UAE
: return "ar_AE";
1571 case SUBLANG_ARABIC_BAHRAIN
: return "ar_BH";
1572 case SUBLANG_ARABIC_QATAR
: return "ar_QA";
1578 case SUBLANG_ARMENIAN_ARMENIA
: return "hy_AM";
1584 case SUBLANG_ASSAMESE_INDIA
: return "as_IN";
1590 /* FIXME: Adjust this when Azerbaijani locales appear on Unix. */
1591 case 0x1e: return "az@latin";
1592 case SUBLANG_AZERI_LATIN
: return "az_AZ@latin";
1593 case 0x1d: return "az@cyrillic";
1594 case SUBLANG_AZERI_CYRILLIC
: return "az_AZ@cyrillic";
1600 case SUBLANG_BASHKIR_RUSSIA
: return "ba_RU";
1606 case SUBLANG_BASQUE_BASQUE
: return "eu_ES";
1608 return "eu"; /* Ambiguous: could be "eu_ES" or "eu_FR". */
1609 case LANG_BELARUSIAN
:
1612 case SUBLANG_BELARUSIAN_BELARUS
: return "be_BY";
1618 case SUBLANG_BENGALI_INDIA
: return "bn_IN";
1619 case SUBLANG_BENGALI_BANGLADESH
: return "bn_BD";
1625 case SUBLANG_BRETON_FRANCE
: return "br_FR";
1628 case LANG_BULGARIAN
:
1631 case SUBLANG_BULGARIAN_BULGARIA
: return "bg_BG";
1637 case SUBLANG_DEFAULT
: return "my_MM";
1640 case LANG_CAMBODIAN
:
1643 case SUBLANG_CAMBODIAN_CAMBODIA
: return "km_KH";
1649 case SUBLANG_CATALAN_SPAIN
: return "ca_ES";
1655 case SUBLANG_DEFAULT
: return "chr_US";
1661 case SUBLANG_CHINESE_TRADITIONAL
: case 0x1f: return "zh_TW";
1662 case SUBLANG_CHINESE_SIMPLIFIED
: case 0x00: return "zh_CN";
1663 case SUBLANG_CHINESE_HONGKONG
: return "zh_HK"; /* traditional */
1664 case SUBLANG_CHINESE_SINGAPORE
: return "zh_SG"; /* simplified */
1665 case SUBLANG_CHINESE_MACAU
: return "zh_MO"; /* traditional */
1671 case SUBLANG_CORSICAN_FRANCE
: return "co_FR";
1674 case LANG_CROATIAN
: /* LANG_CROATIAN == LANG_SERBIAN == LANG_BOSNIAN
1675 * What used to be called Serbo-Croatian
1676 * should really now be two separate
1677 * languages because of political reasons.
1678 * (Says tml, who knows nothing about Serbian
1680 * (I can feel those flames coming already.)
1685 case 0x00: return "hr";
1686 case SUBLANG_CROATIAN_CROATIA
: return "hr_HR";
1687 case SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN
: return "hr_BA";
1689 case 0x1f: return "sr";
1690 case 0x1c: return "sr"; /* latin */
1691 case SUBLANG_SERBIAN_LATIN
: return "sr_CS"; /* latin */
1692 case 0x09: return "sr_RS"; /* latin */
1693 case 0x0b: return "sr_ME"; /* latin */
1694 case 0x06: return "sr_BA"; /* latin */
1695 case 0x1b: return "sr@cyrillic";
1696 case SUBLANG_SERBIAN_CYRILLIC
: return "sr_CS@cyrillic";
1697 case 0x0a: return "sr_RS@cyrillic";
1698 case 0x0c: return "sr_ME@cyrillic";
1699 case 0x07: return "sr_BA@cyrillic";
1701 case 0x1e: return "bs";
1702 case 0x1a: return "bs"; /* latin */
1703 case SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN
: return "bs_BA"; /* latin */
1704 case 0x19: return "bs@cyrillic";
1705 case SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC
: return "bs_BA@cyrillic";
1711 case SUBLANG_CZECH_CZECH_REPUBLIC
: return "cs_CZ";
1717 case SUBLANG_DANISH_DENMARK
: return "da_DK";
1721 /* FIXME: Adjust this when such locales appear on Unix. */
1724 case SUBLANG_DARI_AFGHANISTAN
: return "prs_AF";
1730 case SUBLANG_DIVEHI_MALDIVES
: return "dv_MV";
1736 case SUBLANG_DUTCH
: return "nl_NL";
1737 case SUBLANG_DUTCH_BELGIAN
: /* FLEMISH, VLAAMS */ return "nl_BE";
1738 case SUBLANG_DUTCH_SURINAM
: return "nl_SR";
1744 case SUBLANG_DEFAULT
: return "bin_NG";
1750 /* SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. Heh. I thought
1751 * English was the language spoken in England.
1754 case SUBLANG_ENGLISH_US
: return "en_US";
1755 case SUBLANG_ENGLISH_UK
: return "en_GB";
1756 case SUBLANG_ENGLISH_AUS
: return "en_AU";
1757 case SUBLANG_ENGLISH_CAN
: return "en_CA";
1758 case SUBLANG_ENGLISH_NZ
: return "en_NZ";
1759 case SUBLANG_ENGLISH_EIRE
: return "en_IE";
1760 case SUBLANG_ENGLISH_SOUTH_AFRICA
: return "en_ZA";
1761 case SUBLANG_ENGLISH_JAMAICA
: return "en_JM";
1762 case SUBLANG_ENGLISH_CARIBBEAN
: return "en_GD"; /* Grenada? */
1763 case SUBLANG_ENGLISH_BELIZE
: return "en_BZ";
1764 case SUBLANG_ENGLISH_TRINIDAD
: return "en_TT";
1765 case SUBLANG_ENGLISH_ZIMBABWE
: return "en_ZW";
1766 case SUBLANG_ENGLISH_PHILIPPINES
: return "en_PH";
1767 case SUBLANG_ENGLISH_INDONESIA
: return "en_ID";
1768 case SUBLANG_ENGLISH_HONGKONG
: return "en_HK";
1769 case SUBLANG_ENGLISH_INDIA
: return "en_IN";
1770 case SUBLANG_ENGLISH_MALAYSIA
: return "en_MY";
1771 case SUBLANG_ENGLISH_SINGAPORE
: return "en_SG";
1777 case SUBLANG_ESTONIAN_ESTONIA
: return "et_EE";
1783 case SUBLANG_FAEROESE_FAROE_ISLANDS
: return "fo_FO";
1789 case SUBLANG_FARSI_IRAN
: return "fa_IR";
1795 case SUBLANG_FINNISH_FINLAND
: return "fi_FI";
1801 case SUBLANG_FRENCH
: return "fr_FR";
1802 case SUBLANG_FRENCH_BELGIAN
: /* WALLOON */ return "fr_BE";
1803 case SUBLANG_FRENCH_CANADIAN
: return "fr_CA";
1804 case SUBLANG_FRENCH_SWISS
: return "fr_CH";
1805 case SUBLANG_FRENCH_LUXEMBOURG
: return "fr_LU";
1806 case SUBLANG_FRENCH_MONACO
: return "fr_MC";
1807 case SUBLANG_FRENCH_WESTINDIES
: return "fr"; /* Caribbean? */
1808 case SUBLANG_FRENCH_REUNION
: return "fr_RE";
1809 case SUBLANG_FRENCH_CONGO
: return "fr_CG";
1810 case SUBLANG_FRENCH_SENEGAL
: return "fr_SN";
1811 case SUBLANG_FRENCH_CAMEROON
: return "fr_CM";
1812 case SUBLANG_FRENCH_COTEDIVOIRE
: return "fr_CI";
1813 case SUBLANG_FRENCH_MALI
: return "fr_ML";
1814 case SUBLANG_FRENCH_MOROCCO
: return "fr_MA";
1815 case SUBLANG_FRENCH_HAITI
: return "fr_HT";
1821 case SUBLANG_FRISIAN_NETHERLANDS
: return "fy_NL";
1825 /* Spoken in Nigeria, Guinea, Senegal, Mali, Niger, Cameroon, Benin. */
1828 case SUBLANG_DEFAULT
: return "ff_NG";
1834 case 0x01: /* SCOTTISH */
1835 /* old, superseded by LANG_SCOTTISH_GAELIC */
1837 case SUBLANG_IRISH_IRELAND
: return "ga_IE";
1843 case SUBLANG_GALICIAN_SPAIN
: return "gl_ES";
1849 case SUBLANG_GEORGIAN_GEORGIA
: return "ka_GE";
1855 case SUBLANG_GERMAN
: return "de_DE";
1856 case SUBLANG_GERMAN_SWISS
: return "de_CH";
1857 case SUBLANG_GERMAN_AUSTRIAN
: return "de_AT";
1858 case SUBLANG_GERMAN_LUXEMBOURG
: return "de_LU";
1859 case SUBLANG_GERMAN_LIECHTENSTEIN
: return "de_LI";
1865 case SUBLANG_GREEK_GREECE
: return "el_GR";
1868 case LANG_GREENLANDIC
:
1871 case SUBLANG_GREENLANDIC_GREENLAND
: return "kl_GL";
1877 case SUBLANG_DEFAULT
: return "gn_PY";
1883 case SUBLANG_GUJARATI_INDIA
: return "gu_IN";
1889 case 0x1f: return "ha";
1890 case SUBLANG_HAUSA_NIGERIA_LATIN
: return "ha_NG";
1894 /* FIXME: Do they mean Hawaiian ("haw_US", 1000 speakers)
1895 or Hawaii Creole English ("cpe_US", 600000 speakers)? */
1898 case SUBLANG_DEFAULT
: return "cpe_US";
1904 case SUBLANG_HEBREW_ISRAEL
: return "he_IL";
1910 case SUBLANG_HINDI_INDIA
: return "hi_IN";
1913 case LANG_HUNGARIAN
:
1916 case SUBLANG_HUNGARIAN_HUNGARY
: return "hu_HU";
1922 case SUBLANG_DEFAULT
: return "nic_NG";
1925 case LANG_ICELANDIC
:
1928 case SUBLANG_ICELANDIC_ICELAND
: return "is_IS";
1934 case SUBLANG_IGBO_NIGERIA
: return "ig_NG";
1937 case LANG_INDONESIAN
:
1940 case SUBLANG_INDONESIAN_INDONESIA
: return "id_ID";
1943 case LANG_INUKTITUT
:
1946 case 0x1e: return "iu"; /* syllabic */
1947 case SUBLANG_INUKTITUT_CANADA
: return "iu_CA"; /* syllabic */
1948 case 0x1f: return "iu@latin";
1949 case SUBLANG_INUKTITUT_CANADA_LATIN
: return "iu_CA@latin";
1955 case SUBLANG_ITALIAN
: return "it_IT";
1956 case SUBLANG_ITALIAN_SWISS
: return "it_CH";
1962 case SUBLANG_JAPANESE_JAPAN
: return "ja_JP";
1968 case SUBLANG_KANNADA_INDIA
: return "kn_IN";
1974 case SUBLANG_DEFAULT
: return "kr_NG";
1980 case SUBLANG_DEFAULT
: return "ks_PK";
1981 case SUBLANG_KASHMIRI_INDIA
: return "ks_IN";
1987 case SUBLANG_KAZAK_KAZAKHSTAN
: return "kk_KZ";
1991 /* FIXME: Adjust this when such locales appear on Unix. */
1994 case SUBLANG_KICHE_GUATEMALA
: return "qut_GT";
1997 case LANG_KINYARWANDA
:
2000 case SUBLANG_KINYARWANDA_RWANDA
: return "rw_RW";
2004 /* FIXME: Adjust this when such locales appear on Unix. */
2007 case SUBLANG_KONKANI_INDIA
: return "kok_IN";
2013 case SUBLANG_DEFAULT
: return "ko_KR";
2019 case SUBLANG_KYRGYZ_KYRGYZSTAN
: return "ky_KG";
2025 case SUBLANG_LAO_LAOS
: return "lo_LA";
2031 case SUBLANG_DEFAULT
: return "la_VA";
2037 case SUBLANG_LATVIAN_LATVIA
: return "lv_LV";
2040 case LANG_LITHUANIAN
:
2043 case SUBLANG_LITHUANIAN_LITHUANIA
: return "lt_LT";
2046 case LANG_LUXEMBOURGISH
:
2049 case SUBLANG_LUXEMBOURGISH_LUXEMBOURG
: return "lb_LU";
2052 case LANG_MACEDONIAN
:
2055 case SUBLANG_MACEDONIAN_MACEDONIA
: return "mk_MK";
2061 case SUBLANG_MALAY_MALAYSIA
: return "ms_MY";
2062 case SUBLANG_MALAY_BRUNEI_DARUSSALAM
: return "ms_BN";
2065 case LANG_MALAYALAM
:
2068 case SUBLANG_MALAYALAM_INDIA
: return "ml_IN";
2074 case SUBLANG_MALTESE_MALTA
: return "mt_MT";
2078 /* FIXME: Adjust this when such locales appear on Unix. */
2081 case SUBLANG_DEFAULT
: return "mni_IN";
2087 case SUBLANG_MAORI_NEW_ZEALAND
: return "mi_NZ";
2090 case LANG_MAPUDUNGUN
:
2093 case SUBLANG_MAPUDUNGUN_CHILE
: return "arn_CL";
2099 case SUBLANG_MARATHI_INDIA
: return "mr_IN";
2105 case SUBLANG_MOHAWK_CANADA
: return "moh_CA";
2108 case LANG_MONGOLIAN
:
2111 case SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA
: case 0x1e: return "mn_MN";
2112 case SUBLANG_MONGOLIAN_PRC
: case 0x1f: return "mn_CN";
2114 return "mn"; /* Ambiguous: could be "mn_CN" or "mn_MN". */
2118 case SUBLANG_NEPALI_NEPAL
: return "ne_NP";
2119 case SUBLANG_NEPALI_INDIA
: return "ne_IN";
2122 case LANG_NORWEGIAN
:
2125 case 0x1f: return "nb";
2126 case SUBLANG_NORWEGIAN_BOKMAL
: return "nb_NO";
2127 case 0x1e: return "nn";
2128 case SUBLANG_NORWEGIAN_NYNORSK
: return "nn_NO";
2134 case SUBLANG_OCCITAN_FRANCE
: return "oc_FR";
2140 case SUBLANG_ORIYA_INDIA
: return "or_IN";
2146 case SUBLANG_DEFAULT
: return "om_ET";
2149 case LANG_PAPIAMENTU
:
2152 case SUBLANG_DEFAULT
: return "pap_AN";
2158 case SUBLANG_PASHTO_AFGHANISTAN
: return "ps_AF";
2160 return "ps"; /* Ambiguous: could be "ps_PK" or "ps_AF". */
2164 case SUBLANG_POLISH_POLAND
: return "pl_PL";
2167 case LANG_PORTUGUESE
:
2170 /* Hmm. SUBLANG_PORTUGUESE_BRAZILIAN == SUBLANG_DEFAULT.
2171 Same phenomenon as SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. */
2172 case SUBLANG_PORTUGUESE_BRAZILIAN
: return "pt_BR";
2173 case SUBLANG_PORTUGUESE
: return "pt_PT";
2179 case SUBLANG_PUNJABI_INDIA
: return "pa_IN"; /* Gurmukhi script */
2180 case SUBLANG_PUNJABI_PAKISTAN
: return "pa_PK"; /* Arabic script */
2184 /* Note: Microsoft uses the non-ISO language code "quz". */
2187 case SUBLANG_QUECHUA_BOLIVIA
: return "qu_BO";
2188 case SUBLANG_QUECHUA_ECUADOR
: return "qu_EC";
2189 case SUBLANG_QUECHUA_PERU
: return "qu_PE";
2195 case SUBLANG_ROMANIAN_ROMANIA
: return "ro_RO";
2196 case SUBLANG_ROMANIAN_MOLDOVA
: return "ro_MD";
2202 case SUBLANG_ROMANSH_SWITZERLAND
: return "rm_CH";
2208 case SUBLANG_RUSSIAN_RUSSIA
: return "ru_RU";
2209 case SUBLANG_RUSSIAN_MOLDAVIA
: return "ru_MD";
2211 return "ru"; /* Ambiguous: could be "ru_RU" or "ru_UA" or "ru_MD". */
2216 case 0x00: return "se";
2217 case SUBLANG_SAMI_NORTHERN_NORWAY
: return "se_NO";
2218 case SUBLANG_SAMI_NORTHERN_SWEDEN
: return "se_SE";
2219 case SUBLANG_SAMI_NORTHERN_FINLAND
: return "se_FI";
2221 case 0x1f: return "smj";
2222 case SUBLANG_SAMI_LULE_NORWAY
: return "smj_NO";
2223 case SUBLANG_SAMI_LULE_SWEDEN
: return "smj_SE";
2225 case 0x1e: return "sma";
2226 case SUBLANG_SAMI_SOUTHERN_NORWAY
: return "sma_NO";
2227 case SUBLANG_SAMI_SOUTHERN_SWEDEN
: return "sma_SE";
2229 case 0x1d: return "sms";
2230 case SUBLANG_SAMI_SKOLT_FINLAND
: return "sms_FI";
2232 case 0x1c: return "smn";
2233 case SUBLANG_SAMI_INARI_FINLAND
: return "smn_FI";
2235 return "se"; /* or "smi"? */
2239 case SUBLANG_SANSKRIT_INDIA
: return "sa_IN";
2242 case LANG_SCOTTISH_GAELIC
:
2245 case SUBLANG_DEFAULT
: return "gd_GB";
2251 case SUBLANG_SINDHI_INDIA
: return "sd_IN";
2252 case SUBLANG_SINDHI_PAKISTAN
: return "sd_PK";
2253 /*case SUBLANG_SINDHI_AFGHANISTAN: return "sd_AF";*/
2256 case LANG_SINHALESE
:
2259 case SUBLANG_SINHALESE_SRI_LANKA
: return "si_LK";
2265 case SUBLANG_SLOVAK_SLOVAKIA
: return "sk_SK";
2268 case LANG_SLOVENIAN
:
2271 case SUBLANG_SLOVENIAN_SLOVENIA
: return "sl_SI";
2277 case SUBLANG_DEFAULT
: return "so_SO";
2281 /* FIXME: Adjust this when such locales appear on Unix. */
2285 case 0x00: return "hsb";
2286 case SUBLANG_UPPER_SORBIAN_GERMANY
: return "hsb_DE";
2288 case 0x1f: return "dsb";
2289 case SUBLANG_LOWER_SORBIAN_GERMANY
: return "dsb_DE";
2293 /* <https://msdn.microsoft.com/en-us/library/dd318693.aspx> calls
2294 it "Sesotho sa Leboa"; according to
2295 <https://www.ethnologue.com/show_language.asp?code=nso>
2296 <https://www.ethnologue.com/show_language.asp?code=sot>
2297 it's the same as Northern Sotho. */
2300 case SUBLANG_SOTHO_SOUTH_AFRICA
: return "nso_ZA";
2306 case SUBLANG_SPANISH
: return "es_ES";
2307 case SUBLANG_SPANISH_MEXICAN
: return "es_MX";
2308 case SUBLANG_SPANISH_MODERN
:
2309 return "es_ES@modern"; /* not seen on Unix */
2310 case SUBLANG_SPANISH_GUATEMALA
: return "es_GT";
2311 case SUBLANG_SPANISH_COSTA_RICA
: return "es_CR";
2312 case SUBLANG_SPANISH_PANAMA
: return "es_PA";
2313 case SUBLANG_SPANISH_DOMINICAN_REPUBLIC
: return "es_DO";
2314 case SUBLANG_SPANISH_VENEZUELA
: return "es_VE";
2315 case SUBLANG_SPANISH_COLOMBIA
: return "es_CO";
2316 case SUBLANG_SPANISH_PERU
: return "es_PE";
2317 case SUBLANG_SPANISH_ARGENTINA
: return "es_AR";
2318 case SUBLANG_SPANISH_ECUADOR
: return "es_EC";
2319 case SUBLANG_SPANISH_CHILE
: return "es_CL";
2320 case SUBLANG_SPANISH_URUGUAY
: return "es_UY";
2321 case SUBLANG_SPANISH_PARAGUAY
: return "es_PY";
2322 case SUBLANG_SPANISH_BOLIVIA
: return "es_BO";
2323 case SUBLANG_SPANISH_EL_SALVADOR
: return "es_SV";
2324 case SUBLANG_SPANISH_HONDURAS
: return "es_HN";
2325 case SUBLANG_SPANISH_NICARAGUA
: return "es_NI";
2326 case SUBLANG_SPANISH_PUERTO_RICO
: return "es_PR";
2327 case SUBLANG_SPANISH_US
: return "es_US";
2333 case SUBLANG_DEFAULT
: return "bnt_TZ"; /* or "st_LS" or "nso_ZA"? */
2339 case SUBLANG_SWAHILI_KENYA
: return "sw_KE";
2345 case SUBLANG_SWEDISH_SWEDEN
: return "sv_SE";
2346 case SUBLANG_SWEDISH_FINLAND
: return "sv_FI";
2352 case SUBLANG_SYRIAC_SYRIA
: return "syr_SY"; /* An extinct language. */
2358 case SUBLANG_TAGALOG_PHILIPPINES
: return "tl_PH"; /* or "fil_PH"? */
2360 return "tl"; /* or "fil"? */
2364 case 0x1f: return "tg";
2365 case SUBLANG_TAJIK_TAJIKISTAN
: return "tg_TJ";
2368 case LANG_TAMAZIGHT
:
2369 /* Note: Microsoft uses the non-ISO language code "tmz". */
2372 /* FIXME: Adjust this when Tamazight locales appear on Unix. */
2373 case SUBLANG_TAMAZIGHT_ARABIC
: return "ber_MA@arabic";
2374 case 0x1f: return "ber@latin";
2375 case SUBLANG_TAMAZIGHT_ALGERIA_LATIN
: return "ber_DZ@latin";
2381 case SUBLANG_TAMIL_INDIA
: return "ta_IN";
2383 return "ta"; /* Ambiguous: could be "ta_IN" or "ta_LK" or "ta_SG". */
2387 case SUBLANG_TATAR_RUSSIA
: return "tt_RU";
2393 case SUBLANG_TELUGU_INDIA
: return "te_IN";
2399 case SUBLANG_THAI_THAILAND
: return "th_TH";
2405 case SUBLANG_TIBETAN_PRC
:
2406 /* Most Tibetans would not like "bo_CN". But Tibet does not yet
2407 have a country code of its own. */
2409 case SUBLANG_TIBETAN_BHUTAN
: return "bo_BT";
2415 case SUBLANG_TIGRINYA_ETHIOPIA
: return "ti_ET";
2416 case SUBLANG_TIGRINYA_ERITREA
: return "ti_ER";
2422 case SUBLANG_DEFAULT
: return "ts_ZA";
2426 /* Spoken in South Africa, Botswana. */
2429 case SUBLANG_TSWANA_SOUTH_AFRICA
: return "tn_ZA";
2435 case SUBLANG_TURKISH_TURKEY
: return "tr_TR";
2441 case SUBLANG_TURKMEN_TURKMENISTAN
: return "tk_TM";
2447 case SUBLANG_UIGHUR_PRC
: return "ug_CN";
2450 case LANG_UKRAINIAN
:
2453 case SUBLANG_UKRAINIAN_UKRAINE
: return "uk_UA";
2459 case SUBLANG_URDU_PAKISTAN
: return "ur_PK";
2460 case SUBLANG_URDU_INDIA
: return "ur_IN";
2466 case 0x1f: return "uz";
2467 case SUBLANG_UZBEK_LATIN
: return "uz_UZ";
2468 case 0x1e: return "uz@cyrillic";
2469 case SUBLANG_UZBEK_CYRILLIC
: return "uz_UZ@cyrillic";
2475 case SUBLANG_DEFAULT
: return "ve_ZA";
2478 case LANG_VIETNAMESE
:
2481 case SUBLANG_VIETNAMESE_VIETNAM
: return "vi_VN";
2487 case SUBLANG_WELSH_UNITED_KINGDOM
: return "cy_GB";
2493 case SUBLANG_WOLOF_SENEGAL
: return "wo_SN";
2499 case SUBLANG_XHOSA_SOUTH_AFRICA
: return "xh_ZA";
2505 case SUBLANG_YAKUT_RUSSIA
: return "sah_RU";
2511 case SUBLANG_YI_PRC
: return "ii_CN";
2517 case SUBLANG_DEFAULT
: return "yi_IL";
2523 case SUBLANG_YORUBA_NIGERIA
: return "yo_NG";
2529 case SUBLANG_ZULU_SOUTH_AFRICA
: return "zu_ZA";
2532 default: return "C";
2537 # if !defined IN_LIBINTL
2541 gl_locale_name_from_win32_LCID (LCID lcid
)
2545 /* Strip off the sorting rules, keep only the language part. */
2546 langid
= LANGIDFROMLCID (lcid
);
2548 return gl_locale_name_from_win32_LANGID (langid
);
2551 # ifdef WINDOWS_NATIVE
2553 /* Two variables to interface between get_lcid and the EnumLocales
2554 callback function below. */
2555 static LCID found_lcid
;
2556 static char lname
[LC_MAX
* (LOCALE_NAME_MAX_LENGTH
+ 1) + 1];
2558 /* Callback function for EnumLocales. */
2559 static BOOL CALLBACK
2560 enum_locales_fn (LPTSTR locale_num_str
)
2563 char locval
[2 * LOCALE_NAME_MAX_LENGTH
+ 1 + 1];
2564 LCID try_lcid
= strtoul (locale_num_str
, &endp
, 16);
2566 if (GetLocaleInfo (try_lcid
, LOCALE_SENGLANGUAGE
,
2567 locval
, LOCALE_NAME_MAX_LENGTH
))
2569 strcat (locval
, "_");
2570 if (GetLocaleInfo (try_lcid
, LOCALE_SENGCOUNTRY
,
2571 locval
+ strlen (locval
), LOCALE_NAME_MAX_LENGTH
))
2573 size_t locval_len
= strlen (locval
);
2575 if (strncmp (locval
, lname
, locval_len
) == 0
2576 && (lname
[locval_len
] == '.'
2577 || lname
[locval_len
] == '\0'))
2579 found_lcid
= try_lcid
;
2587 /* This lock protects the get_lcid against multiple simultaneous calls. */
2588 gl_lock_define_initialized(static, get_lcid_lock
)
2590 /* Return the Locale ID (LCID) number given the locale's name, a
2591 string, in LOCALE_NAME. This works by enumerating all the locales
2592 supported by the system, until we find one whose name matches
2595 get_lcid (const char *locale_name
)
2597 /* A simple cache. */
2598 static LCID last_lcid
;
2599 static char last_locale
[1000];
2601 /* Lock while looking for an LCID, to protect access to static
2602 variables: last_lcid, last_locale, found_lcid, and lname. */
2603 gl_lock_lock (get_lcid_lock
);
2604 if (last_lcid
> 0 && strcmp (locale_name
, last_locale
) == 0)
2606 gl_lock_unlock (get_lcid_lock
);
2609 strncpy (lname
, locale_name
, sizeof (lname
) - 1);
2610 lname
[sizeof (lname
) - 1] = '\0';
2612 EnumSystemLocales (enum_locales_fn
, LCID_SUPPORTED
);
2615 last_lcid
= found_lcid
;
2616 strcpy (last_locale
, locale_name
);
2618 gl_lock_unlock (get_lcid_lock
);
2626 #if HAVE_USELOCALE /* glibc, Mac OS X, Solaris 11 OpenIndiana, or Solaris >= 11.4 */
2628 /* Simple hash set of strings. We don't want to drag in lots of hash table
2631 # define SIZE_BITS (sizeof (size_t) * CHAR_BIT)
2633 /* A hash function for NUL-terminated char* strings using
2634 the method described by Bruno Haible.
2635 See https://www.haible.de/bruno/hashfunc.html. */
2636 static size_t _GL_ATTRIBUTE_PURE
2637 string_hash (const void *x
)
2639 const char *s
= (const char *) x
;
2643 h
= *s
+ ((h
<< 9) | (h
>> (SIZE_BITS
- 9)));
2648 /* A hash table of fixed size. Multiple threads can access it read-only
2649 simultaneously, but only one thread can insert into it at the same time. */
2651 /* A node in a hash bucket collision list. */
2652 struct struniq_hash_node
2654 struct struniq_hash_node
* volatile next
;
2655 char contents
[FLEXIBLE_ARRAY_MEMBER
];
2658 # define STRUNIQ_HASH_TABLE_SIZE 257
2659 static struct struniq_hash_node
* volatile struniq_hash_table
[STRUNIQ_HASH_TABLE_SIZE
]
2660 /* = { NULL, ..., NULL } */;
2662 /* This lock protects the struniq_hash_table against multiple simultaneous
2664 gl_lock_define_initialized(static, struniq_lock
)
2666 /* Store a copy of the given string in a string pool with indefinite extent.
2667 Return a pointer to this copy. */
2669 struniq (const char *string
)
2671 size_t hashcode
= string_hash (string
);
2672 size_t slot
= hashcode
% STRUNIQ_HASH_TABLE_SIZE
;
2674 struct struniq_hash_node
*new_node
;
2675 struct struniq_hash_node
*p
;
2676 for (p
= struniq_hash_table
[slot
]; p
!= NULL
; p
= p
->next
)
2677 if (strcmp (p
->contents
, string
) == 0)
2679 size
= strlen (string
) + 1;
2681 (struct struniq_hash_node
*)
2682 malloc (FLEXSIZEOF (struct struniq_hash_node
, contents
, size
));
2683 if (new_node
== NULL
)
2684 /* Out of memory. Return a statically allocated string. */
2686 memcpy (new_node
->contents
, string
, size
);
2687 /* Lock while inserting new_node. */
2688 gl_lock_lock (struniq_lock
);
2689 /* Check whether another thread already added the string while we were
2690 waiting on the lock. */
2691 for (p
= struniq_hash_table
[slot
]; p
!= NULL
; p
= p
->next
)
2692 if (strcmp (p
->contents
, string
) == 0)
2698 /* Really insert new_node into the hash table. Fill new_node entirely first,
2699 because other threads may be iterating over the linked list. */
2700 new_node
->next
= struniq_hash_table
[slot
];
2701 struniq_hash_table
[slot
] = new_node
;
2703 /* Unlock after new_node is inserted. */
2704 gl_lock_unlock (struniq_lock
);
2705 return new_node
->contents
;
2711 #if HAVE_USELOCALE && HAVE_NAMELESS_LOCALES
2713 /* The 'locale_t' object does not contain the names of the locale categories.
2714 We have to associate them with the object through a hash table.
2715 The hash table is defined in localename-table.[hc]. */
2717 /* Returns the name of a given locale category in a given locale_t object,
2718 allocated as a string with indefinite extent. */
2720 get_locale_t_name (int category
, locale_t locale
)
2722 if (locale
== LC_GLOBAL_LOCALE
)
2724 /* Query the global locale. */
2725 const char *name
= setlocale (category
, NULL
);
2727 return struniq (name
);
2729 /* Should normally not happen. */
2734 /* Look up the names in the hash table. */
2735 size_t hashcode
= locale_hash_function (locale
);
2736 size_t slot
= hashcode
% LOCALE_HASH_TABLE_SIZE
;
2737 /* If the locale was not found in the table, return "". This can
2738 happen if the application uses the original newlocale()/duplocale()
2739 functions instead of the overridden ones. */
2740 const char *name
= "";
2741 struct locale_hash_node
*p
;
2742 /* Lock while looking up the hash node. */
2743 gl_rwlock_rdlock (locale_lock
);
2744 for (p
= locale_hash_table
[slot
]; p
!= NULL
; p
= p
->next
)
2745 if (p
->locale
== locale
)
2747 name
= p
->names
.category_name
[category
];
2750 gl_rwlock_unlock (locale_lock
);
2755 # if !(defined newlocale && defined duplocale && defined freelocale)
2756 # error "newlocale, duplocale, freelocale not being replaced as expected!"
2759 /* newlocale() override. */
2761 newlocale (int category_mask
, const char *name
, locale_t base
)
2764 struct locale_categories_names names
;
2765 struct locale_hash_node
*node
;
2768 /* Make sure name has indefinite extent. */
2769 if (((LC_CTYPE_MASK
| LC_NUMERIC_MASK
| LC_TIME_MASK
| LC_COLLATE_MASK
2770 | LC_MONETARY_MASK
| LC_MESSAGES_MASK
)
2771 & category_mask
) != 0)
2772 name
= struniq (name
);
2774 /* Determine the category names of the result. */
2775 if (((LC_CTYPE_MASK
| LC_NUMERIC_MASK
| LC_TIME_MASK
| LC_COLLATE_MASK
2776 | LC_MONETARY_MASK
| LC_MESSAGES_MASK
)
2777 & ~category_mask
) == 0)
2779 /* Use name, ignore base. */
2782 name
= struniq (name
);
2783 for (category
= 0; category
< 6; category
++)
2784 names
.category_name
[category
] = name
;
2788 /* Use base, possibly also name. */
2793 for (category
= 0; category
< 6; category
++)
2800 mask
= LC_CTYPE_MASK
;
2803 mask
= LC_NUMERIC_MASK
;
2806 mask
= LC_TIME_MASK
;
2809 mask
= LC_COLLATE_MASK
;
2812 mask
= LC_MONETARY_MASK
;
2815 mask
= LC_MESSAGES_MASK
;
2820 names
.category_name
[category
] =
2821 ((mask
& category_mask
) != 0 ? name
: "C");
2824 else if (base
== LC_GLOBAL_LOCALE
)
2828 for (category
= 0; category
< 6; category
++)
2835 mask
= LC_CTYPE_MASK
;
2838 mask
= LC_NUMERIC_MASK
;
2841 mask
= LC_TIME_MASK
;
2844 mask
= LC_COLLATE_MASK
;
2847 mask
= LC_MONETARY_MASK
;
2850 mask
= LC_MESSAGES_MASK
;
2855 names
.category_name
[category
] =
2856 ((mask
& category_mask
) != 0
2858 : get_locale_t_name (category
, LC_GLOBAL_LOCALE
));
2863 /* Look up the names of base in the hash table. Like multiple calls
2864 of get_locale_t_name, but locking only once. */
2865 struct locale_hash_node
*p
;
2868 /* Lock while looking up the hash node. */
2869 gl_rwlock_rdlock (locale_lock
);
2870 for (p
= locale_hash_table
[locale_hash_function (base
) % LOCALE_HASH_TABLE_SIZE
];
2873 if (p
->locale
== base
)
2876 for (category
= 0; category
< 6; category
++)
2883 mask
= LC_CTYPE_MASK
;
2886 mask
= LC_NUMERIC_MASK
;
2889 mask
= LC_TIME_MASK
;
2892 mask
= LC_COLLATE_MASK
;
2895 mask
= LC_MONETARY_MASK
;
2898 mask
= LC_MESSAGES_MASK
;
2903 names
.category_name
[category
] =
2904 ((mask
& category_mask
) != 0
2906 : (p
!= NULL
? p
->names
.category_name
[category
] : ""));
2909 gl_rwlock_unlock (locale_lock
);
2913 node
= (struct locale_hash_node
*) malloc (sizeof (struct locale_hash_node
));
2915 /* errno is set to ENOMEM. */
2918 result
= newlocale (category_mask
, name
, base
);
2921 int saved_errno
= errno
;
2923 errno
= saved_errno
;
2927 /* Fill the hash node. */
2928 node
->locale
= result
;
2929 node
->names
= names
;
2931 /* Insert it in the hash table. */
2933 size_t hashcode
= locale_hash_function (result
);
2934 size_t slot
= hashcode
% LOCALE_HASH_TABLE_SIZE
;
2935 struct locale_hash_node
*p
;
2937 /* Lock while inserting the new node. */
2938 gl_rwlock_wrlock (locale_lock
);
2939 for (p
= locale_hash_table
[slot
]; p
!= NULL
; p
= p
->next
)
2940 if (p
->locale
== result
)
2942 /* This can happen if the application uses the original freelocale()
2943 function instead of the overridden one. */
2944 p
->names
= node
->names
;
2949 node
->next
= locale_hash_table
[slot
];
2950 locale_hash_table
[slot
] = node
;
2953 gl_rwlock_unlock (locale_lock
);
2962 /* duplocale() override. */
2964 duplocale (locale_t locale
)
2967 struct locale_hash_node
*node
;
2971 /* Invalid argument. */
2974 node
= (struct locale_hash_node
*) malloc (sizeof (struct locale_hash_node
));
2976 /* errno is set to ENOMEM. */
2979 result
= duplocale (locale
);
2982 int saved_errno
= errno
;
2984 errno
= saved_errno
;
2988 /* Fill the hash node. */
2989 node
->locale
= result
;
2990 if (locale
== LC_GLOBAL_LOCALE
)
2994 for (category
= 0; category
< 6; category
++)
2995 node
->names
.category_name
[category
] =
2996 get_locale_t_name (category
, LC_GLOBAL_LOCALE
);
2998 /* Lock before inserting the new node. */
2999 gl_rwlock_wrlock (locale_lock
);
3003 struct locale_hash_node
*p
;
3005 /* Lock once, for the lookup and the insertion. */
3006 gl_rwlock_wrlock (locale_lock
);
3008 for (p
= locale_hash_table
[locale_hash_function (locale
) % LOCALE_HASH_TABLE_SIZE
];
3011 if (p
->locale
== locale
)
3014 node
->names
= p
->names
;
3017 /* This can happen if the application uses the original
3018 newlocale()/duplocale() functions instead of the overridden
3022 for (category
= 0; category
< 6; category
++)
3023 node
->names
.category_name
[category
] = "";
3027 /* Insert it in the hash table. */
3029 size_t hashcode
= locale_hash_function (result
);
3030 size_t slot
= hashcode
% LOCALE_HASH_TABLE_SIZE
;
3031 struct locale_hash_node
*p
;
3033 for (p
= locale_hash_table
[slot
]; p
!= NULL
; p
= p
->next
)
3034 if (p
->locale
== result
)
3036 /* This can happen if the application uses the original freelocale()
3037 function instead of the overridden one. */
3038 p
->names
= node
->names
;
3043 node
->next
= locale_hash_table
[slot
];
3044 locale_hash_table
[slot
] = node
;
3047 gl_rwlock_unlock (locale_lock
);
3056 /* freelocale() override. */
3058 freelocale (locale_t locale
)
3061 if (locale
== NULL
|| locale
== LC_GLOBAL_LOCALE
)
3062 /* Invalid argument. */
3066 size_t hashcode
= locale_hash_function (locale
);
3067 size_t slot
= hashcode
% LOCALE_HASH_TABLE_SIZE
;
3068 struct locale_hash_node
*found
;
3069 struct locale_hash_node
**p
;
3072 /* Lock while removing the hash node. */
3073 gl_rwlock_wrlock (locale_lock
);
3074 for (p
= &locale_hash_table
[slot
]; *p
!= NULL
; p
= &(*p
)->next
)
3075 if ((*p
)->locale
== locale
)
3081 gl_rwlock_unlock (locale_lock
);
3085 freelocale (locale
);
3091 #if defined IN_LIBINTL || HAVE_USELOCALE
3093 /* Like gl_locale_name_thread, except that the result is not in storage of
3094 indefinite extent. */
3095 # if !defined IN_LIBINTL
3099 gl_locale_name_thread_unsafe (int category
, const char *categoryname
)
3103 locale_t thread_locale
= uselocale (NULL
);
3104 if (thread_locale
!= LC_GLOBAL_LOCALE
)
3106 # if __GLIBC__ >= 2 && !defined __UCLIBC__
3107 /* Work around an incorrect definition of the _NL_LOCALE_NAME macro in
3109 See <https://sourceware.org/bugzilla/show_bug.cgi?id=10968>. */
3111 nl_langinfo (_NL_ITEM ((category
), _NL_ITEM_INDEX (-1)));
3112 if (name
[0] == '\0')
3113 /* Fallback code for glibc < 2.4, which did not implement
3114 nl_langinfo (_NL_LOCALE_NAME (category)). */
3115 name
= thread_locale
->__names
[category
];
3117 # elif defined __linux__ && HAVE_LANGINFO_H && defined NL_LOCALE_NAME
3119 return nl_langinfo_l (NL_LOCALE_NAME (category
), thread_locale
);
3120 # elif (defined __FreeBSD__ || defined __DragonFly__) || (defined __APPLE__ && defined __MACH__)
3121 /* FreeBSD, Mac OS X */
3127 mask
= LC_CTYPE_MASK
;
3130 mask
= LC_NUMERIC_MASK
;
3133 mask
= LC_TIME_MASK
;
3136 mask
= LC_COLLATE_MASK
;
3139 mask
= LC_MONETARY_MASK
;
3142 mask
= LC_MESSAGES_MASK
;
3144 default: /* We shouldn't get here. */
3147 return querylocale (mask
, thread_locale
);
3148 # elif defined __sun
3149 # if HAVE_GETLOCALENAME_L
3150 /* Solaris >= 12. */
3151 return getlocalename_l (category
, thread_locale
);
3152 # elif HAVE_SOLARIS114_LOCALES
3153 /* Solaris >= 11.4. */
3154 void *lcp
= (*thread_locale
)->core
.data
->lcp
;
3164 return ((const char * const *) lcp
)[category
];
3165 default: /* We shouldn't get here. */
3168 # elif HAVE_NAMELESS_LOCALES
3169 return get_locale_t_name (category
, thread_locale
);
3171 /* Solaris 11 OpenIndiana.
3172 For the internal structure of locale objects, see
3173 https://github.com/OpenIndiana/illumos-gate/blob/master/usr/src/lib/libc/port/locale/localeimpl.h */
3182 return ((const char * const *) thread_locale
)[category
];
3183 default: /* We shouldn't get here. */
3187 # elif defined __CYGWIN__
3188 /* Cygwin < 2.6 lacks uselocale and thread-local locales altogether.
3189 Cygwin <= 2.6.1 lacks NL_LOCALE_NAME, requiring peeking inside
3190 an opaque struct. */
3191 # ifdef NL_LOCALE_NAME
3192 return nl_langinfo_l (NL_LOCALE_NAME (category
), thread_locale
);
3194 /* FIXME: Remove when we can assume new-enough Cygwin. */
3196 char categories
[7][32];
3198 return ((struct __locale_t
*) thread_locale
)->categories
[category
];
3200 # elif defined __ANDROID__
3201 return MB_CUR_MAX
== 4 ? "C.UTF-8" : "C";
3212 gl_locale_name_thread (int category
, const char *categoryname
)
3215 const char *name
= gl_locale_name_thread_unsafe (category
, categoryname
);
3217 return struniq (name
);
3219 /* On WINDOWS_NATIVE, don't use GetThreadLocale() here, because when
3220 SetThreadLocale has not been called - which is a very frequent case -
3221 the value of GetThreadLocale() ignores past calls to 'setlocale'. */
3225 /* XPG3 defines the result of 'setlocale (category, NULL)' as:
3226 "Directs 'setlocale()' to query 'category' and return the current
3227 setting of 'local'."
3228 However it does not specify the exact format. Neither do SUSV2 and
3229 ISO C 99. So we can use this feature only on selected systems (e.g.
3230 those using GNU C Library). */
3231 #if defined _LIBC || ((defined __GLIBC__ && __GLIBC__ >= 2) && !defined __UCLIBC__)
3232 # define HAVE_LOCALE_NULL
3236 gl_locale_name_posix (int category
, const char *categoryname
)
3238 #if defined WINDOWS_NATIVE
3239 if (LC_MIN
<= category
&& category
<= LC_MAX
)
3241 const char *locname
= setlocale (category
, NULL
);
3244 /* If CATEGORY is LC_ALL, the result might be a semi-colon
3245 separated list of locales. We need only one, so we take the
3246 one corresponding to LC_CTYPE, as the most important for
3247 character translations. */
3248 if (category
== LC_ALL
&& strchr (locname
, ';'))
3249 locname
= setlocale (LC_CTYPE
, NULL
);
3251 /* Convert locale name to LCID. We don't want to use
3252 LocaleNameToLCID because (a) it is only available since Vista,
3253 and (b) it doesn't accept locale names returned by 'setlocale'. */
3254 lcid
= get_lcid (locname
);
3257 return gl_locale_name_from_win32_LCID (lcid
);
3261 const char *locname
;
3263 /* Use the POSIX methods of looking to 'LC_ALL', 'LC_xxx', and 'LANG'.
3264 On some systems this can be done by the 'setlocale' function itself. */
3265 #if defined HAVE_SETLOCALE && defined HAVE_LC_MESSAGES && defined HAVE_LOCALE_NULL
3266 locname
= setlocale (category
, NULL
);
3268 /* On other systems we ignore what setlocale reports and instead look at the
3269 environment variables directly. This is necessary
3270 1. on systems which have a facility for customizing the default locale
3271 (Mac OS X, native Windows, Cygwin) and where the system's setlocale()
3272 function ignores this default locale (Mac OS X, Cygwin), in two cases:
3273 a. when the user missed to use the setlocale() override from libintl
3274 (for example by not including <libintl.h>),
3275 b. when setlocale supports only the "C" locale, such as on Cygwin
3276 1.5.x. In this case even the override from libintl cannot help.
3277 2. on all systems where setlocale supports only the "C" locale. */
3278 /* Strictly speaking, it is a POSIX violation to look at the environment
3279 variables regardless whether setlocale has been called or not. POSIX
3281 "For C-language programs, the POSIX locale shall be the
3282 default locale when the setlocale() function is not called."
3283 But we assume that all programs that use internationalized APIs call
3284 setlocale (LC_ALL, ""). */
3285 locname
= gl_locale_name_environ (category
, categoryname
);
3287 /* Convert the locale name from the format returned by setlocale() or found
3288 in the environment variables to the XPG syntax. */
3289 #if defined WINDOWS_NATIVE
3291 /* Convert locale name to LCID. We don't want to use
3292 LocaleNameToLCID because (a) it is only available since Vista,
3293 and (b) it doesn't accept locale names returned by 'setlocale'. */
3294 LCID lcid
= get_lcid (locname
);
3297 return gl_locale_name_from_win32_LCID (lcid
);
3305 gl_locale_name_environ (int category
, const char *categoryname
)
3309 /* Setting of LC_ALL overrides all other. */
3310 retval
= getenv ("LC_ALL");
3311 if (retval
!= NULL
&& retval
[0] != '\0')
3313 /* Next comes the name of the desired category. */
3314 retval
= getenv (categoryname
);
3315 if (retval
!= NULL
&& retval
[0] != '\0')
3317 /* Last possibility is the LANG environment variable. */
3318 retval
= getenv ("LANG");
3319 if (retval
!= NULL
&& retval
[0] != '\0')
3321 #if HAVE_CFLOCALECOPYCURRENT || HAVE_CFPREFERENCESCOPYAPPVALUE
3322 /* Mac OS X 10.2 or newer.
3323 Ignore invalid LANG value set by the Terminal application. */
3324 if (strcmp (retval
, "UTF-8") != 0)
3326 #if defined __CYGWIN__
3328 Ignore dummy LANG value set by ~/.profile. */
3329 if (strcmp (retval
, "C.UTF-8") != 0)
3338 gl_locale_name_default (void)
3341 "All implementations shall define a locale as the default locale, to be
3342 invoked when no environment variables are set, or set to the empty
3343 string. This default locale can be the POSIX locale or any other
3344 implementation-defined locale. Some implementations may provide
3345 facilities for local installation administrators to set the default
3346 locale, customizing it for each location. POSIX:2001 does not require
3349 The systems with such a facility are Mac OS X and Windows: They provide a
3350 GUI that allows the user to choose a locale.
3351 - On Mac OS X, by default, none of LC_* or LANG are set. Starting with
3352 Mac OS X 10.4 or 10.5, LANG is set for processes launched by the
3353 'Terminal' application (but sometimes to an incorrect value "UTF-8").
3354 When no environment variable is set, setlocale (LC_ALL, "") uses the
3356 - On native Windows, by default, none of LC_* or LANG are set.
3357 When no environment variable is set, setlocale (LC_ALL, "") uses the
3358 locale chosen by the user.
3359 - On Cygwin 1.5.x, by default, none of LC_* or LANG are set.
3360 When no environment variable is set, setlocale (LC_ALL, "") uses the
3362 - On Cygwin 1.7, by default, LANG is set to "C.UTF-8" when the default
3363 ~/.profile is executed.
3364 When no environment variable is set, setlocale (LC_ALL, "") uses the
3365 "C.UTF-8" locale, which operates in the same way as the "C" locale.
3368 #if !(HAVE_CFLOCALECOPYCURRENT || HAVE_CFPREFERENCESCOPYAPPVALUE || defined WINDOWS_NATIVE || defined __CYGWIN__)
3370 /* The system does not have a way of setting the locale, other than the
3371 POSIX specified environment variables. We use C as default locale. */
3376 /* Return an XPG style locale name language[_territory][@modifier].
3377 Don't even bother determining the codeset; it's not useful in this
3378 context, because message catalogs are not specific to a single
3381 # if HAVE_CFLOCALECOPYCURRENT || HAVE_CFPREFERENCESCOPYAPPVALUE
3382 /* Mac OS X 10.4 or newer */
3384 /* Cache the locale name, since CoreFoundation calls are expensive. */
3385 static const char *cached_localename
;
3387 if (cached_localename
== NULL
)
3390 # if HAVE_CFLOCALECOPYCURRENT /* Mac OS X 10.5 or newer */
3391 CFLocaleRef locale
= CFLocaleCopyCurrent ();
3392 CFStringRef name
= CFLocaleGetIdentifier (locale
);
3393 # elif HAVE_CFPREFERENCESCOPYAPPVALUE /* Mac OS X 10.4 or newer */
3395 CFPreferencesCopyAppValue (CFSTR ("AppleLocale"),
3396 kCFPreferencesCurrentApplication
);
3397 if (value
!= NULL
&& CFGetTypeID (value
) == CFStringGetTypeID ())
3399 CFStringRef name
= (CFStringRef
)value
;
3402 if (CFStringGetCString (name
, namebuf
, sizeof (namebuf
),
3403 kCFStringEncodingASCII
))
3405 gl_locale_name_canonicalize (namebuf
);
3406 cached_localename
= strdup (namebuf
);
3409 # if HAVE_CFLOCALECOPYCURRENT /* Mac OS X 10.5 or newer */
3411 # elif HAVE_CFPREFERENCESCOPYAPPVALUE /* Mac OS X 10.4 or newer */
3414 if (cached_localename
== NULL
)
3415 cached_localename
= "C";
3417 return cached_localename
;
3422 # if defined WINDOWS_NATIVE || defined __CYGWIN__ /* Native Windows or Cygwin */
3426 /* Use native Windows API locale ID. */
3427 lcid
= GetThreadLocale ();
3429 return gl_locale_name_from_win32_LCID (lcid
);
3435 /* Determine the current locale's name, and canonicalize it into XPG syntax
3436 language[_territory][.codeset][@modifier]
3437 The codeset part in the result is not reliable; the locale_charset()
3438 should be used for codeset information instead.
3439 The result must not be freed; it is statically allocated. */
3442 gl_locale_name (int category
, const char *categoryname
)
3446 retval
= gl_locale_name_thread (category
, categoryname
);
3450 retval
= gl_locale_name_posix (category
, categoryname
);
3454 return gl_locale_name_default ();