1 /* w32-gettext.h - A simple gettext implementation for Windows targets.
2 Copyright (C) 1995,1996,1997,1999,2005 Free Software Foundation, Inc.
3 Copyright (C) 2005 g10 Code GmbH
5 This file is part of libgpg-error.
7 libgpg-error is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public License
9 as published by the Free Software Foundation; either version 2.1 of
10 the License, or (at your option) any later version.
12 libgpg-error is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public
18 License along with libgpg-error; if not, write to the Free
19 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
31 #include <sys/types.h>
35 #include <gpg-error.h>
40 /* localname.c from gettext. */
42 /* Edit: Added a "static" to _nl_locale_name. Note that the category
43 argument is ignored on w32. */
45 /* Determine the current selected locale.
46 Copyright (C) 1995-1999, 2000-2003 Free Software Foundation, Inc.
48 This program is free software; you can redistribute it and/or modify it
49 under the terms of the GNU Library General Public License as published
50 by the Free Software Foundation; either version 2, or (at your option)
53 This program is distributed in the hope that it will be useful,
54 but WITHOUT ANY WARRANTY; without even the implied warranty of
55 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
56 Library General Public License for more details.
58 You should have received a copy of the GNU Library General Public
59 License along with this program; if not, write to the Free Software
60 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
63 /* Written by Ulrich Drepper <drepper@gnu.org>, 1995. */
64 /* Win32 code written by Tor Lillqvist <tml@iki.fi>. */
73 #ifdef HAVE_W32_SYSTEM
75 /* List of language codes, sorted by value:
98 0x17 LANG_RHAETO_ROMANCE
101 0x1a LANG_CROATIAN == LANG_SERBIAN
193 /* Mingw headers don't have latest language and sublanguage codes. */
194 # ifndef LANG_AFRIKAANS
195 # define LANG_AFRIKAANS 0x36
197 # ifndef LANG_ALBANIAN
198 # define LANG_ALBANIAN 0x1c
200 # ifndef LANG_AMHARIC
201 # define LANG_AMHARIC 0x5e
204 # define LANG_ARABIC 0x01
206 # ifndef LANG_ARMENIAN
207 # define LANG_ARMENIAN 0x2b
209 # ifndef LANG_ASSAMESE
210 # define LANG_ASSAMESE 0x4d
213 # define LANG_AZERI 0x2c
216 # define LANG_BASQUE 0x2d
218 # ifndef LANG_BELARUSIAN
219 # define LANG_BELARUSIAN 0x23
221 # ifndef LANG_BENGALI
222 # define LANG_BENGALI 0x45
224 # ifndef LANG_BURMESE
225 # define LANG_BURMESE 0x55
227 # ifndef LANG_CAMBODIAN
228 # define LANG_CAMBODIAN 0x53
230 # ifndef LANG_CATALAN
231 # define LANG_CATALAN 0x03
233 # ifndef LANG_CHEROKEE
234 # define LANG_CHEROKEE 0x5c
237 # define LANG_DIVEHI 0x65
240 # define LANG_EDO 0x66
242 # ifndef LANG_ESTONIAN
243 # define LANG_ESTONIAN 0x25
245 # ifndef LANG_FAEROESE
246 # define LANG_FAEROESE 0x38
249 # define LANG_FARSI 0x29
251 # ifndef LANG_FRISIAN
252 # define LANG_FRISIAN 0x62
254 # ifndef LANG_FULFULDE
255 # define LANG_FULFULDE 0x67
258 # define LANG_GAELIC 0x3c
260 # ifndef LANG_GALICIAN
261 # define LANG_GALICIAN 0x56
263 # ifndef LANG_GEORGIAN
264 # define LANG_GEORGIAN 0x37
266 # ifndef LANG_GUARANI
267 # define LANG_GUARANI 0x74
269 # ifndef LANG_GUJARATI
270 # define LANG_GUJARATI 0x47
273 # define LANG_HAUSA 0x68
275 # ifndef LANG_HAWAIIAN
276 # define LANG_HAWAIIAN 0x75
279 # define LANG_HEBREW 0x0d
282 # define LANG_HINDI 0x39
285 # define LANG_IBIBIO 0x69
288 # define LANG_IGBO 0x70
290 # ifndef LANG_INDONESIAN
291 # define LANG_INDONESIAN 0x21
293 # ifndef LANG_INUKTITUT
294 # define LANG_INUKTITUT 0x5d
296 # ifndef LANG_KANNADA
297 # define LANG_KANNADA 0x4b
300 # define LANG_KANURI 0x71
302 # ifndef LANG_KASHMIRI
303 # define LANG_KASHMIRI 0x60
306 # define LANG_KAZAK 0x3f
308 # ifndef LANG_KONKANI
309 # define LANG_KONKANI 0x57
312 # define LANG_KYRGYZ 0x40
315 # define LANG_LAO 0x54
318 # define LANG_LATIN 0x76
320 # ifndef LANG_LATVIAN
321 # define LANG_LATVIAN 0x26
323 # ifndef LANG_LITHUANIAN
324 # define LANG_LITHUANIAN 0x27
326 # ifndef LANG_MACEDONIAN
327 # define LANG_MACEDONIAN 0x2f
330 # define LANG_MALAY 0x3e
332 # ifndef LANG_MALAYALAM
333 # define LANG_MALAYALAM 0x4c
335 # ifndef LANG_MALTESE
336 # define LANG_MALTESE 0x3a
338 # ifndef LANG_MANIPURI
339 # define LANG_MANIPURI 0x58
341 # ifndef LANG_MARATHI
342 # define LANG_MARATHI 0x4e
344 # ifndef LANG_MONGOLIAN
345 # define LANG_MONGOLIAN 0x50
348 # define LANG_NEPALI 0x61
351 # define LANG_ORIYA 0x48
354 # define LANG_OROMO 0x72
356 # ifndef LANG_PAPIAMENTU
357 # define LANG_PAPIAMENTU 0x79
360 # define LANG_PASHTO 0x63
362 # ifndef LANG_PUNJABI
363 # define LANG_PUNJABI 0x46
365 # ifndef LANG_RHAETO_ROMANCE
366 # define LANG_RHAETO_ROMANCE 0x17
369 # define LANG_SAAMI 0x3b
371 # ifndef LANG_SANSKRIT
372 # define LANG_SANSKRIT 0x4f
374 # ifndef LANG_SERBIAN
375 # define LANG_SERBIAN 0x1a
378 # define LANG_SINDHI 0x59
380 # ifndef LANG_SINHALESE
381 # define LANG_SINHALESE 0x5b
384 # define LANG_SLOVAK 0x1b
387 # define LANG_SOMALI 0x77
389 # ifndef LANG_SORBIAN
390 # define LANG_SORBIAN 0x2e
393 # define LANG_SUTU 0x30
395 # ifndef LANG_SWAHILI
396 # define LANG_SWAHILI 0x41
399 # define LANG_SYRIAC 0x5a
401 # ifndef LANG_TAGALOG
402 # define LANG_TAGALOG 0x64
405 # define LANG_TAJIK 0x28
407 # ifndef LANG_TAMAZIGHT
408 # define LANG_TAMAZIGHT 0x5f
411 # define LANG_TAMIL 0x49
414 # define LANG_TATAR 0x44
417 # define LANG_TELUGU 0x4a
420 # define LANG_THAI 0x1e
422 # ifndef LANG_TIBETAN
423 # define LANG_TIBETAN 0x51
425 # ifndef LANG_TIGRINYA
426 # define LANG_TIGRINYA 0x73
429 # define LANG_TSONGA 0x31
432 # define LANG_TSWANA 0x32
434 # ifndef LANG_TURKMEN
435 # define LANG_TURKMEN 0x42
437 # ifndef LANG_UKRAINIAN
438 # define LANG_UKRAINIAN 0x22
441 # define LANG_URDU 0x20
444 # define LANG_UZBEK 0x43
447 # define LANG_VENDA 0x33
449 # ifndef LANG_VIETNAMESE
450 # define LANG_VIETNAMESE 0x2a
453 # define LANG_WELSH 0x52
456 # define LANG_XHOSA 0x34
459 # define LANG_YI 0x78
461 # ifndef LANG_YIDDISH
462 # define LANG_YIDDISH 0x3d
465 # define LANG_YORUBA 0x6a
468 # define LANG_ZULU 0x35
470 # ifndef SUBLANG_ARABIC_SAUDI_ARABIA
471 # define SUBLANG_ARABIC_SAUDI_ARABIA 0x01
473 # ifndef SUBLANG_ARABIC_IRAQ
474 # define SUBLANG_ARABIC_IRAQ 0x02
476 # ifndef SUBLANG_ARABIC_EGYPT
477 # define SUBLANG_ARABIC_EGYPT 0x03
479 # ifndef SUBLANG_ARABIC_LIBYA
480 # define SUBLANG_ARABIC_LIBYA 0x04
482 # ifndef SUBLANG_ARABIC_ALGERIA
483 # define SUBLANG_ARABIC_ALGERIA 0x05
485 # ifndef SUBLANG_ARABIC_MOROCCO
486 # define SUBLANG_ARABIC_MOROCCO 0x06
488 # ifndef SUBLANG_ARABIC_TUNISIA
489 # define SUBLANG_ARABIC_TUNISIA 0x07
491 # ifndef SUBLANG_ARABIC_OMAN
492 # define SUBLANG_ARABIC_OMAN 0x08
494 # ifndef SUBLANG_ARABIC_YEMEN
495 # define SUBLANG_ARABIC_YEMEN 0x09
497 # ifndef SUBLANG_ARABIC_SYRIA
498 # define SUBLANG_ARABIC_SYRIA 0x0a
500 # ifndef SUBLANG_ARABIC_JORDAN
501 # define SUBLANG_ARABIC_JORDAN 0x0b
503 # ifndef SUBLANG_ARABIC_LEBANON
504 # define SUBLANG_ARABIC_LEBANON 0x0c
506 # ifndef SUBLANG_ARABIC_KUWAIT
507 # define SUBLANG_ARABIC_KUWAIT 0x0d
509 # ifndef SUBLANG_ARABIC_UAE
510 # define SUBLANG_ARABIC_UAE 0x0e
512 # ifndef SUBLANG_ARABIC_BAHRAIN
513 # define SUBLANG_ARABIC_BAHRAIN 0x0f
515 # ifndef SUBLANG_ARABIC_QATAR
516 # define SUBLANG_ARABIC_QATAR 0x10
518 # ifndef SUBLANG_AZERI_LATIN
519 # define SUBLANG_AZERI_LATIN 0x01
521 # ifndef SUBLANG_AZERI_CYRILLIC
522 # define SUBLANG_AZERI_CYRILLIC 0x02
524 # ifndef SUBLANG_BENGALI_INDIA
525 # define SUBLANG_BENGALI_INDIA 0x01
527 # ifndef SUBLANG_BENGALI_BANGLADESH
528 # define SUBLANG_BENGALI_BANGLADESH 0x02
530 # ifndef SUBLANG_CHINESE_MACAU
531 # define SUBLANG_CHINESE_MACAU 0x05
533 # ifndef SUBLANG_ENGLISH_SOUTH_AFRICA
534 # define SUBLANG_ENGLISH_SOUTH_AFRICA 0x07
536 # ifndef SUBLANG_ENGLISH_JAMAICA
537 # define SUBLANG_ENGLISH_JAMAICA 0x08
539 # ifndef SUBLANG_ENGLISH_CARIBBEAN
540 # define SUBLANG_ENGLISH_CARIBBEAN 0x09
542 # ifndef SUBLANG_ENGLISH_BELIZE
543 # define SUBLANG_ENGLISH_BELIZE 0x0a
545 # ifndef SUBLANG_ENGLISH_TRINIDAD
546 # define SUBLANG_ENGLISH_TRINIDAD 0x0b
548 # ifndef SUBLANG_ENGLISH_ZIMBABWE
549 # define SUBLANG_ENGLISH_ZIMBABWE 0x0c
551 # ifndef SUBLANG_ENGLISH_PHILIPPINES
552 # define SUBLANG_ENGLISH_PHILIPPINES 0x0d
554 # ifndef SUBLANG_ENGLISH_INDONESIA
555 # define SUBLANG_ENGLISH_INDONESIA 0x0e
557 # ifndef SUBLANG_ENGLISH_HONGKONG
558 # define SUBLANG_ENGLISH_HONGKONG 0x0f
560 # ifndef SUBLANG_ENGLISH_INDIA
561 # define SUBLANG_ENGLISH_INDIA 0x10
563 # ifndef SUBLANG_ENGLISH_MALAYSIA
564 # define SUBLANG_ENGLISH_MALAYSIA 0x11
566 # ifndef SUBLANG_ENGLISH_SINGAPORE
567 # define SUBLANG_ENGLISH_SINGAPORE 0x12
569 # ifndef SUBLANG_FRENCH_LUXEMBOURG
570 # define SUBLANG_FRENCH_LUXEMBOURG 0x05
572 # ifndef SUBLANG_FRENCH_MONACO
573 # define SUBLANG_FRENCH_MONACO 0x06
575 # ifndef SUBLANG_FRENCH_WESTINDIES
576 # define SUBLANG_FRENCH_WESTINDIES 0x07
578 # ifndef SUBLANG_FRENCH_REUNION
579 # define SUBLANG_FRENCH_REUNION 0x08
581 # ifndef SUBLANG_FRENCH_CONGO
582 # define SUBLANG_FRENCH_CONGO 0x09
584 # ifndef SUBLANG_FRENCH_SENEGAL
585 # define SUBLANG_FRENCH_SENEGAL 0x0a
587 # ifndef SUBLANG_FRENCH_CAMEROON
588 # define SUBLANG_FRENCH_CAMEROON 0x0b
590 # ifndef SUBLANG_FRENCH_COTEDIVOIRE
591 # define SUBLANG_FRENCH_COTEDIVOIRE 0x0c
593 # ifndef SUBLANG_FRENCH_MALI
594 # define SUBLANG_FRENCH_MALI 0x0d
596 # ifndef SUBLANG_FRENCH_MOROCCO
597 # define SUBLANG_FRENCH_MOROCCO 0x0e
599 # ifndef SUBLANG_FRENCH_HAITI
600 # define SUBLANG_FRENCH_HAITI 0x0f
602 # ifndef SUBLANG_GERMAN_LUXEMBOURG
603 # define SUBLANG_GERMAN_LUXEMBOURG 0x04
605 # ifndef SUBLANG_GERMAN_LIECHTENSTEIN
606 # define SUBLANG_GERMAN_LIECHTENSTEIN 0x05
608 # ifndef SUBLANG_KASHMIRI_INDIA
609 # define SUBLANG_KASHMIRI_INDIA 0x02
611 # ifndef SUBLANG_MALAY_MALAYSIA
612 # define SUBLANG_MALAY_MALAYSIA 0x01
614 # ifndef SUBLANG_MALAY_BRUNEI_DARUSSALAM
615 # define SUBLANG_MALAY_BRUNEI_DARUSSALAM 0x02
617 # ifndef SUBLANG_NEPALI_INDIA
618 # define SUBLANG_NEPALI_INDIA 0x02
620 # ifndef SUBLANG_PUNJABI_INDIA
621 # define SUBLANG_PUNJABI_INDIA 0x01
623 # ifndef SUBLANG_ROMANIAN_ROMANIA
624 # define SUBLANG_ROMANIAN_ROMANIA 0x01
626 # ifndef SUBLANG_SERBIAN_LATIN
627 # define SUBLANG_SERBIAN_LATIN 0x02
629 # ifndef SUBLANG_SERBIAN_CYRILLIC
630 # define SUBLANG_SERBIAN_CYRILLIC 0x03
632 # ifndef SUBLANG_SINDHI_INDIA
633 # define SUBLANG_SINDHI_INDIA 0x00
635 # ifndef SUBLANG_SINDHI_PAKISTAN
636 # define SUBLANG_SINDHI_PAKISTAN 0x01
638 # ifndef SUBLANG_SPANISH_GUATEMALA
639 # define SUBLANG_SPANISH_GUATEMALA 0x04
641 # ifndef SUBLANG_SPANISH_COSTA_RICA
642 # define SUBLANG_SPANISH_COSTA_RICA 0x05
644 # ifndef SUBLANG_SPANISH_PANAMA
645 # define SUBLANG_SPANISH_PANAMA 0x06
647 # ifndef SUBLANG_SPANISH_DOMINICAN_REPUBLIC
648 # define SUBLANG_SPANISH_DOMINICAN_REPUBLIC 0x07
650 # ifndef SUBLANG_SPANISH_VENEZUELA
651 # define SUBLANG_SPANISH_VENEZUELA 0x08
653 # ifndef SUBLANG_SPANISH_COLOMBIA
654 # define SUBLANG_SPANISH_COLOMBIA 0x09
656 # ifndef SUBLANG_SPANISH_PERU
657 # define SUBLANG_SPANISH_PERU 0x0a
659 # ifndef SUBLANG_SPANISH_ARGENTINA
660 # define SUBLANG_SPANISH_ARGENTINA 0x0b
662 # ifndef SUBLANG_SPANISH_ECUADOR
663 # define SUBLANG_SPANISH_ECUADOR 0x0c
665 # ifndef SUBLANG_SPANISH_CHILE
666 # define SUBLANG_SPANISH_CHILE 0x0d
668 # ifndef SUBLANG_SPANISH_URUGUAY
669 # define SUBLANG_SPANISH_URUGUAY 0x0e
671 # ifndef SUBLANG_SPANISH_PARAGUAY
672 # define SUBLANG_SPANISH_PARAGUAY 0x0f
674 # ifndef SUBLANG_SPANISH_BOLIVIA
675 # define SUBLANG_SPANISH_BOLIVIA 0x10
677 # ifndef SUBLANG_SPANISH_EL_SALVADOR
678 # define SUBLANG_SPANISH_EL_SALVADOR 0x11
680 # ifndef SUBLANG_SPANISH_HONDURAS
681 # define SUBLANG_SPANISH_HONDURAS 0x12
683 # ifndef SUBLANG_SPANISH_NICARAGUA
684 # define SUBLANG_SPANISH_NICARAGUA 0x13
686 # ifndef SUBLANG_SPANISH_PUERTO_RICO
687 # define SUBLANG_SPANISH_PUERTO_RICO 0x14
689 # ifndef SUBLANG_SWEDISH_FINLAND
690 # define SUBLANG_SWEDISH_FINLAND 0x02
692 # ifndef SUBLANG_TAMAZIGHT_ARABIC
693 # define SUBLANG_TAMAZIGHT_ARABIC 0x01
695 # ifndef SUBLANG_TAMAZIGHT_LATIN
696 # define SUBLANG_TAMAZIGHT_LATIN 0x02
698 # ifndef SUBLANG_TIGRINYA_ETHIOPIA
699 # define SUBLANG_TIGRINYA_ETHIOPIA 0x00
701 # ifndef SUBLANG_TIGRINYA_ERITREA
702 # define SUBLANG_TIGRINYA_ERITREA 0x01
704 # ifndef SUBLANG_URDU_PAKISTAN
705 # define SUBLANG_URDU_PAKISTAN 0x01
707 # ifndef SUBLANG_URDU_INDIA
708 # define SUBLANG_URDU_INDIA 0x02
710 # ifndef SUBLANG_UZBEK_LATIN
711 # define SUBLANG_UZBEK_LATIN 0x01
713 # ifndef SUBLANG_UZBEK_CYRILLIC
714 # define SUBLANG_UZBEK_CYRILLIC 0x02
716 #endif /* HAVE_W32_SYSTEM */
718 /* XPG3 defines the result of 'setlocale (category, NULL)' as:
719 "Directs 'setlocale()' to query 'category' and return the current
721 However it does not specify the exact format. Neither do SUSV2 and
722 ISO C 99. So we can use this feature only on selected systems (e.g.
723 those using GNU C Library). */
724 #if defined _LIBC || (defined __GNU_LIBRARY__ && __GNU_LIBRARY__ >= 2)
725 # define HAVE_LOCALE_NULL
728 /* Determine the current locale's name, and canonicalize it into XPG syntax
729 language[_territory[.codeset]][@modifier]
730 The codeset part in the result is not reliable; the locale_charset()
731 should be used for codeset information instead.
732 The result must not be freed; it is statically allocated. */
735 _nl_locale_name (int category, const char *categoryname)
739 #ifndef HAVE_W32_SYSTEM
741 /* Use the POSIX methods of looking to 'LC_ALL', 'LC_xxx', and 'LANG'.
742 On some systems this can be done by the 'setlocale' function itself. */
743 # if defined HAVE_SETLOCALE && defined HAVE_LC_MESSAGES && defined HAVE_LOCALE_NULL
744 retval = setlocale (category, NULL);
746 /* Setting of LC_ALL overwrites all other. */
747 retval = getenv ("LC_ALL");
748 if (retval == NULL || retval[0] == '\0')
750 /* Next comes the name of the desired category. */
751 retval = getenv (categoryname);
752 if (retval == NULL || retval[0] == '\0')
754 /* Last possibility is the LANG environment variable. */
755 retval = getenv ("LANG");
756 if (retval == NULL || retval[0] == '\0')
757 /* We use C as the default domain. POSIX says this is
758 implementation defined. */
766 #else /* HAVE_W32_SYSTEM */
768 /* Return an XPG style locale name language[_territory][@modifier].
769 Don't even bother determining the codeset; it's not useful in this
770 context, because message catalogs are not specific to a single
777 /* Let the user override the system settings through environment
778 variables, as on POSIX systems. */
779 retval = getenv ("LC_ALL");
780 if (retval != NULL && retval[0] != '\0')
782 retval = getenv (categoryname);
783 if (retval != NULL && retval[0] != '\0')
785 retval = getenv ("LANG");
786 if (retval != NULL && retval[0] != '\0')
789 /* Use native Win32 API locale ID. */
790 lcid = GetThreadLocale ();
792 /* Strip off the sorting rules, keep only the language part. */
793 langid = LANGIDFROMLCID (lcid);
795 /* Split into language and territory part. */
796 primary = PRIMARYLANGID (langid);
797 sub = SUBLANGID (langid);
799 /* Dispatch on language.
800 See also http://www.unicode.org/unicode/onlinedat/languages.html .
801 For details about languages, see http://www.ethnologue.com/ . */
804 case LANG_AFRIKAANS: return "af_ZA";
805 case LANG_ALBANIAN: return "sq_AL";
806 case LANG_AMHARIC: return "am_ET";
810 case SUBLANG_ARABIC_SAUDI_ARABIA: return "ar_SA";
811 case SUBLANG_ARABIC_IRAQ: return "ar_IQ";
812 case SUBLANG_ARABIC_EGYPT: return "ar_EG";
813 case SUBLANG_ARABIC_LIBYA: return "ar_LY";
814 case SUBLANG_ARABIC_ALGERIA: return "ar_DZ";
815 case SUBLANG_ARABIC_MOROCCO: return "ar_MA";
816 case SUBLANG_ARABIC_TUNISIA: return "ar_TN";
817 case SUBLANG_ARABIC_OMAN: return "ar_OM";
818 case SUBLANG_ARABIC_YEMEN: return "ar_YE";
819 case SUBLANG_ARABIC_SYRIA: return "ar_SY";
820 case SUBLANG_ARABIC_JORDAN: return "ar_JO";
821 case SUBLANG_ARABIC_LEBANON: return "ar_LB";
822 case SUBLANG_ARABIC_KUWAIT: return "ar_KW";
823 case SUBLANG_ARABIC_UAE: return "ar_AE";
824 case SUBLANG_ARABIC_BAHRAIN: return "ar_BH";
825 case SUBLANG_ARABIC_QATAR: return "ar_QA";
828 case LANG_ARMENIAN: return "hy_AM";
829 case LANG_ASSAMESE: return "as_IN";
833 /* FIXME: Adjust this when Azerbaijani locales appear on Unix. */
834 case SUBLANG_AZERI_LATIN: return "az_AZ@latin";
835 case SUBLANG_AZERI_CYRILLIC: return "az_AZ@cyrillic";
839 return "eu"; /* Ambiguous: could be "eu_ES" or "eu_FR". */
840 case LANG_BELARUSIAN: return "be_BY";
844 case SUBLANG_BENGALI_INDIA: return "bn_IN";
845 case SUBLANG_BENGALI_BANGLADESH: return "bn_BD";
848 case LANG_BULGARIAN: return "bg_BG";
849 case LANG_BURMESE: return "my_MM";
850 case LANG_CAMBODIAN: return "km_KH";
851 case LANG_CATALAN: return "ca_ES";
852 case LANG_CHEROKEE: return "chr_US";
856 case SUBLANG_CHINESE_TRADITIONAL: return "zh_TW";
857 case SUBLANG_CHINESE_SIMPLIFIED: return "zh_CN";
858 case SUBLANG_CHINESE_HONGKONG: return "zh_HK";
859 case SUBLANG_CHINESE_SINGAPORE: return "zh_SG";
860 case SUBLANG_CHINESE_MACAU: return "zh_MO";
863 case LANG_CROATIAN: /* LANG_CROATIAN == LANG_SERBIAN
864 * What used to be called Serbo-Croatian
865 * should really now be two separate
866 * languages because of political reasons.
867 * (Says tml, who knows nothing about Serbian
869 * (I can feel those flames coming already.)
873 case SUBLANG_DEFAULT: return "hr_HR";
874 case SUBLANG_SERBIAN_LATIN: return "sr_CS";
875 case SUBLANG_SERBIAN_CYRILLIC: return "sr_CS@cyrillic";
878 case LANG_CZECH: return "cs_CZ";
879 case LANG_DANISH: return "da_DK";
880 case LANG_DIVEHI: return "div_MV";
884 case SUBLANG_DUTCH: return "nl_NL";
885 case SUBLANG_DUTCH_BELGIAN: /* FLEMISH, VLAAMS */ return "nl_BE";
888 case LANG_EDO: return "bin_NG";
892 /* SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. Heh. I thought
893 * English was the language spoken in England.
896 case SUBLANG_ENGLISH_US: return "en_US";
897 case SUBLANG_ENGLISH_UK: return "en_GB";
898 case SUBLANG_ENGLISH_AUS: return "en_AU";
899 case SUBLANG_ENGLISH_CAN: return "en_CA";
900 case SUBLANG_ENGLISH_NZ: return "en_NZ";
901 case SUBLANG_ENGLISH_EIRE: return "en_IE";
902 case SUBLANG_ENGLISH_SOUTH_AFRICA: return "en_ZA";
903 case SUBLANG_ENGLISH_JAMAICA: return "en_JM";
904 case SUBLANG_ENGLISH_CARIBBEAN: return "en_GD"; /* Grenada? */
905 case SUBLANG_ENGLISH_BELIZE: return "en_BZ";
906 case SUBLANG_ENGLISH_TRINIDAD: return "en_TT";
907 case SUBLANG_ENGLISH_ZIMBABWE: return "en_ZW";
908 case SUBLANG_ENGLISH_PHILIPPINES: return "en_PH";
909 case SUBLANG_ENGLISH_INDONESIA: return "en_ID";
910 case SUBLANG_ENGLISH_HONGKONG: return "en_HK";
911 case SUBLANG_ENGLISH_INDIA: return "en_IN";
912 case SUBLANG_ENGLISH_MALAYSIA: return "en_MY";
913 case SUBLANG_ENGLISH_SINGAPORE: return "en_SG";
916 case LANG_ESTONIAN: return "et_EE";
917 case LANG_FAEROESE: return "fo_FO";
918 case LANG_FARSI: return "fa_IR";
919 case LANG_FINNISH: return "fi_FI";
923 case SUBLANG_FRENCH: return "fr_FR";
924 case SUBLANG_FRENCH_BELGIAN: /* WALLOON */ return "fr_BE";
925 case SUBLANG_FRENCH_CANADIAN: return "fr_CA";
926 case SUBLANG_FRENCH_SWISS: return "fr_CH";
927 case SUBLANG_FRENCH_LUXEMBOURG: return "fr_LU";
928 case SUBLANG_FRENCH_MONACO: return "fr_MC";
929 case SUBLANG_FRENCH_WESTINDIES: return "fr"; /* Caribbean? */
930 case SUBLANG_FRENCH_REUNION: return "fr_RE";
931 case SUBLANG_FRENCH_CONGO: return "fr_CG";
932 case SUBLANG_FRENCH_SENEGAL: return "fr_SN";
933 case SUBLANG_FRENCH_CAMEROON: return "fr_CM";
934 case SUBLANG_FRENCH_COTEDIVOIRE: return "fr_CI";
935 case SUBLANG_FRENCH_MALI: return "fr_ML";
936 case SUBLANG_FRENCH_MOROCCO: return "fr_MA";
937 case SUBLANG_FRENCH_HAITI: return "fr_HT";
940 case LANG_FRISIAN: return "fy_NL";
941 case LANG_FULFULDE: return "ful_NG";
945 case 0x01: /* SCOTTISH */ return "gd_GB";
946 case 0x02: /* IRISH */ return "ga_IE";
949 case LANG_GALICIAN: return "gl_ES";
950 case LANG_GEORGIAN: return "ka_GE";
954 case SUBLANG_GERMAN: return "de_DE";
955 case SUBLANG_GERMAN_SWISS: return "de_CH";
956 case SUBLANG_GERMAN_AUSTRIAN: return "de_AT";
957 case SUBLANG_GERMAN_LUXEMBOURG: return "de_LU";
958 case SUBLANG_GERMAN_LIECHTENSTEIN: return "de_LI";
961 case LANG_GREEK: return "el_GR";
962 case LANG_GUARANI: return "gn_PY";
963 case LANG_GUJARATI: return "gu_IN";
964 case LANG_HAUSA: return "ha_NG";
966 /* FIXME: Do they mean Hawaiian ("haw_US", 1000 speakers)
967 or Hawaii Creole English ("cpe_US", 600000 speakers)? */
969 case LANG_HEBREW: return "he_IL";
970 case LANG_HINDI: return "hi_IN";
971 case LANG_HUNGARIAN: return "hu_HU";
972 case LANG_IBIBIO: return "nic_NG";
973 case LANG_ICELANDIC: return "is_IS";
974 case LANG_IGBO: return "ibo_NG";
975 case LANG_INDONESIAN: return "id_ID";
976 case LANG_INUKTITUT: return "iu_CA";
980 case SUBLANG_ITALIAN: return "it_IT";
981 case SUBLANG_ITALIAN_SWISS: return "it_CH";
984 case LANG_JAPANESE: return "ja_JP";
985 case LANG_KANNADA: return "kn_IN";
986 case LANG_KANURI: return "kau_NG";
990 case SUBLANG_DEFAULT: return "ks_PK";
991 case SUBLANG_KASHMIRI_INDIA: return "ks_IN";
994 case LANG_KAZAK: return "kk_KZ";
996 /* FIXME: Adjust this when such locales appear on Unix. */
998 case LANG_KOREAN: return "ko_KR";
999 case LANG_KYRGYZ: return "ky_KG";
1000 case LANG_LAO: return "lo_LA";
1001 case LANG_LATIN: return "la_VA";
1002 case LANG_LATVIAN: return "lv_LV";
1003 case LANG_LITHUANIAN: return "lt_LT";
1004 case LANG_MACEDONIAN: return "mk_MK";
1008 case SUBLANG_MALAY_MALAYSIA: return "ms_MY";
1009 case SUBLANG_MALAY_BRUNEI_DARUSSALAM: return "ms_BN";
1012 case LANG_MALAYALAM: return "ml_IN";
1013 case LANG_MALTESE: return "mt_MT";
1015 /* FIXME: Adjust this when such locales appear on Unix. */
1017 case LANG_MARATHI: return "mr_IN";
1018 case LANG_MONGOLIAN:
1019 return "mn"; /* Ambiguous: could be "mn_CN" or "mn_MN". */
1023 case SUBLANG_DEFAULT: return "ne_NP";
1024 case SUBLANG_NEPALI_INDIA: return "ne_IN";
1027 case LANG_NORWEGIAN:
1030 case SUBLANG_NORWEGIAN_BOKMAL: return "no_NO";
1031 case SUBLANG_NORWEGIAN_NYNORSK: return "nn_NO";
1034 case LANG_ORIYA: return "or_IN";
1035 case LANG_OROMO: return "om_ET";
1036 case LANG_PAPIAMENTU: return "pap_AN";
1038 return "ps"; /* Ambiguous: could be "ps_PK" or "ps_AF". */
1039 case LANG_POLISH: return "pl_PL";
1040 case LANG_PORTUGUESE:
1043 case SUBLANG_PORTUGUESE: return "pt_PT";
1044 /* Hmm. SUBLANG_PORTUGUESE_BRAZILIAN == SUBLANG_DEFAULT.
1045 Same phenomenon as SUBLANG_ENGLISH_US == SUBLANG_DEFAULT. */
1046 case SUBLANG_PORTUGUESE_BRAZILIAN: return "pt_BR";
1052 case SUBLANG_PUNJABI_INDIA: return "pa_IN"; /* Gurmukhi script */
1055 case LANG_RHAETO_ROMANCE: return "rm_CH";
1059 case SUBLANG_ROMANIAN_ROMANIA: return "ro_RO";
1063 return "ru"; /* Ambiguous: could be "ru_RU" or "ru_UA" or "ru_MD". */
1064 case LANG_SAAMI: /* actually Northern Sami */ return "se_NO";
1065 case LANG_SANSKRIT: return "sa_IN";
1069 case SUBLANG_SINDHI_INDIA: return "sd_IN";
1070 case SUBLANG_SINDHI_PAKISTAN: return "sd_PK";
1073 case LANG_SINHALESE: return "si_LK";
1074 case LANG_SLOVAK: return "sk_SK";
1075 case LANG_SLOVENIAN: return "sl_SI";
1076 case LANG_SOMALI: return "so_SO";
1078 /* FIXME: Adjust this when such locales appear on Unix. */
1083 case SUBLANG_SPANISH: return "es_ES";
1084 case SUBLANG_SPANISH_MEXICAN: return "es_MX";
1085 case SUBLANG_SPANISH_MODERN:
1086 return "es_ES@modern"; /* not seen on Unix */
1087 case SUBLANG_SPANISH_GUATEMALA: return "es_GT";
1088 case SUBLANG_SPANISH_COSTA_RICA: return "es_CR";
1089 case SUBLANG_SPANISH_PANAMA: return "es_PA";
1090 case SUBLANG_SPANISH_DOMINICAN_REPUBLIC: return "es_DO";
1091 case SUBLANG_SPANISH_VENEZUELA: return "es_VE";
1092 case SUBLANG_SPANISH_COLOMBIA: return "es_CO";
1093 case SUBLANG_SPANISH_PERU: return "es_PE";
1094 case SUBLANG_SPANISH_ARGENTINA: return "es_AR";
1095 case SUBLANG_SPANISH_ECUADOR: return "es_EC";
1096 case SUBLANG_SPANISH_CHILE: return "es_CL";
1097 case SUBLANG_SPANISH_URUGUAY: return "es_UY";
1098 case SUBLANG_SPANISH_PARAGUAY: return "es_PY";
1099 case SUBLANG_SPANISH_BOLIVIA: return "es_BO";
1100 case SUBLANG_SPANISH_EL_SALVADOR: return "es_SV";
1101 case SUBLANG_SPANISH_HONDURAS: return "es_HN";
1102 case SUBLANG_SPANISH_NICARAGUA: return "es_NI";
1103 case SUBLANG_SPANISH_PUERTO_RICO: return "es_PR";
1106 case LANG_SUTU: return "bnt_TZ"; /* or "st_LS" or "nso_ZA"? */
1107 case LANG_SWAHILI: return "sw_KE";
1111 case SUBLANG_DEFAULT: return "sv_SE";
1112 case SUBLANG_SWEDISH_FINLAND: return "sv_FI";
1115 case LANG_SYRIAC: return "syr_TR"; /* An extinct language. */
1116 case LANG_TAGALOG: return "tl_PH";
1117 case LANG_TAJIK: return "tg_TJ";
1118 case LANG_TAMAZIGHT:
1121 /* FIXME: Adjust this when Tamazight locales appear on Unix. */
1122 case SUBLANG_TAMAZIGHT_ARABIC: return "ber_MA@arabic";
1123 case SUBLANG_TAMAZIGHT_LATIN: return "ber_MA@latin";
1127 return "ta"; /* Ambiguous: could be "ta_IN" or "ta_LK" or "ta_SG". */
1128 case LANG_TATAR: return "tt_RU";
1129 case LANG_TELUGU: return "te_IN";
1130 case LANG_THAI: return "th_TH";
1131 case LANG_TIBETAN: return "bo_CN";
1135 case SUBLANG_TIGRINYA_ETHIOPIA: return "ti_ET";
1136 case SUBLANG_TIGRINYA_ERITREA: return "ti_ER";
1139 case LANG_TSONGA: return "ts_ZA";
1140 case LANG_TSWANA: return "tn_BW";
1141 case LANG_TURKISH: return "tr_TR";
1142 case LANG_TURKMEN: return "tk_TM";
1143 case LANG_UKRAINIAN: return "uk_UA";
1147 case SUBLANG_URDU_PAKISTAN: return "ur_PK";
1148 case SUBLANG_URDU_INDIA: return "ur_IN";
1154 case SUBLANG_UZBEK_LATIN: return "uz_UZ";
1155 case SUBLANG_UZBEK_CYRILLIC: return "uz_UZ@cyrillic";
1159 /* FIXME: It's not clear whether Venda has the ISO 639-2 two-letter code
1161 http://www.loc.gov/standards/iso639-2/englangn.html has it, but
1162 http://lcweb.loc.gov/standards/iso639-2/codechanges.html doesn't, */
1163 return "ven_ZA"; /* or "ve_ZA"? */
1164 case LANG_VIETNAMESE: return "vi_VN";
1165 case LANG_WELSH: return "cy_GB";
1166 case LANG_XHOSA: return "xh_ZA";
1167 case LANG_YI: return "sit_CN";
1168 case LANG_YIDDISH: return "yi_IL";
1169 case LANG_YORUBA: return "yo_NG";
1170 case LANG_ZULU: return "zu_ZA";
1171 default: return "C";
1174 #endif /* HAVE_W32_SYSTEM */
1177 /* localname.c from gettext END. */
1179 /* Support functions. */
1181 typedef uint32_t u32;
1182 typedef unsigned long ulong;
1184 static __inline__ u32
1187 return (i << 24) | ((i & 0xff00) << 8) | ((i >> 8) & 0xff00) | (i >> 24);
1190 #define SWAPIT(flag, data) ((flag) ? do_swap_u32(data) : (data))
1193 /* We assume to have `unsigned long int' value with at least 32 bits. */
1194 #define HASHWORDBITS 32
1196 /* The so called `hashpjw' function by P.J. Weinberger
1197 [see Aho/Sethi/Ullman, COMPILERS: Principles, Techniques and Tools,
1198 1986, 1987 Bell Telephone Laboratories, Inc.] */
1200 static __inline__ ulong
1201 hash_string( const char *str_param )
1203 unsigned long int hval, g;
1204 const char *str = str_param;
1207 while (*str != '\0')
1210 hval += (unsigned long int) *str++;
1211 g = hval & ((unsigned long int) 0xf << (HASHWORDBITS - 4));
1214 hval ^= g >> (HASHWORDBITS - 8);
1222 /* Generic message catalog and gettext stuff. */
1224 /* The magic number of the GNU message catalog format. */
1225 #define MAGIC 0x950412de
1226 #define MAGIC_SWAPPED 0xde120495
1228 /* Revision number of the currently used .mo (binary) file format. */
1229 #define MO_REVISION_NUMBER 0
1231 /* Header for binary .mo file format. */
1232 struct mo_file_header
1234 /* The magic number. */
1236 /* The revision number of the file format. */
1238 /* The number of strings pairs. */
1240 /* Offset of table with start offsets of original strings. */
1241 u32 orig_tab_offset;
1242 /* Offset of table with start offsets of translation strings. */
1243 u32 trans_tab_offset;
1244 /* Size of hashing table. */
1246 /* Offset of first hashing entry. */
1247 u32 hash_tab_offset;
1252 /* Length of addressed string. */
1254 /* Offset of string in file. */
1259 struct overflow_space_s
1261 struct overflow_space_s *next;
1266 struct loaded_domain
1271 char *mapped; /* 0 = not yet mapped, 1 = mapped,
1274 struct overflow_space_s *overflow_space;
1275 struct string_desc *orig_tab;
1276 struct string_desc *trans_tab;
1282 /* Free the domain data. */
1284 free_domain (struct loaded_domain *domain)
1286 struct overflow_space_s *os, *os2;
1287 free (domain->data);
1288 free (domain->mapped);
1289 for (os = domain->overflow_space; os; os = os2)
1298 /* The gettext implementation; support functions. */
1299 static struct loaded_domain *
1300 load_domain (const char *filename)
1305 struct mo_file_header *data = NULL;
1306 struct loaded_domain *domain = NULL;
1310 fp = fopen (filename, "rb");
1314 /* Determine the file size. */
1315 if (fstat (fileno (fp), &st)
1316 || (size = (size_t) st.st_size) != st.st_size
1317 || size < sizeof (struct mo_file_header))
1323 data = malloc (size);
1331 read_ptr = (char *) data;
1334 long int nb = fread (read_ptr, 1, to_read, fp);
1344 while (to_read > 0);
1347 /* Using the magic number we can test whether it really is a message
1349 if (data->magic != MAGIC && data->magic != MAGIC_SWAPPED)
1351 /* The magic number is wrong: not a message catalog file. */
1356 domain = calloc (1, sizeof *domain);
1362 domain->data = (char *) data;
1363 domain->must_swap = data->magic != MAGIC;
1365 /* Fill in the information about the available tables. */
1366 switch (SWAPIT (domain->must_swap, data->revision))
1369 domain->nstrings = SWAPIT (domain->must_swap, data->nstrings);
1370 domain->orig_tab = (struct string_desc *)
1371 ((char *) data + SWAPIT (domain->must_swap, data->orig_tab_offset));
1372 domain->trans_tab = (struct string_desc *)
1373 ((char *) data + SWAPIT (domain->must_swap, data->trans_tab_offset));
1374 domain->hash_size = SWAPIT (domain->must_swap, data->hash_tab_size);
1375 domain->hash_tab = (u32 *)
1376 ((char *) data + SWAPIT (domain->must_swap, data->hash_tab_offset));
1380 /* This is an invalid revision. */
1386 /* Allocate an array to keep track of code page mappings. */
1387 domain->mapped = calloc (1, domain->nstrings);
1388 if (!domain->mapped)
1399 /* Return a malloced string encoded in UTF-8 from the wide char input
1400 string STRING. Caller must free this value. On failure returns
1401 NULL; caller may use GetLastError to get the actual error number.
1402 The result of calling this function with STRING set to NULL is not
1405 wchar_to_native (const wchar_t *string)
1410 n = WideCharToMultiByte (CP_ACP, 0, string, -1, NULL, 0, NULL, NULL);
1414 result = malloc (n+1);
1418 n = WideCharToMultiByte (CP_ACP, 0, string, -1, result, n, NULL, NULL);
1428 /* Return a malloced wide char string from an UTF-8 encoded input
1429 string STRING. Caller must free this value. On failure returns
1430 NULL; caller may use GetLastError to get the actual error number.
1431 The result of calling this function with STRING set to NULL is not
1434 utf8_to_wchar (const char *string)
1439 n = MultiByteToWideChar (CP_UTF8, 0, string, -1, NULL, 0);
1443 result = malloc ((n+1) * sizeof *result);
1447 n = MultiByteToWideChar (CP_UTF8, 0, string, -1, result, n);
1458 utf8_to_native (const char *string)
1463 wstring = utf8_to_wchar (string);
1467 result = wchar_to_native (wstring);
1475 get_string (struct loaded_domain *domain, u32 idx)
1477 struct overflow_space_s *os;
1480 p = domain->data + SWAPIT (domain->must_swap, domain->trans_tab[idx].offset);
1481 if (!domain->mapped[idx])
1483 size_t plen, buflen;
1486 domain->mapped[idx] = 1;
1489 buf = utf8_to_native (p);
1490 buflen = strlen (buf);
1495 /* There is not enough space for the translation - store it
1496 in the overflow_space else and mark that in the mapped
1497 array. Because we expect that this won't happen too
1498 often, we use a simple linked list. */
1499 os = malloc (sizeof *os + buflen);
1503 strcpy (os->d, buf);
1504 os->next = domain->overflow_space;
1505 domain->overflow_space = os;
1509 p = "ERROR in GETTEXT MALLOC";
1513 else if (domain->mapped[idx] == 2)
1515 /* We need to get the string from the overflow_space. */
1516 for (os=domain->overflow_space; os; os = os->next)
1518 return (const char*) os->d;
1519 p = "ERROR in GETTEXT\n";
1521 return (const char*) p;
1526 /* The domain we use. We only support one domain at this point. This
1527 is why this implementation can not be shared. Bindtextdomain and
1528 dgettext will simply cheat and always use this one domain. */
1529 static struct loaded_domain *the_domain;
1532 /* Specify that the DOMAINNAME message catalog will be found
1533 in DIRNAME rather than in the system locale data base. */
1535 bindtextdomain (const char *domainname, const char *dirname)
1537 struct loaded_domain *domain = NULL;
1538 const char *catval_full;
1542 /* DOMAINNAME is ignored. We only support one domain. */
1544 /* DIRNAME is "$INSTALLDIR\share\locale". */
1546 /* First found out the category value. */
1548 catval_full = _nl_locale_name (LC_MESSAGES, "LC_MESSAGES");
1550 /* Normally, we would have to loop over all returned locales, and
1551 search for the right file. See gettext intl/dcigettext.c for all
1552 the gory details. Here, we only support the basic category, and
1553 ignore everything else. */
1558 catval = malloc (strlen (catval_full) + 1);
1561 strcpy (catval, catval_full);
1562 p = strchr (catval, '_');
1570 /* Now build the filename string. The complete filename is this:
1571 DIRNAME + \ + CATVAL + \LC_MESSAGES\ + DOMAINNAME + .mo */
1573 int len = strlen (dirname) + 1 + strlen (catval) + 13
1574 + strlen (domainname) + 3 + 1;
1577 fname = malloc (len);
1585 strcpy (p, dirname);
1586 p += strlen (dirname);
1589 p += strlen (catval);
1590 strcpy (p, "\\LC_MESSAGES\\");
1592 strcpy (p, domainname);
1593 p += strlen (domainname);
1597 domain = load_domain (fname);
1601 /* We should not be invoked twice, but this is how you would do
1602 it if it happened. */
1604 free_domain (the_domain);
1605 the_domain = domain;
1607 /* For historic reasoins we are not allowed to return a const char*. */
1608 return (char*)dirname;
1613 gettext (const char *msgid)
1615 struct loaded_domain *domain;
1619 if (!(domain = the_domain))
1622 /* Locate the MSGID and its translation. */
1623 if (domain->hash_size > 2 && domain->hash_tab)
1625 /* Use the hashing table. */
1626 u32 len = strlen (msgid);
1627 u32 hash_val = hash_string (msgid);
1628 u32 idx = hash_val % domain->hash_size;
1629 u32 incr = 1 + (hash_val % (domain->hash_size - 2));
1630 u32 nstr = SWAPIT (domain->must_swap, domain->hash_tab[idx]);
1633 /* Hash table entry is empty. */
1636 if (SWAPIT (domain->must_swap,
1637 domain->orig_tab[nstr - 1].length) == len
1640 + SWAPIT (domain->must_swap,
1641 domain->orig_tab[nstr - 1].offset)))
1642 return get_string (domain, nstr - 1);
1646 if (idx >= domain->hash_size - incr)
1647 idx -= domain->hash_size - incr;
1651 nstr = SWAPIT (domain->must_swap, domain->hash_tab[idx]);
1653 /* Hash table entry is empty. */
1656 if (SWAPIT (domain->must_swap,
1657 domain->orig_tab[nstr - 1].length) == len
1660 + SWAPIT (domain->must_swap,
1661 domain->orig_tab[nstr - 1].offset)))
1662 return get_string (domain, nstr-1);
1667 /* Now we try the default method: binary search in the sorted array
1670 top = domain->nstrings;
1671 while (bottom < top)
1675 act = (bottom + top) / 2;
1676 cmp_val = strcmp(msgid, domain->data
1677 + SWAPIT (domain->must_swap,
1678 domain->orig_tab[act].offset));
1681 else if (cmp_val > 0)
1684 return get_string (domain, act);
1693 textdomain (const char *domainname)
1695 /* For now, support only one domain. */
1696 return (char*)domainname;
1700 dgettext (const char *domainname, const char *msgid)
1702 /* For now, support only one domain. */
1703 return (char*)gettext (msgid);