@@ -715,12 +715,41 @@ cache_locale_time(void)
715
715
716
716
#if defined(WIN32 )&& defined(LC_MESSAGES )
717
717
/*
718
- *Convert Windows locale name to the ISO formatted one
719
- *if possible.
718
+ * Convert a Windows setlocale() argument to a Unix-style one.
720
719
*
721
- *This function returns NULL if conversion is impossible,
722
- *otherwise returns the pointer to a static area which
723
- *contains the iso formatted locale name.
720
+ * Regardless of platform, we install message catalogs under a Unix-style
721
+ * LL[_CC][.ENCODING][@VARIANT] naming convention. Only LC_MESSAGES settings
722
+ * following that style will elicit localized interface strings.
723
+ *
724
+ * Before Visual Studio 2012 (msvcr110.dll), Windows setlocale() accepted "C"
725
+ * (but not "c") and strings of the form <Language>[_<Country>][.<CodePage>],
726
+ * case-insensitive. setlocale() returns the fully-qualified form; for
727
+ * example, setlocale("thaI") returns "Thai_Thailand.874". Internally,
728
+ * setlocale() and _create_locale() select a "locale identifier"[1] and store
729
+ * it in an undocumented _locale_t field. From that LCID, we can retrieve the
730
+ * ISO 639 language and the ISO 3166 country. Character encoding does not
731
+ * matter, because the server and client encodings govern that.
732
+ *
733
+ * Windows Vista introduced the "locale name" concept[2], closely following
734
+ * RFC 4646. Locale identifiers are now deprecated. Starting with Visual
735
+ * Studio 2012, setlocale() accepts locale names in addition to the strings it
736
+ * accepted historically. It does not standardize them; setlocale("Th-tH")
737
+ * returns "Th-tH". setlocale(category, "") still returns a traditional
738
+ * string. Furthermore, msvcr110.dll changed the undocumented _locale_t
739
+ * content to carry locale names instead of locale identifiers.
740
+ *
741
+ * MinGW headers declare _create_locale(), but msvcrt.dll lacks that symbol.
742
+ * IsoLocaleName() always fails in a MinGW-built postgres.exe, so only
743
+ * Unix-style values of the lc_messages GUC can elicit localized messages. In
744
+ * particular, every lc_messages setting that initdb can select automatically
745
+ * will yield only C-locale messages. XXX This could be fixed by running the
746
+ * fully-qualified locale name through a lookup table.
747
+ *
748
+ * This function returns a pointer to a static buffer bearing the converted
749
+ * name or NULL if conversion fails.
750
+ *
751
+ * [1] http://msdn.microsoft.com/en-us/library/windows/desktop/dd373763.aspx
752
+ * [2] http://msdn.microsoft.com/en-us/library/windows/desktop/dd373814.aspx
724
753
*/
725
754
static char *
726
755
IsoLocaleName (const char * winlocname )
@@ -739,6 +768,34 @@ IsoLocaleName(const char *winlocname)
739
768
loct = _create_locale (LC_CTYPE ,winlocname );
740
769
if (loct != NULL )
741
770
{
771
+ #if (_MSC_VER >=1700 )/* Visual Studio 2012 or later */
772
+ size_t rc ;
773
+ char * hyphen ;
774
+
775
+ /* Locale names use only ASCII, any conversion locale suffices. */
776
+ rc = wchar2char (iso_lc_messages ,loct -> locinfo -> locale_name [LC_CTYPE ],
777
+ sizeof (iso_lc_messages ),NULL );
778
+ _free_locale (loct );
779
+ if (rc == -1 || rc == sizeof (iso_lc_messages ))
780
+ return NULL ;
781
+
782
+ /*
783
+ * Since the message catalogs sit on a case-insensitive filesystem, we
784
+ * need not standardize letter case here. So long as we do not ship
785
+ * message catalogs for which it would matter, we also need not
786
+ * translate the script/variant portion, e.g. uz-Cyrl-UZ to
787
+ * uz_UZ@cyrillic. Simply replace the hyphen with an underscore.
788
+ *
789
+ * Note that the locale name can be less-specific than the value we
790
+ * would derive under earlier Visual Studio releases. For example,
791
+ * French_France.1252 yields just "fr". This does not affect any of
792
+ * the country-specific message catalogs available as of this writing
793
+ * (pt_BR, zh_CN, zh_TW).
794
+ */
795
+ hyphen = strchr (iso_lc_messages ,'-' );
796
+ if (hyphen )
797
+ * hyphen = '_' ;
798
+ #else
742
799
char isolang [32 ],
743
800
isocrty [32 ];
744
801
LCID lcid ;
@@ -753,6 +810,7 @@ IsoLocaleName(const char *winlocname)
753
810
if (!GetLocaleInfoA (lcid ,LOCALE_SISO3166CTRYNAME ,isocrty ,sizeof (isocrty )))
754
811
return NULL ;
755
812
snprintf (iso_lc_messages ,sizeof (iso_lc_messages )- 1 ,"%s_%s" ,isolang ,isocrty );
813
+ #endif
756
814
return iso_lc_messages ;
757
815
}
758
816
return NULL ;