1 /* Determine name of the currently selected locale.
2 Copyright (C) 1995-2024 Free Software Foundation, Inc.
4 This file is free software: you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as
6 published by the Free Software Foundation; either version 2.1 of the
7 License, or (at your option) any later version.
9 This file is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
17 /* Written by Ulrich Drepper <drepper@gnu.org>, 1995. */
18 /* Native Windows code written by Tor Lillqvist <tml@iki.fi>. */
19 /* Mac OS X code written by Bruno Haible <bruno@clisp.org>. */
21 /* Don't use __attribute__ __nonnull__ in this compilation unit. Otherwise gcc
22 optimizes away the locale == NULL tests below in duplocale() and freelocale(),
23 or xlclang reports -Wtautological-pointer-compare warnings for these tests.
25 #define _GL_ARG_NONNULL(params)
30 #include "localename.h"
38 #include "setlocale_null.h"
40 #if HAVE_GOOD_USELOCALE
41 /* Mac OS X 10.5 defines the locale_t type in <xlocale.h>. */
42 # if defined __APPLE__ && defined __MACH__
45 # if (__GLIBC__ >= 2 && !defined __UCLIBC__) || (defined __linux__ && HAVE_LANGINFO_H) || defined __CYGWIN__
46 # include <langinfo.h>
49 # if HAVE_GETLOCALENAME_L
51 extern char * getlocalename_l(int, locale_t
);
52 # elif HAVE_SOLARIS114_LOCALES
53 # include <sys/localedef.h>
56 # if HAVE_NAMELESS_LOCALES
57 # include "localename-table.h"
59 # if defined __HAIKU__
64 #if HAVE_CFPREFERENCESCOPYAPPVALUE
65 # include <CoreFoundation/CFString.h>
66 # include <CoreFoundation/CFPreferences.h>
69 #if defined _WIN32 && !defined __CYGWIN__
70 # define WINDOWS_NATIVE
71 # include "glthread/lock.h"
74 #if LOCALENAME_ENHANCE_LOCALE_FUNCS
75 # include "flexmember.h"
76 # include "glthread/lock.h"
77 # include "thread-optim.h"
80 #if defined WINDOWS_NATIVE || defined __CYGWIN__ /* Native Windows or Cygwin */
81 # define WIN32_LEAN_AND_MEAN
84 /* List of language codes, sorted by value:
110 0x1a LANG_CROATIAN == LANG_SERBIAN
192 0x6e LANG_LUXEMBOURGISH
193 0x6f LANG_GREENLANDIC
212 0x87 LANG_KINYARWANDA
215 0x91 LANG_SCOTTISH_GAELIC
217 /* Mingw headers don't have latest language and sublanguage codes. */
218 # ifndef LANG_AFRIKAANS
219 # define LANG_AFRIKAANS 0x36
221 # ifndef LANG_ALBANIAN
222 # define LANG_ALBANIAN 0x1c
224 # ifndef LANG_ALSATIAN
225 # define LANG_ALSATIAN 0x84
227 # ifndef LANG_AMHARIC
228 # define LANG_AMHARIC 0x5e
231 # define LANG_ARABIC 0x01
233 # ifndef LANG_ARMENIAN
234 # define LANG_ARMENIAN 0x2b
236 # ifndef LANG_ASSAMESE
237 # define LANG_ASSAMESE 0x4d
240 # define LANG_AZERI 0x2c
242 # ifndef LANG_BASHKIR
243 # define LANG_BASHKIR 0x6d
246 # define LANG_BASQUE 0x2d
248 # ifndef LANG_BELARUSIAN
249 # define LANG_BELARUSIAN 0x23
251 # ifndef LANG_BENGALI
252 # define LANG_BENGALI 0x45
255 # define LANG_BRETON 0x7e
257 # ifndef LANG_BURMESE
258 # define LANG_BURMESE 0x55
260 # ifndef LANG_CAMBODIAN
261 # define LANG_CAMBODIAN 0x53
263 # ifndef LANG_CATALAN
264 # define LANG_CATALAN 0x03
266 # ifndef LANG_CHEROKEE
267 # define LANG_CHEROKEE 0x5c
269 # ifndef LANG_CORSICAN
270 # define LANG_CORSICAN 0x83
273 # define LANG_DARI 0x8c
276 # define LANG_DIVEHI 0x65
279 # define LANG_EDO 0x66
281 # ifndef LANG_ESTONIAN
282 # define LANG_ESTONIAN 0x25
284 # ifndef LANG_FAEROESE
285 # define LANG_FAEROESE 0x38
288 # define LANG_FARSI 0x29
290 # ifndef LANG_FRISIAN
291 # define LANG_FRISIAN 0x62
293 # ifndef LANG_FULFULDE
294 # define LANG_FULFULDE 0x67
297 # define LANG_GAELIC 0x3c
299 # ifndef LANG_GALICIAN
300 # define LANG_GALICIAN 0x56
302 # ifndef LANG_GEORGIAN
303 # define LANG_GEORGIAN 0x37
305 # ifndef LANG_GREENLANDIC
306 # define LANG_GREENLANDIC 0x6f
308 # ifndef LANG_GUARANI
309 # define LANG_GUARANI 0x74
311 # ifndef LANG_GUJARATI
312 # define LANG_GUJARATI 0x47
315 # define LANG_HAUSA 0x68
317 # ifndef LANG_HAWAIIAN
318 # define LANG_HAWAIIAN 0x75
321 # define LANG_HEBREW 0x0d
324 # define LANG_HINDI 0x39
327 # define LANG_IBIBIO 0x69
330 # define LANG_IGBO 0x70
332 # ifndef LANG_INDONESIAN
333 # define LANG_INDONESIAN 0x21
335 # ifndef LANG_INUKTITUT
336 # define LANG_INUKTITUT 0x5d
338 # ifndef LANG_KANNADA
339 # define LANG_KANNADA 0x4b
342 # define LANG_KANURI 0x71
344 # ifndef LANG_KASHMIRI
345 # define LANG_KASHMIRI 0x60
348 # define LANG_KAZAK 0x3f
351 # define LANG_KICHE 0x86
353 # ifndef LANG_KINYARWANDA
354 # define LANG_KINYARWANDA 0x87
356 # ifndef LANG_KONKANI
357 # define LANG_KONKANI 0x57
360 # define LANG_KYRGYZ 0x40
363 # define LANG_LAO 0x54
366 # define LANG_LATIN 0x76
368 # ifndef LANG_LATVIAN
369 # define LANG_LATVIAN 0x26
371 # ifndef LANG_LITHUANIAN
372 # define LANG_LITHUANIAN 0x27
374 # ifndef LANG_LUXEMBOURGISH
375 # define LANG_LUXEMBOURGISH 0x6e
377 # ifndef LANG_MACEDONIAN
378 # define LANG_MACEDONIAN 0x2f
381 # define LANG_MALAY 0x3e
383 # ifndef LANG_MALAYALAM
384 # define LANG_MALAYALAM 0x4c
386 # ifndef LANG_MALTESE
387 # define LANG_MALTESE 0x3a
389 # ifndef LANG_MANIPURI
390 # define LANG_MANIPURI 0x58
393 # define LANG_MAORI 0x81
395 # ifndef LANG_MAPUDUNGUN
396 # define LANG_MAPUDUNGUN 0x7a
398 # ifndef LANG_MARATHI
399 # define LANG_MARATHI 0x4e
402 # define LANG_MOHAWK 0x7c
404 # ifndef LANG_MONGOLIAN
405 # define LANG_MONGOLIAN 0x50
408 # define LANG_NEPALI 0x61
410 # ifndef LANG_OCCITAN
411 # define LANG_OCCITAN 0x82
414 # define LANG_ORIYA 0x48
417 # define LANG_OROMO 0x72
419 # ifndef LANG_PAPIAMENTU
420 # define LANG_PAPIAMENTU 0x79
423 # define LANG_PASHTO 0x63
425 # ifndef LANG_PUNJABI
426 # define LANG_PUNJABI 0x46
428 # ifndef LANG_QUECHUA
429 # define LANG_QUECHUA 0x6b
431 # ifndef LANG_ROMANSH
432 # define LANG_ROMANSH 0x17
435 # define LANG_SAMI 0x3b
437 # ifndef LANG_SANSKRIT
438 # define LANG_SANSKRIT 0x4f
440 # ifndef LANG_SCOTTISH_GAELIC
441 # define LANG_SCOTTISH_GAELIC 0x91
443 # ifndef LANG_SERBIAN
444 # define LANG_SERBIAN 0x1a
447 # define LANG_SINDHI 0x59
449 # ifndef LANG_SINHALESE
450 # define LANG_SINHALESE 0x5b
453 # define LANG_SLOVAK 0x1b
456 # define LANG_SOMALI 0x77
458 # ifndef LANG_SORBIAN
459 # define LANG_SORBIAN 0x2e
462 # define LANG_SOTHO 0x6c
465 # define LANG_SUTU 0x30
467 # ifndef LANG_SWAHILI
468 # define LANG_SWAHILI 0x41
471 # define LANG_SYRIAC 0x5a
473 # ifndef LANG_TAGALOG
474 # define LANG_TAGALOG 0x64
477 # define LANG_TAJIK 0x28
479 # ifndef LANG_TAMAZIGHT
480 # define LANG_TAMAZIGHT 0x5f
483 # define LANG_TAMIL 0x49
486 # define LANG_TATAR 0x44
489 # define LANG_TELUGU 0x4a
492 # define LANG_THAI 0x1e
494 # ifndef LANG_TIBETAN
495 # define LANG_TIBETAN 0x51
497 # ifndef LANG_TIGRINYA
498 # define LANG_TIGRINYA 0x73
501 # define LANG_TSONGA 0x31
504 # define LANG_TSWANA 0x32
506 # ifndef LANG_TURKMEN
507 # define LANG_TURKMEN 0x42
510 # define LANG_UIGHUR 0x80
512 # ifndef LANG_UKRAINIAN
513 # define LANG_UKRAINIAN 0x22
516 # define LANG_URDU 0x20
519 # define LANG_UZBEK 0x43
522 # define LANG_VENDA 0x33
524 # ifndef LANG_VIETNAMESE
525 # define LANG_VIETNAMESE 0x2a
528 # define LANG_WELSH 0x52
531 # define LANG_WOLOF 0x88
534 # define LANG_XHOSA 0x34
537 # define LANG_YAKUT 0x85
540 # define LANG_YI 0x78
542 # ifndef LANG_YIDDISH
543 # define LANG_YIDDISH 0x3d
546 # define LANG_YORUBA 0x6a
549 # define LANG_ZULU 0x35
551 # ifndef SUBLANG_AFRIKAANS_SOUTH_AFRICA
552 # define SUBLANG_AFRIKAANS_SOUTH_AFRICA 0x01
554 # ifndef SUBLANG_ALBANIAN_ALBANIA
555 # define SUBLANG_ALBANIAN_ALBANIA 0x01
557 # ifndef SUBLANG_ALSATIAN_FRANCE
558 # define SUBLANG_ALSATIAN_FRANCE 0x01
560 # ifndef SUBLANG_AMHARIC_ETHIOPIA
561 # define SUBLANG_AMHARIC_ETHIOPIA 0x01
563 # ifndef SUBLANG_ARABIC_SAUDI_ARABIA
564 # define SUBLANG_ARABIC_SAUDI_ARABIA 0x01
566 # ifndef SUBLANG_ARABIC_IRAQ
567 # define SUBLANG_ARABIC_IRAQ 0x02
569 # ifndef SUBLANG_ARABIC_EGYPT
570 # define SUBLANG_ARABIC_EGYPT 0x03
572 # ifndef SUBLANG_ARABIC_LIBYA
573 # define SUBLANG_ARABIC_LIBYA 0x04
575 # ifndef SUBLANG_ARABIC_ALGERIA
576 # define SUBLANG_ARABIC_ALGERIA 0x05
578 # ifndef SUBLANG_ARABIC_MOROCCO
579 # define SUBLANG_ARABIC_MOROCCO 0x06
581 # ifndef SUBLANG_ARABIC_TUNISIA
582 # define SUBLANG_ARABIC_TUNISIA 0x07
584 # ifndef SUBLANG_ARABIC_OMAN
585 # define SUBLANG_ARABIC_OMAN 0x08
587 # ifndef SUBLANG_ARABIC_YEMEN
588 # define SUBLANG_ARABIC_YEMEN 0x09
590 # ifndef SUBLANG_ARABIC_SYRIA
591 # define SUBLANG_ARABIC_SYRIA 0x0a
593 # ifndef SUBLANG_ARABIC_JORDAN
594 # define SUBLANG_ARABIC_JORDAN 0x0b
596 # ifndef SUBLANG_ARABIC_LEBANON
597 # define SUBLANG_ARABIC_LEBANON 0x0c
599 # ifndef SUBLANG_ARABIC_KUWAIT
600 # define SUBLANG_ARABIC_KUWAIT 0x0d
602 # ifndef SUBLANG_ARABIC_UAE
603 # define SUBLANG_ARABIC_UAE 0x0e
605 # ifndef SUBLANG_ARABIC_BAHRAIN
606 # define SUBLANG_ARABIC_BAHRAIN 0x0f
608 # ifndef SUBLANG_ARABIC_QATAR
609 # define SUBLANG_ARABIC_QATAR 0x10
611 # ifndef SUBLANG_ARMENIAN_ARMENIA
612 # define SUBLANG_ARMENIAN_ARMENIA 0x01
614 # ifndef SUBLANG_ASSAMESE_INDIA
615 # define SUBLANG_ASSAMESE_INDIA 0x01
617 # ifndef SUBLANG_AZERI_LATIN
618 # define SUBLANG_AZERI_LATIN 0x01
620 # ifndef SUBLANG_AZERI_CYRILLIC
621 # define SUBLANG_AZERI_CYRILLIC 0x02
623 # ifndef SUBLANG_BASHKIR_RUSSIA
624 # define SUBLANG_BASHKIR_RUSSIA 0x01
626 # ifndef SUBLANG_BASQUE_BASQUE
627 # define SUBLANG_BASQUE_BASQUE 0x01
629 # ifndef SUBLANG_BELARUSIAN_BELARUS
630 # define SUBLANG_BELARUSIAN_BELARUS 0x01
632 # ifndef SUBLANG_BENGALI_INDIA
633 # define SUBLANG_BENGALI_INDIA 0x01
635 # ifndef SUBLANG_BENGALI_BANGLADESH
636 # define SUBLANG_BENGALI_BANGLADESH 0x02
638 # ifndef SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN
639 # define SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN 0x05
641 # ifndef SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC
642 # define SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC 0x08
644 # ifndef SUBLANG_BRETON_FRANCE
645 # define SUBLANG_BRETON_FRANCE 0x01
647 # ifndef SUBLANG_BULGARIAN_BULGARIA
648 # define SUBLANG_BULGARIAN_BULGARIA 0x01
650 # ifndef SUBLANG_CAMBODIAN_CAMBODIA
651 # define SUBLANG_CAMBODIAN_CAMBODIA 0x01
653 # ifndef SUBLANG_CATALAN_SPAIN
654 # define SUBLANG_CATALAN_SPAIN 0x01
656 # ifndef SUBLANG_CORSICAN_FRANCE
657 # define SUBLANG_CORSICAN_FRANCE 0x01
659 # ifndef SUBLANG_CROATIAN_CROATIA
660 # define SUBLANG_CROATIAN_CROATIA 0x01
662 # ifndef SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN
663 # define SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN 0x04
665 # ifndef SUBLANG_CHINESE_MACAU
666 # define SUBLANG_CHINESE_MACAU 0x05
668 # ifndef SUBLANG_CZECH_CZECH_REPUBLIC
669 # define SUBLANG_CZECH_CZECH_REPUBLIC 0x01
671 # ifndef SUBLANG_DANISH_DENMARK
672 # define SUBLANG_DANISH_DENMARK 0x01
674 # ifndef SUBLANG_DARI_AFGHANISTAN
675 # define SUBLANG_DARI_AFGHANISTAN 0x01
677 # ifndef SUBLANG_DIVEHI_MALDIVES
678 # define SUBLANG_DIVEHI_MALDIVES 0x01
680 # ifndef SUBLANG_DUTCH_SURINAM
681 # define SUBLANG_DUTCH_SURINAM 0x03
683 # ifndef SUBLANG_ENGLISH_SOUTH_AFRICA
684 # define SUBLANG_ENGLISH_SOUTH_AFRICA 0x07
686 # ifndef SUBLANG_ENGLISH_JAMAICA
687 # define SUBLANG_ENGLISH_JAMAICA 0x08
689 # ifndef SUBLANG_ENGLISH_CARIBBEAN
690 # define SUBLANG_ENGLISH_CARIBBEAN 0x09
692 # ifndef SUBLANG_ENGLISH_BELIZE
693 # define SUBLANG_ENGLISH_BELIZE 0x0a
695 # ifndef SUBLANG_ENGLISH_TRINIDAD
696 # define SUBLANG_ENGLISH_TRINIDAD 0x0b
698 # ifndef SUBLANG_ENGLISH_ZIMBABWE
699 # define SUBLANG_ENGLISH_ZIMBABWE 0x0c
701 # ifndef SUBLANG_ENGLISH_PHILIPPINES
702 # define SUBLANG_ENGLISH_PHILIPPINES 0x0d
704 # ifndef SUBLANG_ENGLISH_INDONESIA
705 # define SUBLANG_ENGLISH_INDONESIA 0x0e
707 # ifndef SUBLANG_ENGLISH_HONGKONG
708 # define SUBLANG_ENGLISH_HONGKONG 0x0f
710 # ifndef SUBLANG_ENGLISH_INDIA
711 # define SUBLANG_ENGLISH_INDIA 0x10
713 # ifndef SUBLANG_ENGLISH_MALAYSIA
714 # define SUBLANG_ENGLISH_MALAYSIA 0x11
716 # ifndef SUBLANG_ENGLISH_SINGAPORE
717 # define SUBLANG_ENGLISH_SINGAPORE 0x12
719 # ifndef SUBLANG_ESTONIAN_ESTONIA
720 # define SUBLANG_ESTONIAN_ESTONIA 0x01
722 # ifndef SUBLANG_FAEROESE_FAROE_ISLANDS
723 # define SUBLANG_FAEROESE_FAROE_ISLANDS 0x01
725 # ifndef SUBLANG_FARSI_IRAN
726 # define SUBLANG_FARSI_IRAN 0x01
728 # ifndef SUBLANG_FINNISH_FINLAND
729 # define SUBLANG_FINNISH_FINLAND 0x01
731 # ifndef SUBLANG_FRENCH_LUXEMBOURG
732 # define SUBLANG_FRENCH_LUXEMBOURG 0x05
734 # ifndef SUBLANG_FRENCH_MONACO
735 # define SUBLANG_FRENCH_MONACO 0x06
737 # ifndef SUBLANG_FRENCH_WESTINDIES
738 # define SUBLANG_FRENCH_WESTINDIES 0x07
740 # ifndef SUBLANG_FRENCH_REUNION
741 # define SUBLANG_FRENCH_REUNION 0x08
743 # ifndef SUBLANG_FRENCH_CONGO
744 # define SUBLANG_FRENCH_CONGO 0x09
746 # ifndef SUBLANG_FRENCH_SENEGAL
747 # define SUBLANG_FRENCH_SENEGAL 0x0a
749 # ifndef SUBLANG_FRENCH_CAMEROON
750 # define SUBLANG_FRENCH_CAMEROON 0x0b
752 # ifndef SUBLANG_FRENCH_COTEDIVOIRE
753 # define SUBLANG_FRENCH_COTEDIVOIRE 0x0c
755 # ifndef SUBLANG_FRENCH_MALI
756 # define SUBLANG_FRENCH_MALI 0x0d
758 # ifndef SUBLANG_FRENCH_MOROCCO
759 # define SUBLANG_FRENCH_MOROCCO 0x0e
761 # ifndef SUBLANG_FRENCH_HAITI
762 # define SUBLANG_FRENCH_HAITI 0x0f
764 # ifndef SUBLANG_FRISIAN_NETHERLANDS
765 # define SUBLANG_FRISIAN_NETHERLANDS 0x01
767 # ifndef SUBLANG_GALICIAN_SPAIN
768 # define SUBLANG_GALICIAN_SPAIN 0x01
770 # ifndef SUBLANG_GEORGIAN_GEORGIA
771 # define SUBLANG_GEORGIAN_GEORGIA 0x01
773 # ifndef SUBLANG_GERMAN_LUXEMBOURG
774 # define SUBLANG_GERMAN_LUXEMBOURG 0x04
776 # ifndef SUBLANG_GERMAN_LIECHTENSTEIN
777 # define SUBLANG_GERMAN_LIECHTENSTEIN 0x05
779 # ifndef SUBLANG_GREEK_GREECE
780 # define SUBLANG_GREEK_GREECE 0x01
782 # ifndef SUBLANG_GREENLANDIC_GREENLAND
783 # define SUBLANG_GREENLANDIC_GREENLAND 0x01
785 # ifndef SUBLANG_GUJARATI_INDIA
786 # define SUBLANG_GUJARATI_INDIA 0x01
788 # ifndef SUBLANG_HAUSA_NIGERIA_LATIN
789 # define SUBLANG_HAUSA_NIGERIA_LATIN 0x01
791 # ifndef SUBLANG_HEBREW_ISRAEL
792 # define SUBLANG_HEBREW_ISRAEL 0x01
794 # ifndef SUBLANG_HINDI_INDIA
795 # define SUBLANG_HINDI_INDIA 0x01
797 # ifndef SUBLANG_HUNGARIAN_HUNGARY
798 # define SUBLANG_HUNGARIAN_HUNGARY 0x01
800 # ifndef SUBLANG_ICELANDIC_ICELAND
801 # define SUBLANG_ICELANDIC_ICELAND 0x01
803 # ifndef SUBLANG_IGBO_NIGERIA
804 # define SUBLANG_IGBO_NIGERIA 0x01
806 # ifndef SUBLANG_INDONESIAN_INDONESIA
807 # define SUBLANG_INDONESIAN_INDONESIA 0x01
809 # ifndef SUBLANG_INUKTITUT_CANADA
810 # define SUBLANG_INUKTITUT_CANADA 0x01
812 # undef SUBLANG_INUKTITUT_CANADA_LATIN
813 # define SUBLANG_INUKTITUT_CANADA_LATIN 0x02
814 # undef SUBLANG_IRISH_IRELAND
815 # define SUBLANG_IRISH_IRELAND 0x02
816 # ifndef SUBLANG_JAPANESE_JAPAN
817 # define SUBLANG_JAPANESE_JAPAN 0x01
819 # ifndef SUBLANG_KANNADA_INDIA
820 # define SUBLANG_KANNADA_INDIA 0x01
822 # ifndef SUBLANG_KASHMIRI_INDIA
823 # define SUBLANG_KASHMIRI_INDIA 0x02
825 # ifndef SUBLANG_KAZAK_KAZAKHSTAN
826 # define SUBLANG_KAZAK_KAZAKHSTAN 0x01
828 # ifndef SUBLANG_KICHE_GUATEMALA
829 # define SUBLANG_KICHE_GUATEMALA 0x01
831 # ifndef SUBLANG_KINYARWANDA_RWANDA
832 # define SUBLANG_KINYARWANDA_RWANDA 0x01
834 # ifndef SUBLANG_KONKANI_INDIA
835 # define SUBLANG_KONKANI_INDIA 0x01
837 # ifndef SUBLANG_KYRGYZ_KYRGYZSTAN
838 # define SUBLANG_KYRGYZ_KYRGYZSTAN 0x01
840 # ifndef SUBLANG_LAO_LAOS
841 # define SUBLANG_LAO_LAOS 0x01
843 # ifndef SUBLANG_LATVIAN_LATVIA
844 # define SUBLANG_LATVIAN_LATVIA 0x01
846 # ifndef SUBLANG_LITHUANIAN_LITHUANIA
847 # define SUBLANG_LITHUANIAN_LITHUANIA 0x01
849 # undef SUBLANG_LOWER_SORBIAN_GERMANY
850 # define SUBLANG_LOWER_SORBIAN_GERMANY 0x02
851 # ifndef SUBLANG_LUXEMBOURGISH_LUXEMBOURG
852 # define SUBLANG_LUXEMBOURGISH_LUXEMBOURG 0x01
854 # ifndef SUBLANG_MACEDONIAN_MACEDONIA
855 # define SUBLANG_MACEDONIAN_MACEDONIA 0x01
857 # ifndef SUBLANG_MALAY_MALAYSIA
858 # define SUBLANG_MALAY_MALAYSIA 0x01
860 # ifndef SUBLANG_MALAY_BRUNEI_DARUSSALAM
861 # define SUBLANG_MALAY_BRUNEI_DARUSSALAM 0x02
863 # ifndef SUBLANG_MALAYALAM_INDIA
864 # define SUBLANG_MALAYALAM_INDIA 0x01
866 # ifndef SUBLANG_MALTESE_MALTA
867 # define SUBLANG_MALTESE_MALTA 0x01
869 # ifndef SUBLANG_MAORI_NEW_ZEALAND
870 # define SUBLANG_MAORI_NEW_ZEALAND 0x01
872 # ifndef SUBLANG_MAPUDUNGUN_CHILE
873 # define SUBLANG_MAPUDUNGUN_CHILE 0x01
875 # ifndef SUBLANG_MARATHI_INDIA
876 # define SUBLANG_MARATHI_INDIA 0x01
878 # ifndef SUBLANG_MOHAWK_CANADA
879 # define SUBLANG_MOHAWK_CANADA 0x01
881 # ifndef SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA
882 # define SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA 0x01
884 # ifndef SUBLANG_MONGOLIAN_PRC
885 # define SUBLANG_MONGOLIAN_PRC 0x02
887 # ifndef SUBLANG_NEPALI_NEPAL
888 # define SUBLANG_NEPALI_NEPAL 0x01
890 # ifndef SUBLANG_NEPALI_INDIA
891 # define SUBLANG_NEPALI_INDIA 0x02
893 # ifndef SUBLANG_OCCITAN_FRANCE
894 # define SUBLANG_OCCITAN_FRANCE 0x01
896 # ifndef SUBLANG_ORIYA_INDIA
897 # define SUBLANG_ORIYA_INDIA 0x01
899 # ifndef SUBLANG_PASHTO_AFGHANISTAN
900 # define SUBLANG_PASHTO_AFGHANISTAN 0x01
902 # ifndef SUBLANG_POLISH_POLAND
903 # define SUBLANG_POLISH_POLAND 0x01
905 # ifndef SUBLANG_PUNJABI_INDIA
906 # define SUBLANG_PUNJABI_INDIA 0x01
908 # ifndef SUBLANG_PUNJABI_PAKISTAN
909 # define SUBLANG_PUNJABI_PAKISTAN 0x02
911 # ifndef SUBLANG_QUECHUA_BOLIVIA
912 # define SUBLANG_QUECHUA_BOLIVIA 0x01
914 # ifndef SUBLANG_QUECHUA_ECUADOR
915 # define SUBLANG_QUECHUA_ECUADOR 0x02
917 # ifndef SUBLANG_QUECHUA_PERU
918 # define SUBLANG_QUECHUA_PERU 0x03
920 # ifndef SUBLANG_ROMANIAN_ROMANIA
921 # define SUBLANG_ROMANIAN_ROMANIA 0x01
923 # ifndef SUBLANG_ROMANIAN_MOLDOVA
924 # define SUBLANG_ROMANIAN_MOLDOVA 0x02
926 # ifndef SUBLANG_ROMANSH_SWITZERLAND
927 # define SUBLANG_ROMANSH_SWITZERLAND 0x01
929 # ifndef SUBLANG_RUSSIAN_RUSSIA
930 # define SUBLANG_RUSSIAN_RUSSIA 0x01
932 # ifndef SUBLANG_RUSSIAN_MOLDAVIA
933 # define SUBLANG_RUSSIAN_MOLDAVIA 0x02
935 # ifndef SUBLANG_SAMI_NORTHERN_NORWAY
936 # define SUBLANG_SAMI_NORTHERN_NORWAY 0x01
938 # ifndef SUBLANG_SAMI_NORTHERN_SWEDEN
939 # define SUBLANG_SAMI_NORTHERN_SWEDEN 0x02
941 # ifndef SUBLANG_SAMI_NORTHERN_FINLAND
942 # define SUBLANG_SAMI_NORTHERN_FINLAND 0x03
944 # ifndef SUBLANG_SAMI_LULE_NORWAY
945 # define SUBLANG_SAMI_LULE_NORWAY 0x04
947 # ifndef SUBLANG_SAMI_LULE_SWEDEN
948 # define SUBLANG_SAMI_LULE_SWEDEN 0x05
950 # ifndef SUBLANG_SAMI_SOUTHERN_NORWAY
951 # define SUBLANG_SAMI_SOUTHERN_NORWAY 0x06
953 # ifndef SUBLANG_SAMI_SOUTHERN_SWEDEN
954 # define SUBLANG_SAMI_SOUTHERN_SWEDEN 0x07
956 # undef SUBLANG_SAMI_SKOLT_FINLAND
957 # define SUBLANG_SAMI_SKOLT_FINLAND 0x08
958 # undef SUBLANG_SAMI_INARI_FINLAND
959 # define SUBLANG_SAMI_INARI_FINLAND 0x09
960 # ifndef SUBLANG_SANSKRIT_INDIA
961 # define SUBLANG_SANSKRIT_INDIA 0x01
963 # ifndef SUBLANG_SERBIAN_LATIN
964 # define SUBLANG_SERBIAN_LATIN 0x02
966 # ifndef SUBLANG_SERBIAN_CYRILLIC
967 # define SUBLANG_SERBIAN_CYRILLIC 0x03
969 # ifndef SUBLANG_SINDHI_INDIA
970 # define SUBLANG_SINDHI_INDIA 0x01
972 # undef SUBLANG_SINDHI_PAKISTAN
973 # define SUBLANG_SINDHI_PAKISTAN 0x02
974 # ifndef SUBLANG_SINDHI_AFGHANISTAN
975 # define SUBLANG_SINDHI_AFGHANISTAN 0x02
977 # ifndef SUBLANG_SINHALESE_SRI_LANKA
978 # define SUBLANG_SINHALESE_SRI_LANKA 0x01
980 # ifndef SUBLANG_SLOVAK_SLOVAKIA
981 # define SUBLANG_SLOVAK_SLOVAKIA 0x01
983 # ifndef SUBLANG_SLOVENIAN_SLOVENIA
984 # define SUBLANG_SLOVENIAN_SLOVENIA 0x01
986 # ifndef SUBLANG_SOTHO_SOUTH_AFRICA
987 # define SUBLANG_SOTHO_SOUTH_AFRICA 0x01
989 # ifndef SUBLANG_SPANISH_GUATEMALA
990 # define SUBLANG_SPANISH_GUATEMALA 0x04
992 # ifndef SUBLANG_SPANISH_COSTA_RICA
993 # define SUBLANG_SPANISH_COSTA_RICA 0x05
995 # ifndef SUBLANG_SPANISH_PANAMA
996 # define SUBLANG_SPANISH_PANAMA 0x06
998 # ifndef SUBLANG_SPANISH_DOMINICAN_REPUBLIC
999 # define SUBLANG_SPANISH_DOMINICAN_REPUBLIC 0x07
1001 # ifndef SUBLANG_SPANISH_VENEZUELA
1002 # define SUBLANG_SPANISH_VENEZUELA 0x08
1004 # ifndef SUBLANG_SPANISH_COLOMBIA
1005 # define SUBLANG_SPANISH_COLOMBIA 0x09
1007 # ifndef SUBLANG_SPANISH_PERU
1008 # define SUBLANG_SPANISH_PERU 0x0a
1010 # ifndef SUBLANG_SPANISH_ARGENTINA
1011 # define SUBLANG_SPANISH_ARGENTINA 0x0b
1013 # ifndef SUBLANG_SPANISH_ECUADOR
1014 # define SUBLANG_SPANISH_ECUADOR 0x0c
1016 # ifndef SUBLANG_SPANISH_CHILE
1017 # define SUBLANG_SPANISH_CHILE 0x0d
1019 # ifndef SUBLANG_SPANISH_URUGUAY
1020 # define SUBLANG_SPANISH_URUGUAY 0x0e
1022 # ifndef SUBLANG_SPANISH_PARAGUAY
1023 # define SUBLANG_SPANISH_PARAGUAY 0x0f
1025 # ifndef SUBLANG_SPANISH_BOLIVIA
1026 # define SUBLANG_SPANISH_BOLIVIA 0x10
1028 # ifndef SUBLANG_SPANISH_EL_SALVADOR
1029 # define SUBLANG_SPANISH_EL_SALVADOR 0x11
1031 # ifndef SUBLANG_SPANISH_HONDURAS
1032 # define SUBLANG_SPANISH_HONDURAS 0x12
1034 # ifndef SUBLANG_SPANISH_NICARAGUA
1035 # define SUBLANG_SPANISH_NICARAGUA 0x13
1037 # ifndef SUBLANG_SPANISH_PUERTO_RICO
1038 # define SUBLANG_SPANISH_PUERTO_RICO 0x14
1040 # ifndef SUBLANG_SPANISH_US
1041 # define SUBLANG_SPANISH_US 0x15
1043 # ifndef SUBLANG_SWAHILI_KENYA
1044 # define SUBLANG_SWAHILI_KENYA 0x01
1046 # ifndef SUBLANG_SWEDISH_SWEDEN
1047 # define SUBLANG_SWEDISH_SWEDEN 0x01
1049 # ifndef SUBLANG_SWEDISH_FINLAND
1050 # define SUBLANG_SWEDISH_FINLAND 0x02
1052 # ifndef SUBLANG_SYRIAC_SYRIA
1053 # define SUBLANG_SYRIAC_SYRIA 0x01
1055 # ifndef SUBLANG_TAGALOG_PHILIPPINES
1056 # define SUBLANG_TAGALOG_PHILIPPINES 0x01
1058 # ifndef SUBLANG_TAJIK_TAJIKISTAN
1059 # define SUBLANG_TAJIK_TAJIKISTAN 0x01
1061 # ifndef SUBLANG_TAMAZIGHT_ARABIC
1062 # define SUBLANG_TAMAZIGHT_ARABIC 0x01
1064 # ifndef SUBLANG_TAMAZIGHT_ALGERIA_LATIN
1065 # define SUBLANG_TAMAZIGHT_ALGERIA_LATIN 0x02
1067 # ifndef SUBLANG_TAMIL_INDIA
1068 # define SUBLANG_TAMIL_INDIA 0x01
1070 # ifndef SUBLANG_TATAR_RUSSIA
1071 # define SUBLANG_TATAR_RUSSIA 0x01
1073 # ifndef SUBLANG_TELUGU_INDIA
1074 # define SUBLANG_TELUGU_INDIA 0x01
1076 # ifndef SUBLANG_THAI_THAILAND
1077 # define SUBLANG_THAI_THAILAND 0x01
1079 # ifndef SUBLANG_TIBETAN_PRC
1080 # define SUBLANG_TIBETAN_PRC 0x01
1082 # undef SUBLANG_TIBETAN_BHUTAN
1083 # define SUBLANG_TIBETAN_BHUTAN 0x02
1084 # ifndef SUBLANG_TIGRINYA_ETHIOPIA
1085 # define SUBLANG_TIGRINYA_ETHIOPIA 0x01
1087 # ifndef SUBLANG_TIGRINYA_ERITREA
1088 # define SUBLANG_TIGRINYA_ERITREA 0x02
1090 # ifndef SUBLANG_TSWANA_SOUTH_AFRICA
1091 # define SUBLANG_TSWANA_SOUTH_AFRICA 0x01
1093 # ifndef SUBLANG_TURKISH_TURKEY
1094 # define SUBLANG_TURKISH_TURKEY 0x01
1096 # ifndef SUBLANG_TURKMEN_TURKMENISTAN
1097 # define SUBLANG_TURKMEN_TURKMENISTAN 0x01
1099 # ifndef SUBLANG_UIGHUR_PRC
1100 # define SUBLANG_UIGHUR_PRC 0x01
1102 # ifndef SUBLANG_UKRAINIAN_UKRAINE
1103 # define SUBLANG_UKRAINIAN_UKRAINE 0x01
1105 # ifndef SUBLANG_UPPER_SORBIAN_GERMANY
1106 # define SUBLANG_UPPER_SORBIAN_GERMANY 0x01
1108 # ifndef SUBLANG_URDU_PAKISTAN
1109 # define SUBLANG_URDU_PAKISTAN 0x01
1111 # ifndef SUBLANG_URDU_INDIA
1112 # define SUBLANG_URDU_INDIA 0x02
1114 # ifndef SUBLANG_UZBEK_LATIN
1115 # define SUBLANG_UZBEK_LATIN 0x01
1117 # ifndef SUBLANG_UZBEK_CYRILLIC
1118 # define SUBLANG_UZBEK_CYRILLIC 0x02
1120 # ifndef SUBLANG_VIETNAMESE_VIETNAM
1121 # define SUBLANG_VIETNAMESE_VIETNAM 0x01
1123 # ifndef SUBLANG_WELSH_UNITED_KINGDOM
1124 # define SUBLANG_WELSH_UNITED_KINGDOM 0x01
1126 # ifndef SUBLANG_WOLOF_SENEGAL
1127 # define SUBLANG_WOLOF_SENEGAL 0x01
1129 # ifndef SUBLANG_XHOSA_SOUTH_AFRICA
1130 # define SUBLANG_XHOSA_SOUTH_AFRICA 0x01
1132 # ifndef SUBLANG_YAKUT_RUSSIA
1133 # define SUBLANG_YAKUT_RUSSIA 0x01
1135 # ifndef SUBLANG_YI_PRC
1136 # define SUBLANG_YI_PRC 0x01
1138 # ifndef SUBLANG_YORUBA_NIGERIA
1139 # define SUBLANG_YORUBA_NIGERIA 0x01
1141 # ifndef SUBLANG_ZULU_SOUTH_AFRICA
1142 # define SUBLANG_ZULU_SOUTH_AFRICA 0x01
1144 /* GetLocaleInfoA operations. */
1145 # ifndef LOCALE_SNAME
1146 # define LOCALE_SNAME 0x5c
1148 # ifndef LOCALE_NAME_MAX_LENGTH
1149 # define LOCALE_NAME_MAX_LENGTH 85
1151 /* Don't assume that UNICODE is not defined. */
1152 # undef GetLocaleInfo
1153 # define GetLocaleInfo GetLocaleInfoA
1154 # undef EnumSystemLocales
1155 # define EnumSystemLocales EnumSystemLocalesA
1158 /* We want to use the system's setlocale() function here, not the gnulib
1163 #if HAVE_CFPREFERENCESCOPYAPPVALUE
1164 /* Mac OS X 10.4 or newer */
1166 /* Canonicalize a Mac OS X locale name to a Unix locale name.
1167 NAME is a sufficiently large buffer.
1168 On input, it contains the Mac OS X locale name.
1169 On output, it contains the Unix locale name. */
1170 # if !defined IN_LIBINTL
1174 gl_locale_name_canonicalize (char *name
)
1176 /* This conversion is based on a posting by
1177 Deborah GoldSmith <goldsmit@apple.com> on 2005-03-08,
1178 https://lists.apple.com/archives/carbon-dev/2005/Mar/msg00293.html */
1180 /* Convert legacy (NeXTstep inherited) English names to Unix (ISO 639 and
1181 ISO 3166) names. Prior to Mac OS X 10.3, there is no API for doing this.
1182 Therefore we do it ourselves, using a table based on the results of the
1183 Mac OS X 10.3.8 function
1184 CFLocaleCreateCanonicalLocaleIdentifierFromString(). */
1185 typedef struct { const char legacy
[21+1]; const char unixy
[5+1]; }
1187 static const legacy_entry legacy_table
[] = {
1188 { "Afrikaans", "af" },
1189 { "Albanian", "sq" },
1190 { "Amharic", "am" },
1192 { "Armenian", "hy" },
1193 { "Assamese", "as" },
1195 { "Azerbaijani", "az" },
1197 { "Belarusian", "be" },
1198 { "Belorussian", "be" },
1199 { "Bengali", "bn" },
1200 { "Brazilian Portugese", "pt_BR" },
1201 { "Brazilian Portuguese", "pt_BR" },
1203 { "Bulgarian", "bg" },
1204 { "Burmese", "my" },
1205 { "Byelorussian", "be" },
1206 { "Catalan", "ca" },
1208 { "Chichewa", "ny" },
1209 { "Chinese", "zh" },
1210 { "Chinese, Simplified", "zh_CN" },
1211 { "Chinese, Traditional", "zh_TW" },
1212 { "Chinese, Tradtional", "zh_TW" },
1213 { "Croatian", "hr" },
1217 { "Dzongkha", "dz" },
1218 { "English", "en" },
1219 { "Esperanto", "eo" },
1220 { "Estonian", "et" },
1221 { "Faroese", "fo" },
1223 { "Finnish", "fi" },
1224 { "Flemish", "nl_BE" },
1226 { "Galician", "gl" },
1227 { "Gallegan", "gl" },
1228 { "Georgian", "ka" },
1231 { "Greenlandic", "kl" },
1232 { "Guarani", "gn" },
1233 { "Gujarati", "gu" },
1234 { "Hawaiian", "haw" }, /* Yes, "haw", not "cpe". */
1237 { "Hungarian", "hu" },
1238 { "Icelandic", "is" },
1239 { "Indonesian", "id" },
1240 { "Inuktitut", "iu" },
1242 { "Italian", "it" },
1243 { "Japanese", "ja" },
1244 { "Javanese", "jv" },
1245 { "Kalaallisut", "kl" },
1246 { "Kannada", "kn" },
1247 { "Kashmiri", "ks" },
1250 { "Kinyarwanda", "rw" },
1251 { "Kirghiz", "ky" },
1253 { "Kurdish", "ku" },
1255 { "Latvian", "lv" },
1256 { "Lithuanian", "lt" },
1257 { "Macedonian", "mk" },
1258 { "Malagasy", "mg" },
1260 { "Malayalam", "ml" },
1261 { "Maltese", "mt" },
1263 { "Marathi", "mr" },
1264 { "Moldavian", "mo" },
1265 { "Mongolian", "mn" },
1267 { "Norwegian", "nb" }, /* Yes, "nb", not the obsolete "no". */
1269 { "Nynorsk", "nn" },
1272 { "Panjabi", "pa" },
1274 { "Persian", "fa" },
1276 { "Portuguese", "pt" },
1277 { "Portuguese, Brazilian", "pt_BR" },
1278 { "Punjabi", "pa" },
1280 { "Quechua", "qu" },
1281 { "Romanian", "ro" },
1284 { "Russian", "ru" },
1285 { "Sami", "se_NO" }, /* Not just "se". */
1286 { "Sanskrit", "sa" },
1287 { "Scottish", "gd" },
1288 { "Serbian", "sr" },
1289 { "Simplified Chinese", "zh_CN" },
1291 { "Sinhalese", "si" },
1293 { "Slovenian", "sl" },
1295 { "Spanish", "es" },
1296 { "Sundanese", "su" },
1297 { "Swahili", "sw" },
1298 { "Swedish", "sv" },
1299 { "Tagalog", "tl" },
1306 { "Tibetan", "bo" },
1307 { "Tigrinya", "ti" },
1309 { "Traditional Chinese", "zh_TW" },
1310 { "Turkish", "tr" },
1311 { "Turkmen", "tk" },
1313 { "Ukrainian", "uk" },
1316 { "Vietnamese", "vi" },
1321 /* Convert new-style locale names with language tags (ISO 639 and ISO 15924)
1322 to Unix (ISO 639 and ISO 3166) names. */
1323 typedef struct { const char langtag
[7+1]; const char unixy
[12+1]; }
1325 static const langtag_entry langtag_table
[] = {
1326 /* Mac OS X has "az-Arab", "az-Cyrl", "az-Latn".
1327 The default script for az on Unix is Latin. */
1328 { "az-Latn", "az" },
1329 /* Mac OS X has "bs-Cyrl", "bs-Latn".
1330 The default script for bs on Unix is Latin. */
1331 { "bs-Latn", "bs" },
1332 /* Mac OS X has "ga-dots". Does not yet exist on Unix. */
1333 { "ga-dots", "ga" },
1334 /* Mac OS X has "kk-Cyrl".
1335 The default script for kk on Unix is Cyrillic. */
1336 { "kk-Cyrl", "kk" },
1337 /* Mac OS X has "mn-Cyrl", "mn-Mong".
1338 The default script for mn on Unix is Cyrillic. */
1339 { "mn-Cyrl", "mn" },
1340 /* Mac OS X has "ms-Arab", "ms-Latn".
1341 The default script for ms on Unix is Latin. */
1342 { "ms-Latn", "ms" },
1343 /* Mac OS X has "pa-Arab", "pa-Guru".
1344 Country codes are used to distinguish these on Unix. */
1345 { "pa-Arab", "pa_PK" },
1346 { "pa-Guru", "pa_IN" },
1347 /* Mac OS X has "shi-Latn", "shi-Tfng". Does not yet exist on Unix. */
1348 /* Mac OS X has "sr-Cyrl", "sr-Latn".
1349 The default script for sr on Unix is Cyrillic. */
1350 { "sr-Cyrl", "sr" },
1351 /* Mac OS X has "tg-Cyrl".
1352 The default script for tg on Unix is Cyrillic. */
1353 { "tg-Cyrl", "tg" },
1354 /* Mac OS X has "tk-Cyrl".
1355 The default script for tk on Unix is Cyrillic. */
1356 { "tk-Cyrl", "tk" },
1357 /* Mac OS X has "tt-Cyrl".
1358 The default script for tt on Unix is Cyrillic. */
1359 { "tt-Cyrl", "tt" },
1360 /* Mac OS X has "uz-Arab", "uz-Cyrl", "uz-Latn".
1361 The default script for uz on Unix is Latin. */
1362 { "uz-Latn", "uz" },
1363 /* Mac OS X has "vai-Latn", "vai-Vaii". Does not yet exist on Unix. */
1364 /* Mac OS X has "yue-Hans", "yue-Hant".
1365 The default script for yue on Unix is Simplified Han. */
1366 { "yue-Hans", "yue" },
1367 /* Mac OS X has "zh-Hans", "zh-Hant".
1368 Country codes are used to distinguish these on Unix. */
1369 { "zh-Hans", "zh_CN" },
1370 { "zh-Hant", "zh_TW" }
1373 /* Convert script names (ISO 15924) to Unix conventions.
1374 See https://www.unicode.org/iso15924/iso15924-codes.html */
1375 typedef struct { const char script
[4+1]; const char unixy
[9+1]; }
1377 static const script_entry script_table
[] = {
1378 { "Arab", "arabic" },
1379 { "Cyrl", "cyrillic" },
1380 { "Latn", "latin" },
1381 { "Mong", "mongolian" }
1384 /* Step 1: Convert using legacy_table. */
1385 if (name
[0] >= 'A' && name
[0] <= 'Z')
1387 unsigned int i1
, i2
;
1389 i2
= sizeof (legacy_table
) / sizeof (legacy_entry
);
1392 /* At this point we know that if name occurs in legacy_table,
1393 its index must be >= i1 and < i2. */
1394 unsigned int i
= (i1
+ i2
) >> 1;
1395 const legacy_entry
*p
= &legacy_table
[i
];
1396 if (strcmp (name
, p
->legacy
) < 0)
1401 if (strcmp (name
, legacy_table
[i1
].legacy
) == 0)
1403 strcpy (name
, legacy_table
[i1
].unixy
);
1408 /* Step 2: Convert using langtag_table and script_table. */
1409 if (strlen (name
) == 7 && name
[2] == '-')
1411 unsigned int i1
, i2
;
1413 i2
= sizeof (langtag_table
) / sizeof (langtag_entry
);
1416 /* At this point we know that if name occurs in langtag_table,
1417 its index must be >= i1 and < i2. */
1418 unsigned int i
= (i1
+ i2
) >> 1;
1419 const langtag_entry
*p
= &langtag_table
[i
];
1420 if (strcmp (name
, p
->langtag
) < 0)
1425 if (strcmp (name
, langtag_table
[i1
].langtag
) == 0)
1427 strcpy (name
, langtag_table
[i1
].unixy
);
1432 i2
= sizeof (script_table
) / sizeof (script_entry
);
1435 /* At this point we know that if (name + 3) occurs in script_table,
1436 its index must be >= i1 and < i2. */
1437 unsigned int i
= (i1
+ i2
) >> 1;
1438 const script_entry
*p
= &script_table
[i
];
1439 if (strcmp (name
+ 3, p
->script
) < 0)
1444 if (strcmp (name
+ 3, script_table
[i1
].script
) == 0)
1447 strcpy (name
+ 3, script_table
[i1
].unixy
);
1452 /* Step 3: Convert new-style dash to Unix underscore. */
1455 for (p
= name
; *p
!= '\0'; p
++)
1464 #if defined WINDOWS_NATIVE || defined __CYGWIN__ /* Native Windows or Cygwin */
1466 /* Canonicalize a Windows native locale name to a Unix locale name.
1467 NAME is a sufficiently large buffer.
1468 On input, it contains the Windows locale name.
1469 On output, it contains the Unix locale name. */
1470 # if !defined IN_LIBINTL
1474 gl_locale_name_canonicalize (char *name
)
1476 /* FIXME: This is probably incomplete: it does not handle "zh-Hans" and
1480 for (p
= name
; *p
!= '\0'; p
++)
1485 for (; *p
!= '\0'; p
++)
1487 if (*p
>= 'a' && *p
<= 'z')
1499 # if !defined IN_LIBINTL
1503 gl_locale_name_from_win32_LANGID (LANGID langid
)
1505 /* Activate the new code only when the GETTEXT_MUI environment variable is
1506 set, for the time being, since the new code is not well tested. */
1507 if (getenv ("GETTEXT_MUI") != NULL
)
1509 static char namebuf
[256];
1511 /* Query the system's notion of locale name.
1512 On Windows95/98/ME, GetLocaleInfoA returns some incorrect results.
1513 But we don't need to support systems that are so old. */
1514 if (GetLocaleInfoA (MAKELCID (langid
, SORT_DEFAULT
), LOCALE_SNAME
,
1515 namebuf
, sizeof (namebuf
) - 1))
1517 /* Convert it to a Unix locale name. */
1518 gl_locale_name_canonicalize (namebuf
);
1522 /* Internet Explorer has an LCID to RFC3066 name mapping stored in
1523 HKEY_CLASSES_ROOT\Mime\Database\Rfc1766. But we better don't use that
1524 since IE's i18n subsystem is known to be inconsistent with the native
1525 Windows base (e.g. they have different character conversion facilities
1526 that produce different results). */
1527 /* Use our own table. */
1531 /* Split into language and territory part. */
1532 primary
= PRIMARYLANGID (langid
);
1533 sub
= SUBLANGID (langid
);
1535 /* Dispatch on language.
1536 See also https://www.unicode.org/unicode/onlinedat/languages.html .
1537 For details about languages, see https://www.ethnologue.com/ . */
1540 case LANG_AFRIKAANS
:
1543 case SUBLANG_AFRIKAANS_SOUTH_AFRICA
: return "af_ZA";
1549 case SUBLANG_ALBANIAN_ALBANIA
: return "sq_AL";
1555 case SUBLANG_ALSATIAN_FRANCE
: return "gsw_FR";
1561 case SUBLANG_AMHARIC_ETHIOPIA
: return "am_ET";
1567 case SUBLANG_ARABIC_SAUDI_ARABIA
: return "ar_SA";
1568 case SUBLANG_ARABIC_IRAQ
: return "ar_IQ";
1569 case SUBLANG_ARABIC_EGYPT
: return "ar_EG";
1570 case SUBLANG_ARABIC_LIBYA
: return "ar_LY";
1571 case SUBLANG_ARABIC_ALGERIA
: return "ar_DZ";
1572 case SUBLANG_ARABIC_MOROCCO
: return "ar_MA";
1573 case SUBLANG_ARABIC_TUNISIA
: return "ar_TN";
1574 case SUBLANG_ARABIC_OMAN
: return "ar_OM";
1575 case SUBLANG_ARABIC_YEMEN
: return "ar_YE";
1576 case SUBLANG_ARABIC_SYRIA
: return "ar_SY";
1577 case SUBLANG_ARABIC_JORDAN
: return "ar_JO";
1578 case SUBLANG_ARABIC_LEBANON
: return "ar_LB";
1579 case SUBLANG_ARABIC_KUWAIT
: return "ar_KW";
1580 case SUBLANG_ARABIC_UAE
: return "ar_AE";
1581 case SUBLANG_ARABIC_BAHRAIN
: return "ar_BH";
1582 case SUBLANG_ARABIC_QATAR
: return "ar_QA";
1588 case SUBLANG_ARMENIAN_ARMENIA
: return "hy_AM";
1594 case SUBLANG_ASSAMESE_INDIA
: return "as_IN";
1600 /* FIXME: Adjust this when Azerbaijani locales appear on Unix. */
1601 case 0x1e: return "az@latin";
1602 case SUBLANG_AZERI_LATIN
: return "az_AZ@latin";
1603 case 0x1d: return "az@cyrillic";
1604 case SUBLANG_AZERI_CYRILLIC
: return "az_AZ@cyrillic";
1610 case SUBLANG_BASHKIR_RUSSIA
: return "ba_RU";
1616 case SUBLANG_BASQUE_BASQUE
: return "eu_ES";
1618 return "eu"; /* Ambiguous: could be "eu_ES" or "eu_FR". */
1619 case LANG_BELARUSIAN
:
1622 case SUBLANG_BELARUSIAN_BELARUS
: return "be_BY";
1628 case SUBLANG_BENGALI_INDIA
: return "bn_IN";
1629 case SUBLANG_BENGALI_BANGLADESH
: return "bn_BD";
1635 case SUBLANG_BRETON_FRANCE
: return "br_FR";
1638 case LANG_BULGARIAN
:
1641 case SUBLANG_BULGARIAN_BULGARIA
: return "bg_BG";
1647 case SUBLANG_DEFAULT
: return "my_MM";
1650 case LANG_CAMBODIAN
:
1653 case SUBLANG_CAMBODIAN_CAMBODIA
: return "km_KH";
1659 case SUBLANG_CATALAN_SPAIN
: return "ca_ES";
1665 case SUBLANG_DEFAULT
: return "chr_US";
1671 case SUBLANG_CHINESE_TRADITIONAL
: case 0x1f: return "zh_TW";
1672 case SUBLANG_CHINESE_SIMPLIFIED
: case 0x00: return "zh_CN";
1673 case SUBLANG_CHINESE_HONGKONG
: return "zh_HK"; /* traditional */
1674 case SUBLANG_CHINESE_SINGAPORE
: return "zh_SG"; /* simplified */
1675 case SUBLANG_CHINESE_MACAU
: return "zh_MO"; /* traditional */
1681 case SUBLANG_CORSICAN_FRANCE
: return "co_FR";
1684 case LANG_CROATIAN
: /* LANG_CROATIAN == LANG_SERBIAN == LANG_BOSNIAN
1685 * What used to be called Serbo-Croatian
1686 * should really now be two separate
1687 * languages because of political reasons.
1688 * (Says tml, who knows nothing about Serbian
1690 * (I can feel those flames coming already.)
1695 case 0x00: return "hr";
1696 case SUBLANG_CROATIAN_CROATIA
: return "hr_HR";
1697 case SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN
: return "hr_BA";
1699 case 0x1f: return "sr";
1700 case 0x1c: return "sr"; /* latin */
1701 case SUBLANG_SERBIAN_LATIN
: return "sr_CS"; /* latin */
1702 case 0x09: return "sr_RS"; /* latin */
1703 case 0x0b: return "sr_ME"; /* latin */
1704 case 0x06: return "sr_BA"; /* latin */
1705 case 0x1b: return "sr@cyrillic";
1706 case SUBLANG_SERBIAN_CYRILLIC
: return "sr_CS@cyrillic";
1707 case 0x0a: return "sr_RS@cyrillic";
1708 case 0x0c: return "sr_ME@cyrillic";
1709 case 0x07: return "sr_BA@cyrillic";
1711 case 0x1e: return "bs";
1712 case 0x1a: return "bs"; /* latin */
1713 case SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN
: return "bs_BA"; /* latin */
1714 case 0x19: return "bs@cyrillic";
1715 case SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC
: return "bs_BA@cyrillic";
1721 case SUBLANG_CZECH_CZECH_REPUBLIC
: return "cs_CZ";
1727 case SUBLANG_DANISH_DENMARK
: return "da_DK";
1731 /* FIXME: Adjust this when such locales appear on Unix. */
1734 case SUBLANG_DARI_AFGHANISTAN
: return "prs_AF";
1740 case SUBLANG_DIVEHI_MALDIVES
: return "dv_MV";
1746 case SUBLANG_DUTCH
: return "nl_NL";
1747 case SUBLANG_DUTCH_BELGIAN
: /* FLEMISH, VLAAMS */ return "nl_BE";
1748 case SUBLANG_DUTCH_SURINAM
: return "nl_SR";
1754 case SUBLANG_DEFAULT
: return "bin_NG";
1760 /* SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. Heh. I thought
1761 * English was the language spoken in England.
1764 case SUBLANG_ENGLISH_US
: return "en_US";
1765 case SUBLANG_ENGLISH_UK
: return "en_GB";
1766 case SUBLANG_ENGLISH_AUS
: return "en_AU";
1767 case SUBLANG_ENGLISH_CAN
: return "en_CA";
1768 case SUBLANG_ENGLISH_NZ
: return "en_NZ";
1769 case SUBLANG_ENGLISH_EIRE
: return "en_IE";
1770 case SUBLANG_ENGLISH_SOUTH_AFRICA
: return "en_ZA";
1771 case SUBLANG_ENGLISH_JAMAICA
: return "en_JM";
1772 case SUBLANG_ENGLISH_CARIBBEAN
: return "en_GD"; /* Grenada? */
1773 case SUBLANG_ENGLISH_BELIZE
: return "en_BZ";
1774 case SUBLANG_ENGLISH_TRINIDAD
: return "en_TT";
1775 case SUBLANG_ENGLISH_ZIMBABWE
: return "en_ZW";
1776 case SUBLANG_ENGLISH_PHILIPPINES
: return "en_PH";
1777 case SUBLANG_ENGLISH_INDONESIA
: return "en_ID";
1778 case SUBLANG_ENGLISH_HONGKONG
: return "en_HK";
1779 case SUBLANG_ENGLISH_INDIA
: return "en_IN";
1780 case SUBLANG_ENGLISH_MALAYSIA
: return "en_MY";
1781 case SUBLANG_ENGLISH_SINGAPORE
: return "en_SG";
1787 case SUBLANG_ESTONIAN_ESTONIA
: return "et_EE";
1793 case SUBLANG_FAEROESE_FAROE_ISLANDS
: return "fo_FO";
1799 case SUBLANG_FARSI_IRAN
: return "fa_IR";
1805 case SUBLANG_FINNISH_FINLAND
: return "fi_FI";
1811 case SUBLANG_FRENCH
: return "fr_FR";
1812 case SUBLANG_FRENCH_BELGIAN
: /* WALLOON */ return "fr_BE";
1813 case SUBLANG_FRENCH_CANADIAN
: return "fr_CA";
1814 case SUBLANG_FRENCH_SWISS
: return "fr_CH";
1815 case SUBLANG_FRENCH_LUXEMBOURG
: return "fr_LU";
1816 case SUBLANG_FRENCH_MONACO
: return "fr_MC";
1817 case SUBLANG_FRENCH_WESTINDIES
: return "fr"; /* Caribbean? */
1818 case SUBLANG_FRENCH_REUNION
: return "fr_RE";
1819 case SUBLANG_FRENCH_CONGO
: return "fr_CG";
1820 case SUBLANG_FRENCH_SENEGAL
: return "fr_SN";
1821 case SUBLANG_FRENCH_CAMEROON
: return "fr_CM";
1822 case SUBLANG_FRENCH_COTEDIVOIRE
: return "fr_CI";
1823 case SUBLANG_FRENCH_MALI
: return "fr_ML";
1824 case SUBLANG_FRENCH_MOROCCO
: return "fr_MA";
1825 case SUBLANG_FRENCH_HAITI
: return "fr_HT";
1831 case SUBLANG_FRISIAN_NETHERLANDS
: return "fy_NL";
1835 /* Spoken in Nigeria, Guinea, Senegal, Mali, Niger, Cameroon, Benin. */
1838 case SUBLANG_DEFAULT
: return "ff_NG";
1844 case 0x01: /* SCOTTISH */
1845 /* old, superseded by LANG_SCOTTISH_GAELIC */
1847 case SUBLANG_IRISH_IRELAND
: return "ga_IE";
1853 case SUBLANG_GALICIAN_SPAIN
: return "gl_ES";
1859 case SUBLANG_GEORGIAN_GEORGIA
: return "ka_GE";
1865 case SUBLANG_GERMAN
: return "de_DE";
1866 case SUBLANG_GERMAN_SWISS
: return "de_CH";
1867 case SUBLANG_GERMAN_AUSTRIAN
: return "de_AT";
1868 case SUBLANG_GERMAN_LUXEMBOURG
: return "de_LU";
1869 case SUBLANG_GERMAN_LIECHTENSTEIN
: return "de_LI";
1875 case SUBLANG_GREEK_GREECE
: return "el_GR";
1878 case LANG_GREENLANDIC
:
1881 case SUBLANG_GREENLANDIC_GREENLAND
: return "kl_GL";
1887 case SUBLANG_DEFAULT
: return "gn_PY";
1893 case SUBLANG_GUJARATI_INDIA
: return "gu_IN";
1899 case 0x1f: return "ha";
1900 case SUBLANG_HAUSA_NIGERIA_LATIN
: return "ha_NG";
1904 /* FIXME: Do they mean Hawaiian ("haw_US", 1000 speakers)
1905 or Hawaii Creole English ("cpe_US", 600000 speakers)? */
1908 case SUBLANG_DEFAULT
: return "cpe_US";
1914 case SUBLANG_HEBREW_ISRAEL
: return "he_IL";
1920 case SUBLANG_HINDI_INDIA
: return "hi_IN";
1923 case LANG_HUNGARIAN
:
1926 case SUBLANG_HUNGARIAN_HUNGARY
: return "hu_HU";
1932 case SUBLANG_DEFAULT
: return "nic_NG";
1935 case LANG_ICELANDIC
:
1938 case SUBLANG_ICELANDIC_ICELAND
: return "is_IS";
1944 case SUBLANG_IGBO_NIGERIA
: return "ig_NG";
1947 case LANG_INDONESIAN
:
1950 case SUBLANG_INDONESIAN_INDONESIA
: return "id_ID";
1953 case LANG_INUKTITUT
:
1956 case 0x1e: return "iu"; /* syllabic */
1957 case SUBLANG_INUKTITUT_CANADA
: return "iu_CA"; /* syllabic */
1958 case 0x1f: return "iu@latin";
1959 case SUBLANG_INUKTITUT_CANADA_LATIN
: return "iu_CA@latin";
1965 case SUBLANG_ITALIAN
: return "it_IT";
1966 case SUBLANG_ITALIAN_SWISS
: return "it_CH";
1972 case SUBLANG_JAPANESE_JAPAN
: return "ja_JP";
1978 case SUBLANG_KANNADA_INDIA
: return "kn_IN";
1984 case SUBLANG_DEFAULT
: return "kr_NG";
1990 case SUBLANG_DEFAULT
: return "ks_PK";
1991 case SUBLANG_KASHMIRI_INDIA
: return "ks_IN";
1997 case SUBLANG_KAZAK_KAZAKHSTAN
: return "kk_KZ";
2001 /* FIXME: Adjust this when such locales appear on Unix. */
2004 case SUBLANG_KICHE_GUATEMALA
: return "qut_GT";
2007 case LANG_KINYARWANDA
:
2010 case SUBLANG_KINYARWANDA_RWANDA
: return "rw_RW";
2014 /* FIXME: Adjust this when such locales appear on Unix. */
2017 case SUBLANG_KONKANI_INDIA
: return "kok_IN";
2023 case SUBLANG_DEFAULT
: return "ko_KR";
2029 case SUBLANG_KYRGYZ_KYRGYZSTAN
: return "ky_KG";
2035 case SUBLANG_LAO_LAOS
: return "lo_LA";
2041 case SUBLANG_DEFAULT
: return "la_VA";
2047 case SUBLANG_LATVIAN_LATVIA
: return "lv_LV";
2050 case LANG_LITHUANIAN
:
2053 case SUBLANG_LITHUANIAN_LITHUANIA
: return "lt_LT";
2056 case LANG_LUXEMBOURGISH
:
2059 case SUBLANG_LUXEMBOURGISH_LUXEMBOURG
: return "lb_LU";
2062 case LANG_MACEDONIAN
:
2065 case SUBLANG_MACEDONIAN_MACEDONIA
: return "mk_MK";
2071 case SUBLANG_MALAY_MALAYSIA
: return "ms_MY";
2072 case SUBLANG_MALAY_BRUNEI_DARUSSALAM
: return "ms_BN";
2075 case LANG_MALAYALAM
:
2078 case SUBLANG_MALAYALAM_INDIA
: return "ml_IN";
2084 case SUBLANG_MALTESE_MALTA
: return "mt_MT";
2088 /* FIXME: Adjust this when such locales appear on Unix. */
2091 case SUBLANG_DEFAULT
: return "mni_IN";
2097 case SUBLANG_MAORI_NEW_ZEALAND
: return "mi_NZ";
2100 case LANG_MAPUDUNGUN
:
2103 case SUBLANG_MAPUDUNGUN_CHILE
: return "arn_CL";
2109 case SUBLANG_MARATHI_INDIA
: return "mr_IN";
2115 case SUBLANG_MOHAWK_CANADA
: return "moh_CA";
2118 case LANG_MONGOLIAN
:
2121 case SUBLANG_MONGOLIAN_CYRILLIC_MONGOLIA
: case 0x1e: return "mn_MN";
2122 case SUBLANG_MONGOLIAN_PRC
: case 0x1f: return "mn_CN";
2124 return "mn"; /* Ambiguous: could be "mn_CN" or "mn_MN". */
2128 case SUBLANG_NEPALI_NEPAL
: return "ne_NP";
2129 case SUBLANG_NEPALI_INDIA
: return "ne_IN";
2132 case LANG_NORWEGIAN
:
2135 case 0x1f: return "nb";
2136 case SUBLANG_NORWEGIAN_BOKMAL
: return "nb_NO";
2137 case 0x1e: return "nn";
2138 case SUBLANG_NORWEGIAN_NYNORSK
: return "nn_NO";
2144 case SUBLANG_OCCITAN_FRANCE
: return "oc_FR";
2150 case SUBLANG_ORIYA_INDIA
: return "or_IN";
2156 case SUBLANG_DEFAULT
: return "om_ET";
2159 case LANG_PAPIAMENTU
:
2162 case SUBLANG_DEFAULT
: return "pap_AN";
2168 case SUBLANG_PASHTO_AFGHANISTAN
: return "ps_AF";
2170 return "ps"; /* Ambiguous: could be "ps_PK" or "ps_AF". */
2174 case SUBLANG_POLISH_POLAND
: return "pl_PL";
2177 case LANG_PORTUGUESE
:
2180 /* Hmm. SUBLANG_PORTUGUESE_BRAZILIAN == SUBLANG_DEFAULT.
2181 Same phenomenon as SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. */
2182 case SUBLANG_PORTUGUESE_BRAZILIAN
: return "pt_BR";
2183 case SUBLANG_PORTUGUESE
: return "pt_PT";
2189 case SUBLANG_PUNJABI_INDIA
: return "pa_IN"; /* Gurmukhi script */
2190 case SUBLANG_PUNJABI_PAKISTAN
: return "pa_PK"; /* Arabic script */
2194 /* Note: Microsoft uses the non-ISO language code "quz". */
2197 case SUBLANG_QUECHUA_BOLIVIA
: return "qu_BO";
2198 case SUBLANG_QUECHUA_ECUADOR
: return "qu_EC";
2199 case SUBLANG_QUECHUA_PERU
: return "qu_PE";
2205 case SUBLANG_ROMANIAN_ROMANIA
: return "ro_RO";
2206 case SUBLANG_ROMANIAN_MOLDOVA
: return "ro_MD";
2212 case SUBLANG_ROMANSH_SWITZERLAND
: return "rm_CH";
2218 case SUBLANG_RUSSIAN_RUSSIA
: return "ru_RU";
2219 case SUBLANG_RUSSIAN_MOLDAVIA
: return "ru_MD";
2221 return "ru"; /* Ambiguous: could be "ru_RU" or "ru_UA" or "ru_MD". */
2226 case 0x00: return "se";
2227 case SUBLANG_SAMI_NORTHERN_NORWAY
: return "se_NO";
2228 case SUBLANG_SAMI_NORTHERN_SWEDEN
: return "se_SE";
2229 case SUBLANG_SAMI_NORTHERN_FINLAND
: return "se_FI";
2231 case 0x1f: return "smj";
2232 case SUBLANG_SAMI_LULE_NORWAY
: return "smj_NO";
2233 case SUBLANG_SAMI_LULE_SWEDEN
: return "smj_SE";
2235 case 0x1e: return "sma";
2236 case SUBLANG_SAMI_SOUTHERN_NORWAY
: return "sma_NO";
2237 case SUBLANG_SAMI_SOUTHERN_SWEDEN
: return "sma_SE";
2239 case 0x1d: return "sms";
2240 case SUBLANG_SAMI_SKOLT_FINLAND
: return "sms_FI";
2242 case 0x1c: return "smn";
2243 case SUBLANG_SAMI_INARI_FINLAND
: return "smn_FI";
2245 return "se"; /* or "smi"? */
2249 case SUBLANG_SANSKRIT_INDIA
: return "sa_IN";
2252 case LANG_SCOTTISH_GAELIC
:
2255 case SUBLANG_DEFAULT
: return "gd_GB";
2261 case SUBLANG_SINDHI_INDIA
: return "sd_IN";
2262 case SUBLANG_SINDHI_PAKISTAN
: return "sd_PK";
2263 /*case SUBLANG_SINDHI_AFGHANISTAN: return "sd_AF";*/
2266 case LANG_SINHALESE
:
2269 case SUBLANG_SINHALESE_SRI_LANKA
: return "si_LK";
2275 case SUBLANG_SLOVAK_SLOVAKIA
: return "sk_SK";
2278 case LANG_SLOVENIAN
:
2281 case SUBLANG_SLOVENIAN_SLOVENIA
: return "sl_SI";
2287 case SUBLANG_DEFAULT
: return "so_SO";
2291 /* FIXME: Adjust this when such locales appear on Unix. */
2295 case 0x00: return "hsb";
2296 case SUBLANG_UPPER_SORBIAN_GERMANY
: return "hsb_DE";
2298 case 0x1f: return "dsb";
2299 case SUBLANG_LOWER_SORBIAN_GERMANY
: return "dsb_DE";
2303 /* <https://docs.microsoft.com/en-us/windows/desktop/Intl/language-identifier-constants-and-strings>
2304 calls it "Sesotho sa Leboa"; according to
2305 <https://www.ethnologue.com/show_language.asp?code=nso>
2306 <https://www.ethnologue.com/show_language.asp?code=sot>
2307 it's the same as Northern Sotho. */
2310 case SUBLANG_SOTHO_SOUTH_AFRICA
: return "nso_ZA";
2316 case SUBLANG_SPANISH
: return "es_ES";
2317 case SUBLANG_SPANISH_MEXICAN
: return "es_MX";
2318 case SUBLANG_SPANISH_MODERN
:
2319 return "es_ES@modern"; /* not seen on Unix */
2320 case SUBLANG_SPANISH_GUATEMALA
: return "es_GT";
2321 case SUBLANG_SPANISH_COSTA_RICA
: return "es_CR";
2322 case SUBLANG_SPANISH_PANAMA
: return "es_PA";
2323 case SUBLANG_SPANISH_DOMINICAN_REPUBLIC
: return "es_DO";
2324 case SUBLANG_SPANISH_VENEZUELA
: return "es_VE";
2325 case SUBLANG_SPANISH_COLOMBIA
: return "es_CO";
2326 case SUBLANG_SPANISH_PERU
: return "es_PE";
2327 case SUBLANG_SPANISH_ARGENTINA
: return "es_AR";
2328 case SUBLANG_SPANISH_ECUADOR
: return "es_EC";
2329 case SUBLANG_SPANISH_CHILE
: return "es_CL";
2330 case SUBLANG_SPANISH_URUGUAY
: return "es_UY";
2331 case SUBLANG_SPANISH_PARAGUAY
: return "es_PY";
2332 case SUBLANG_SPANISH_BOLIVIA
: return "es_BO";
2333 case SUBLANG_SPANISH_EL_SALVADOR
: return "es_SV";
2334 case SUBLANG_SPANISH_HONDURAS
: return "es_HN";
2335 case SUBLANG_SPANISH_NICARAGUA
: return "es_NI";
2336 case SUBLANG_SPANISH_PUERTO_RICO
: return "es_PR";
2337 case SUBLANG_SPANISH_US
: return "es_US";
2343 case SUBLANG_DEFAULT
: return "bnt_TZ"; /* or "st_LS" or "nso_ZA"? */
2349 case SUBLANG_SWAHILI_KENYA
: return "sw_KE";
2355 case SUBLANG_SWEDISH_SWEDEN
: return "sv_SE";
2356 case SUBLANG_SWEDISH_FINLAND
: return "sv_FI";
2362 case SUBLANG_SYRIAC_SYRIA
: return "syr_SY"; /* An extinct language. */
2368 case SUBLANG_TAGALOG_PHILIPPINES
: return "tl_PH"; /* or "fil_PH"? */
2370 return "tl"; /* or "fil"? */
2374 case 0x1f: return "tg";
2375 case SUBLANG_TAJIK_TAJIKISTAN
: return "tg_TJ";
2378 case LANG_TAMAZIGHT
:
2379 /* Note: Microsoft uses the non-ISO language code "tmz". */
2382 /* FIXME: Adjust this when Tamazight locales appear on Unix. */
2383 case SUBLANG_TAMAZIGHT_ARABIC
: return "ber_MA@arabic";
2384 case 0x1f: return "ber@latin";
2385 case SUBLANG_TAMAZIGHT_ALGERIA_LATIN
: return "ber_DZ@latin";
2391 case SUBLANG_TAMIL_INDIA
: return "ta_IN";
2393 return "ta"; /* Ambiguous: could be "ta_IN" or "ta_LK" or "ta_SG". */
2397 case SUBLANG_TATAR_RUSSIA
: return "tt_RU";
2403 case SUBLANG_TELUGU_INDIA
: return "te_IN";
2409 case SUBLANG_THAI_THAILAND
: return "th_TH";
2415 case SUBLANG_TIBETAN_PRC
:
2416 /* Most Tibetans would not like "bo_CN". But Tibet does not yet
2417 have a country code of its own. */
2419 case SUBLANG_TIBETAN_BHUTAN
: return "bo_BT";
2425 case SUBLANG_TIGRINYA_ETHIOPIA
: return "ti_ET";
2426 case SUBLANG_TIGRINYA_ERITREA
: return "ti_ER";
2432 case SUBLANG_DEFAULT
: return "ts_ZA";
2436 /* Spoken in South Africa, Botswana. */
2439 case SUBLANG_TSWANA_SOUTH_AFRICA
: return "tn_ZA";
2445 case SUBLANG_TURKISH_TURKEY
: return "tr_TR";
2451 case SUBLANG_TURKMEN_TURKMENISTAN
: return "tk_TM";
2457 case SUBLANG_UIGHUR_PRC
: return "ug_CN";
2460 case LANG_UKRAINIAN
:
2463 case SUBLANG_UKRAINIAN_UKRAINE
: return "uk_UA";
2469 case SUBLANG_URDU_PAKISTAN
: return "ur_PK";
2470 case SUBLANG_URDU_INDIA
: return "ur_IN";
2476 case 0x1f: return "uz";
2477 case SUBLANG_UZBEK_LATIN
: return "uz_UZ";
2478 case 0x1e: return "uz@cyrillic";
2479 case SUBLANG_UZBEK_CYRILLIC
: return "uz_UZ@cyrillic";
2485 case SUBLANG_DEFAULT
: return "ve_ZA";
2488 case LANG_VIETNAMESE
:
2491 case SUBLANG_VIETNAMESE_VIETNAM
: return "vi_VN";
2497 case SUBLANG_WELSH_UNITED_KINGDOM
: return "cy_GB";
2503 case SUBLANG_WOLOF_SENEGAL
: return "wo_SN";
2509 case SUBLANG_XHOSA_SOUTH_AFRICA
: return "xh_ZA";
2515 case SUBLANG_YAKUT_RUSSIA
: return "sah_RU";
2521 case SUBLANG_YI_PRC
: return "ii_CN";
2527 case SUBLANG_DEFAULT
: return "yi_IL";
2533 case SUBLANG_YORUBA_NIGERIA
: return "yo_NG";
2539 case SUBLANG_ZULU_SOUTH_AFRICA
: return "zu_ZA";
2542 default: return "C";
2547 # if !defined IN_LIBINTL
2551 gl_locale_name_from_win32_LCID (LCID lcid
)
2555 /* Strip off the sorting rules, keep only the language part. */
2556 langid
= LANGIDFROMLCID (lcid
);
2558 return gl_locale_name_from_win32_LANGID (langid
);
2561 # ifdef WINDOWS_NATIVE
2563 /* Two variables to interface between get_lcid and the EnumLocales
2564 callback function below. */
2565 static LCID found_lcid
;
2566 static char lname
[LC_MAX
* (LOCALE_NAME_MAX_LENGTH
+ 1) + 1];
2568 /* Callback function for EnumLocales. */
2569 static BOOL CALLBACK
2570 enum_locales_fn (LPSTR locale_num_str
)
2573 char locval
[2 * LOCALE_NAME_MAX_LENGTH
+ 1 + 1];
2574 LCID try_lcid
= strtoul (locale_num_str
, &endp
, 16);
2576 if (GetLocaleInfo (try_lcid
, LOCALE_SENGLANGUAGE
,
2577 locval
, LOCALE_NAME_MAX_LENGTH
))
2579 strcat (locval
, "_");
2580 if (GetLocaleInfo (try_lcid
, LOCALE_SENGCOUNTRY
,
2581 locval
+ strlen (locval
), LOCALE_NAME_MAX_LENGTH
))
2583 size_t locval_len
= strlen (locval
);
2585 if (strncmp (locval
, lname
, locval_len
) == 0
2586 && (lname
[locval_len
] == '.'
2587 || lname
[locval_len
] == '\0'))
2589 found_lcid
= try_lcid
;
2597 /* This lock protects the get_lcid against multiple simultaneous calls. */
2598 gl_lock_define_initialized(static, get_lcid_lock
)
2600 /* Return the Locale ID (LCID) number given the locale's name, a
2601 string, in LOCALE_NAME. This works by enumerating all the locales
2602 supported by the system, until we find one whose name matches
2605 get_lcid (const char *locale_name
)
2607 /* A simple cache. */
2608 static LCID last_lcid
;
2609 static char last_locale
[1000];
2611 /* Lock while looking for an LCID, to protect access to static
2612 variables: last_lcid, last_locale, found_lcid, and lname. */
2613 gl_lock_lock (get_lcid_lock
);
2614 if (last_lcid
> 0 && strcmp (locale_name
, last_locale
) == 0)
2616 gl_lock_unlock (get_lcid_lock
);
2619 strncpy (lname
, locale_name
, sizeof (lname
) - 1);
2620 lname
[sizeof (lname
) - 1] = '\0';
2622 EnumSystemLocales (enum_locales_fn
, LCID_SUPPORTED
);
2625 last_lcid
= found_lcid
;
2626 strcpy (last_locale
, locale_name
);
2628 gl_lock_unlock (get_lcid_lock
);
2636 #if LOCALENAME_ENHANCE_LOCALE_FUNCS
2638 /* Define a local struniq() function. */
2639 # include "struniq.h"
2641 /* The 'locale_t' object does not contain the names of the locale categories.
2642 We have to associate them with the object through a hash table.
2643 The hash table is defined in localename-table.[hc]. */
2645 /* Returns the name of a given locale category in a given locale_t object,
2646 allocated as a string with indefinite extent. */
2648 get_locale_t_name (int category
, locale_t locale
)
2650 if (category
== LC_ALL
)
2651 /* Invalid argument. */
2653 if (locale
== LC_GLOBAL_LOCALE
)
2655 /* Query the global locale. */
2656 const char *name
= setlocale_null (category
);
2658 return struniq (name
);
2660 /* Should normally not happen. */
2665 # if HAVE_AIX72_LOCALES
2666 if (category
== LC_MESSAGES
)
2668 const char *name
= ((__locale_t
) locale
)->locale_name
;
2670 return struniq (name
);
2673 /* Look up the names in the hash table. */
2674 size_t hashcode
= locale_hash_function (locale
);
2675 size_t slot
= hashcode
% LOCALE_HASH_TABLE_SIZE
;
2676 /* If the locale was not found in the table, return "". This can
2677 happen if the application uses the original newlocale()/duplocale()
2678 functions instead of the overridden ones. */
2679 const char *name
= "";
2680 struct locale_hash_node
*p
;
2681 /* Lock while looking up the hash node. */
2682 gl_rwlock_rdlock (locale_lock
);
2683 for (p
= locale_hash_table
[slot
]; p
!= NULL
; p
= p
->next
)
2684 if (p
->locale
== locale
)
2686 name
= p
->names
.category_name
[category
];
2689 gl_rwlock_unlock (locale_lock
);
2694 # if !(defined newlocale && defined duplocale && defined freelocale)
2695 # error "newlocale, duplocale, freelocale not being replaced as expected!"
2698 /* newlocale() override. */
2700 newlocale (int category_mask
, const char *name
, locale_t base
)
2703 struct locale_categories_names names
;
2704 struct locale_hash_node
*node
;
2707 /* Make sure name has indefinite extent. */
2708 if (((LC_CTYPE_MASK
| LC_NUMERIC_MASK
| LC_TIME_MASK
| LC_COLLATE_MASK
2709 | LC_MONETARY_MASK
| LC_MESSAGES_MASK
)
2710 & category_mask
) != 0)
2711 name
= struniq (name
);
2713 /* Determine the category names of the result. */
2714 if (((LC_CTYPE_MASK
| LC_NUMERIC_MASK
| LC_TIME_MASK
| LC_COLLATE_MASK
2715 | LC_MONETARY_MASK
| LC_MESSAGES_MASK
)
2716 & ~category_mask
) == 0)
2718 /* Use name, ignore base. */
2721 name
= struniq (name
);
2722 for (category
= 0; category
< 6; category
++)
2723 names
.category_name
[category
] = name
;
2727 /* Use base, possibly also name. */
2732 for (category
= 0; category
< 6; category
++)
2739 mask
= LC_CTYPE_MASK
;
2742 mask
= LC_NUMERIC_MASK
;
2745 mask
= LC_TIME_MASK
;
2748 mask
= LC_COLLATE_MASK
;
2751 mask
= LC_MONETARY_MASK
;
2754 mask
= LC_MESSAGES_MASK
;
2759 names
.category_name
[category
] =
2760 ((mask
& category_mask
) != 0 ? name
: "C");
2763 else if (base
== LC_GLOBAL_LOCALE
)
2767 for (category
= 0; category
< 6; category
++)
2774 mask
= LC_CTYPE_MASK
;
2777 mask
= LC_NUMERIC_MASK
;
2780 mask
= LC_TIME_MASK
;
2783 mask
= LC_COLLATE_MASK
;
2786 mask
= LC_MONETARY_MASK
;
2789 mask
= LC_MESSAGES_MASK
;
2794 names
.category_name
[category
] =
2795 ((mask
& category_mask
) != 0
2797 : get_locale_t_name (category
, LC_GLOBAL_LOCALE
));
2802 /* Look up the names of base in the hash table. Like multiple calls
2803 of get_locale_t_name, but locking only once. */
2804 struct locale_hash_node
*p
;
2807 /* Lock while looking up the hash node. */
2808 gl_rwlock_rdlock (locale_lock
);
2809 for (p
= locale_hash_table
[locale_hash_function (base
) % LOCALE_HASH_TABLE_SIZE
];
2812 if (p
->locale
== base
)
2815 for (category
= 0; category
< 6; category
++)
2822 mask
= LC_CTYPE_MASK
;
2825 mask
= LC_NUMERIC_MASK
;
2828 mask
= LC_TIME_MASK
;
2831 mask
= LC_COLLATE_MASK
;
2834 mask
= LC_MONETARY_MASK
;
2837 mask
= LC_MESSAGES_MASK
;
2842 names
.category_name
[category
] =
2843 ((mask
& category_mask
) != 0
2845 : (p
!= NULL
? p
->names
.category_name
[category
] : ""));
2848 gl_rwlock_unlock (locale_lock
);
2852 node
= (struct locale_hash_node
*) malloc (sizeof (struct locale_hash_node
));
2854 /* errno is set to ENOMEM. */
2857 result
= newlocale (category_mask
, name
, base
);
2864 /* Fill the hash node. */
2865 node
->locale
= result
;
2866 node
->names
= names
;
2868 /* Insert it in the hash table. */
2870 size_t hashcode
= locale_hash_function (result
);
2871 size_t slot
= hashcode
% LOCALE_HASH_TABLE_SIZE
;
2872 struct locale_hash_node
*p
;
2874 /* Lock while inserting the new node. */
2875 gl_rwlock_wrlock (locale_lock
);
2876 for (p
= locale_hash_table
[slot
]; p
!= NULL
; p
= p
->next
)
2877 if (p
->locale
== result
)
2879 /* This can happen if the application uses the original freelocale()
2880 function instead of the overridden one. */
2881 p
->names
= node
->names
;
2886 node
->next
= locale_hash_table
[slot
];
2887 locale_hash_table
[slot
] = node
;
2890 gl_rwlock_unlock (locale_lock
);
2899 /* duplocale() override. */
2901 duplocale (locale_t locale
)
2904 struct locale_hash_node
*node
;
2908 /* Invalid argument. */
2911 node
= (struct locale_hash_node
*) malloc (sizeof (struct locale_hash_node
));
2913 /* errno is set to ENOMEM. */
2916 result
= duplocale (locale
);
2923 /* Fill the hash node. */
2924 node
->locale
= result
;
2925 if (locale
== LC_GLOBAL_LOCALE
)
2929 for (category
= 0; category
< 6; category
++)
2930 node
->names
.category_name
[category
] =
2931 get_locale_t_name (category
, LC_GLOBAL_LOCALE
);
2933 /* Lock before inserting the new node. */
2934 gl_rwlock_wrlock (locale_lock
);
2938 struct locale_hash_node
*p
;
2940 /* Lock once, for the lookup and the insertion. */
2941 gl_rwlock_wrlock (locale_lock
);
2943 for (p
= locale_hash_table
[locale_hash_function (locale
) % LOCALE_HASH_TABLE_SIZE
];
2946 if (p
->locale
== locale
)
2949 node
->names
= p
->names
;
2952 /* This can happen if the application uses the original
2953 newlocale()/duplocale() functions instead of the overridden
2957 for (category
= 0; category
< 6; category
++)
2958 node
->names
.category_name
[category
] = "";
2962 /* Insert it in the hash table. */
2964 size_t hashcode
= locale_hash_function (result
);
2965 size_t slot
= hashcode
% LOCALE_HASH_TABLE_SIZE
;
2966 struct locale_hash_node
*p
;
2968 for (p
= locale_hash_table
[slot
]; p
!= NULL
; p
= p
->next
)
2969 if (p
->locale
== result
)
2971 /* This can happen if the application uses the original freelocale()
2972 function instead of the overridden one. */
2973 p
->names
= node
->names
;
2978 node
->next
= locale_hash_table
[slot
];
2979 locale_hash_table
[slot
] = node
;
2982 gl_rwlock_unlock (locale_lock
);
2991 /* freelocale() override. */
2993 freelocale (locale_t locale
)
2996 if (locale
== NULL
|| locale
== LC_GLOBAL_LOCALE
)
2997 /* Invalid argument. */
3001 size_t hashcode
= locale_hash_function (locale
);
3002 size_t slot
= hashcode
% LOCALE_HASH_TABLE_SIZE
;
3003 struct locale_hash_node
*found
;
3004 struct locale_hash_node
**p
;
3007 /* Lock while removing the hash node. */
3008 gl_rwlock_wrlock (locale_lock
);
3009 for (p
= &locale_hash_table
[slot
]; *p
!= NULL
; p
= &(*p
)->next
)
3010 if ((*p
)->locale
== locale
)
3016 gl_rwlock_unlock (locale_lock
);
3020 freelocale (locale
);
3027 gl_locale_name_thread_unsafe (int category
, _GL_UNUSED
const char *categoryname
)
3029 if (category
== LC_ALL
)
3030 /* Invalid argument. */
3032 #if HAVE_GOOD_USELOCALE
3034 locale_t thread_locale
= uselocale (NULL
);
3035 if (thread_locale
!= LC_GLOBAL_LOCALE
)
3037 # if __GLIBC__ >= 2 && !defined __UCLIBC__
3038 /* Work around an incorrect definition of the _NL_LOCALE_NAME macro in
3040 See <https://sourceware.org/bugzilla/show_bug.cgi?id=10968>. */
3042 nl_langinfo (_NL_ITEM ((category
), _NL_ITEM_INDEX (-1)));
3043 if (name
[0] == '\0')
3044 /* Fallback code for glibc < 2.4, which did not implement
3045 nl_langinfo (_NL_LOCALE_NAME (category)). */
3046 name
= thread_locale
->__names
[category
];
3048 # elif defined __linux__ && HAVE_LANGINFO_H && defined NL_LOCALE_NAME
3050 return nl_langinfo_l (NL_LOCALE_NAME (category
), thread_locale
);
3051 # elif (defined __FreeBSD__ || defined __DragonFly__) || (defined __APPLE__ && defined __MACH__)
3052 /* FreeBSD, Mac OS X */
3058 mask
= LC_CTYPE_MASK
;
3061 mask
= LC_NUMERIC_MASK
;
3064 mask
= LC_TIME_MASK
;
3067 mask
= LC_COLLATE_MASK
;
3070 mask
= LC_MONETARY_MASK
;
3073 mask
= LC_MESSAGES_MASK
;
3075 default: /* We shouldn't get here. */
3078 return querylocale (mask
, thread_locale
);
3079 # elif defined __sun
3080 # if HAVE_GETLOCALENAME_L
3081 /* Solaris >= 12. */
3082 return getlocalename_l (category
, thread_locale
);
3083 # elif HAVE_SOLARIS114_LOCALES
3084 /* Solaris >= 11.4. */
3085 void *lcp
= (*thread_locale
)->core
.data
->lcp
;
3095 return ((const char * const *) lcp
)[category
];
3096 default: /* We shouldn't get here. */
3099 # elif HAVE_NAMELESS_LOCALES
3100 return get_locale_t_name (category
, thread_locale
);
3102 /* Solaris 11 OpenIndiana.
3103 For the internal structure of locale objects, see
3104 https://github.com/OpenIndiana/illumos-gate/blob/master/usr/src/lib/libc/port/locale/localeimpl.h */
3113 return ((const char * const *) thread_locale
)[category
];
3114 default: /* We shouldn't get here. */
3118 # elif defined _AIX && HAVE_NAMELESS_LOCALES
3119 return get_locale_t_name (category
, thread_locale
);
3120 # elif defined __CYGWIN__
3121 /* Cygwin < 2.6 lacks uselocale and thread-local locales altogether.
3122 Cygwin <= 2.6.1 lacks NL_LOCALE_NAME, requiring peeking inside
3123 an opaque struct. */
3124 # ifdef NL_LOCALE_NAME
3125 return nl_langinfo_l (NL_LOCALE_NAME (category
), thread_locale
);
3127 /* FIXME: Remove when we can assume new-enough Cygwin. */
3129 char categories
[7][32];
3131 return ((struct __locale_t
*) thread_locale
)->categories
[category
];
3133 # elif defined __HAIKU__
3134 /* Since 2022, Haiku has per-thread locales. locale_t is 'void *',
3135 but in fact a 'LocaleBackendData *'. */
3136 struct LocaleBackendData
{
3138 void /*BPrivate::Libroot::LocaleBackend*/ *backend
;
3139 void /*BPrivate::Libroot::LocaleDataBridge*/ *databridge
;
3141 void *thread_locale_backend
=
3142 ((struct LocaleBackendData
*) thread_locale
)->backend
;
3143 if (thread_locale_backend
!= NULL
)
3145 /* The only existing concrete subclass of
3146 BPrivate::Libroot::LocaleBackend is
3147 BPrivate::Libroot::ICULocaleBackend.
3148 Invoke the (non-virtual) method
3149 BPrivate::Libroot::ICULocaleBackend::_QueryLocale on it.
3150 This method is located in a separate shared library,
3151 libroot-addon-icu.so. */
3152 static void * volatile querylocale_method
/* = NULL */;
3153 static int volatile querylocale_found
/* = 0 */;
3154 /* Attempt to open this shared library, the first time we get
3156 if (querylocale_found
== 0)
3159 dlopen ("/boot/system/lib/libroot-addon-icu.so", 0);
3163 dlsym (handle
, "_ZN8BPrivate7Libroot16ICULocaleBackend12_QueryLocaleEi");
3166 querylocale_method
= sym
;
3167 querylocale_found
= 1;
3170 /* Could not find the symbol. */
3171 querylocale_found
= -1;
3174 /* Could not open the separate shared library. */
3175 querylocale_found
= -1;
3177 if (querylocale_found
> 0)
3179 /* The _QueryLocale method is a non-static C++ method with
3180 parameters (int category) and return type 'const char *'.
3182 haiku/headers/private/libroot/locale/ICULocaleBackend.h
3183 haiku/src/system/libroot/add-ons/icu/ICULocaleBackend.cpp
3184 This is the same as a C function with parameters
3185 (BPrivate::Libroot::LocaleBackend* this, int category)
3186 and return type 'const char *'. Invoke it. */
3187 const char * (*querylocale_func
) (void *, int) =
3188 (const char * (*) (void *, int)) querylocale_method
;
3189 return querylocale_func (thread_locale_backend
, category
);
3193 /* It's the "C" or "POSIX" locale. */
3195 # elif defined __ANDROID__
3196 return MB_CUR_MAX
== 4 ? "C.UTF-8" : "C";
3201 /* On WINDOWS_NATIVE, don't use GetThreadLocale() here, because when
3202 SetThreadLocale has not been called - which is a very frequent case -
3203 the value of GetThreadLocale() ignores past calls to 'setlocale'. */
3207 /* XPG3 defines the result of 'setlocale (category, NULL)' as:
3208 "Directs 'setlocale()' to query 'category' and return the current
3209 setting of 'local'."
3210 However it does not specify the exact format. Neither do SUSV2 and
3211 ISO C 99. So we can use this feature only on selected systems, where
3212 the return value has the XPG syntax
3213 language[_territory][.codeset][@modifier]
3217 - glibc systems (except for aliases from /usr/share/locale/locale.alias,
3218 that no one uses any more),
3224 - macOS, Cygwin (because these systems have a facility for customizing the
3225 default locale, and setlocale (category, NULL) ignores it and merely
3226 returns "C" or "C.UTF-8"),
3227 - OpenBSD (because on OpenBSD ≤ 6.1, LC_ALL does not set the LC_NUMERIC,
3228 LC_TIME, LC_COLLATE, LC_MONETARY categories).
3229 - AIX (because here the return value has the syntax
3230 language[_script]_territory[.codeset]
3231 e.g. zh_Hans_CN.UTF-8),
3232 - native Windows (because it has locale names such as French_France.1252),
3233 - Android (because it only supports the C and C.UTF-8 locales).
3235 #if defined _LIBC || ((defined __GLIBC__ && __GLIBC__ >= 2) && !defined __UCLIBC__) || MUSL_LIBC || defined __FreeBSD__ || defined __NetBSD__ || defined __sun || defined __HAIKU__
3236 # define HAVE_LOCALE_NULL
3240 gl_locale_name_posix_unsafe (int category
, _GL_UNUSED
const char *categoryname
)
3242 if (category
== LC_ALL
)
3243 /* Invalid argument. */
3245 #if defined WINDOWS_NATIVE
3246 if (LC_MIN
<= category
&& category
<= LC_MAX
)
3248 const char *locname
=
3249 /* setlocale_null (category) is identical to setlocale (category, NULL)
3250 on this platform. */
3251 setlocale (category
, NULL
);
3253 /* Convert locale name to LCID. We don't want to use
3254 LocaleNameToLCID because (a) it is only available since Vista,
3255 and (b) it doesn't accept locale names returned by 'setlocale'. */
3256 LCID lcid
= get_lcid (locname
);
3259 return gl_locale_name_from_win32_LCID (lcid
);
3263 const char *locname
;
3265 /* Use the POSIX methods of looking to 'LC_ALL', 'LC_xxx', and 'LANG'.
3266 On some systems this can be done by the 'setlocale' function itself. */
3267 #if defined HAVE_LC_MESSAGES && defined HAVE_LOCALE_NULL
3268 /* All platforms for which HAVE_LOCALE_NULL is defined happen to have
3269 SETLOCALE_NULL_ONE_MTSAFE defined to 1. Therefore it is OK, here,
3270 to call setlocale_null_unlocked instead of setlocale_null. */
3271 locname
= setlocale_null_unlocked (category
);
3273 /* On other systems we ignore what setlocale reports and instead look at the
3274 environment variables directly. This is necessary
3275 1. on systems which have a facility for customizing the default locale
3276 (macOS, native Windows, Cygwin) and where the system's setlocale()
3277 function ignores this default locale (macOS, Cygwin), in two cases:
3278 a. when the user missed to use the setlocale() override from libintl
3279 (for example by not including <libintl.h>),
3280 b. when setlocale supports only the "C" locale, such as on Cygwin
3281 1.5.x. In this case even the override from libintl cannot help.
3282 2. on all systems where setlocale supports only the "C" locale. */
3283 /* Strictly speaking, it is a POSIX violation to look at the environment
3284 variables regardless whether setlocale has been called or not. POSIX
3286 "For C-language programs, the POSIX locale shall be the
3287 default locale when the setlocale() function is not called."
3288 But we assume that all programs that use internationalized APIs call
3289 setlocale (LC_ALL, ""). */
3290 locname
= gl_locale_name_environ (category
, categoryname
);
3292 /* Convert the locale name from the format returned by setlocale() or found
3293 in the environment variables to the XPG syntax. */
3294 #if defined WINDOWS_NATIVE
3295 if (locname
!= NULL
)
3297 /* Convert locale name to LCID. We don't want to use
3298 LocaleNameToLCID because (a) it is only available since Vista,
3299 and (b) it doesn't accept locale names returned by 'setlocale'. */
3300 LCID lcid
= get_lcid (locname
);
3303 return gl_locale_name_from_win32_LCID (lcid
);
3311 gl_locale_name_environ (_GL_UNUSED
int category
, const char *categoryname
)
3315 /* Setting of LC_ALL overrides all other. */
3316 retval
= getenv ("LC_ALL");
3317 if (retval
!= NULL
&& retval
[0] != '\0')
3319 /* Next comes the name of the desired category. */
3320 retval
= getenv (categoryname
);
3321 if (retval
!= NULL
&& retval
[0] != '\0')
3323 /* Last possibility is the LANG environment variable. */
3324 retval
= getenv ("LANG");
3325 if (retval
!= NULL
&& retval
[0] != '\0')
3327 #if HAVE_CFPREFERENCESCOPYAPPVALUE
3328 /* Mac OS X 10.2 or newer.
3329 Ignore invalid LANG value set by the Terminal application. */
3330 if (strcmp (retval
, "UTF-8") != 0)
3332 #if defined __CYGWIN__
3334 Ignore dummy LANG value set by ~/.profile. */
3335 if (strcmp (retval
, "C.UTF-8") != 0)
3344 gl_locale_name_default (void)
3347 "All implementations shall define a locale as the default locale, to be
3348 invoked when no environment variables are set, or set to the empty
3349 string. This default locale can be the POSIX locale or any other
3350 implementation-defined locale. Some implementations may provide
3351 facilities for local installation administrators to set the default
3352 locale, customizing it for each location. POSIX:2001 does not require
3355 The systems with such a facility are Mac OS X and Windows: They provide a
3356 GUI that allows the user to choose a locale.
3357 - On Mac OS X, by default, none of LC_* or LANG are set. Starting with
3358 Mac OS X 10.4 or 10.5, LANG is set for processes launched by the
3359 'Terminal' application (but sometimes to an incorrect value "UTF-8").
3360 When no environment variable is set, setlocale (LC_ALL, "") uses the
3362 - On native Windows, by default, none of LC_* or LANG are set.
3363 When no environment variable is set, setlocale (LC_ALL, "") uses the
3364 locale chosen by the user.
3365 - On Cygwin 1.5.x, by default, none of LC_* or LANG are set.
3366 When no environment variable is set, setlocale (LC_ALL, "") uses the
3368 - On Cygwin 1.7, by default, LANG is set to "C.UTF-8" when the default
3369 ~/.profile is executed.
3370 When no environment variable is set, setlocale (LC_ALL, "") uses the
3371 "C.UTF-8" locale, which operates in the same way as the "C" locale.
3374 #if !(HAVE_CFPREFERENCESCOPYAPPVALUE || defined WINDOWS_NATIVE || defined __CYGWIN__)
3376 /* The system does not have a way of setting the locale, other than the
3377 POSIX specified environment variables. We use C as default locale. */
3382 /* Return an XPG style locale name language[_territory][@modifier].
3383 Don't even bother determining the codeset; it's not useful in this
3384 context, because message catalogs are not specific to a single
3387 # if HAVE_CFPREFERENCESCOPYAPPVALUE
3388 /* Mac OS X 10.4 or newer */
3389 /* Don't use the API introduced in Mac OS X 10.5, CFLocaleCopyCurrent,
3390 because in macOS 10.13.4 it has the following behaviour:
3391 When two or more languages are specified in the
3392 "System Preferences > Language & Region > Preferred Languages" panel,
3393 it returns en_CC where CC is the territory (even when English is not among
3394 the preferred languages!). What we want instead is what
3395 CFLocaleCopyCurrent returned in earlier macOS releases and what
3396 CFPreferencesCopyAppValue still returns, namely ll_CC where ll is the
3397 first among the preferred languages and CC is the territory. */
3399 /* Cache the locale name, since CoreFoundation calls are expensive. */
3400 static const char *cached_localename
;
3402 if (cached_localename
== NULL
)
3406 CFPreferencesCopyAppValue (CFSTR ("AppleLocale"),
3407 kCFPreferencesCurrentApplication
);
3408 if (value
!= NULL
&& CFGetTypeID (value
) == CFStringGetTypeID ())
3410 CFStringRef name
= (CFStringRef
)value
;
3412 if (CFStringGetCString (name
, namebuf
, sizeof (namebuf
),
3413 kCFStringEncodingASCII
))
3415 gl_locale_name_canonicalize (namebuf
);
3416 cached_localename
= strdup (namebuf
);
3419 if (cached_localename
== NULL
)
3420 cached_localename
= "C";
3422 return cached_localename
;
3427 # if defined WINDOWS_NATIVE || defined __CYGWIN__ /* Native Windows or Cygwin */
3431 /* Use native Windows API locale ID. */
3432 lcid
= GetThreadLocale ();
3434 return gl_locale_name_from_win32_LCID (lcid
);
3440 /* Determine the current locale's name, and canonicalize it into XPG syntax
3441 language[_territory][.codeset][@modifier]
3442 The codeset part in the result is not reliable; the locale_charset()
3443 should be used for codeset information instead.
3444 The result must not be freed. It is only valid in the current thread,
3445 until the next uselocale(), setlocale(), newlocale(), or freelocale()
3449 gl_locale_name_unsafe (int category
, const char *categoryname
)
3453 if (category
== LC_ALL
)
3454 /* Invalid argument. */
3457 retval
= gl_locale_name_thread_unsafe (category
, categoryname
);
3461 retval
= gl_locale_name_posix_unsafe (category
, categoryname
);
3465 return gl_locale_name_default ();