Bruce Momjian wrote:
Tom Lane wrote:
Magnus Hagander <[EMAIL PROTECTED]> writes:
Thomas H. wrote:
so at least that explains the "changed" behaviour. nevertheless,
LC_MESSAGES seems to be defunct - with the "locale" folder present,
pg always picks the os' language and ignores the lc_message value.
This looks like I can reproduce though, at least on cvs head. Did this
work for you in previous versions?
Maybe we were using a different build of gettext in the previous
releases, one that didn't look at the same info as the current code?
Anyway the patch mentioned at the start of the thread
http://archives.postgresql.org/pgsql-patches/2008-02/msg00038.php
purports to fix this. It doesn't seem to have gotten reviewed
though.
Where are we on this?
Saito-san and I have been working on this item.
The attached patch is for MSVC version and does the following
when built under vc8 or later version MSVC.
1. Accepts Windows or ISO style locale name.
2. _putenv the ISO style locale name as LC_MESSAGES environemnt
variable so as to be referenced by the gettext library.
Note that we have to call _putenv() in msvcrt.dll not in
each MSVC version's runtime library msvcrxx.dll.
3. Calls SetThreadLocale() if necessary.
The currently used libintl3.dll(0.14.4.1592) seems to need
this handling. ISTM it is badly built and ignores the setting
of step 2.
regards,
Hiroshi Inoue
Index: pg_locale.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/pg_locale.c,v
retrieving revision 1.42
diff -c -c -r1.42 pg_locale.c
*** pg_locale.c 23 Sep 2008 09:20:36 -0000 1.42
--- pg_locale.c 7 Dec 2008 15:53:58 -0000
***************
*** 101,112 ****
--- 101,303 ----
* LC_XXX variables have been set correctly. (Thank you Perl for making this
* kluge necessary.)
*/
+
+ #if defined(WIN32) && defined(_MSC_VER)
+ typedef int (_cdecl *PUTENVPROC)(const char *);
+ #if defined(LC_MESSAGES) && (_MSC_VER >= 1400)
+ #define _TYPE_LOCALE_T_AVAILABLE
+ #include <shlwapi.h>
+ typedef const char * (_cdecl *NLLOCALENAMEPOSIXPROC)(int, const char *);
+
+ /*
+ * Never use DLLGETVERSIONPROC typedef'd in Shlwapi.h.
+ * It's problematic and would cause a crash.
+ */
+ typedef HRESULT (_cdecl *DLLGETVERSIONFUNC)(DLLVERSIONINFO *);
+
+ static char get_lang[64] = "";
+ static char get_country[64] = "";
+ static LCID glcid = (LCID) -1;
+
+ static BOOL CALLBACK lclist(LPTSTR lcname)
+ {
+ static char tmp_country[128] = "";
+ DWORD lcid;
+ char llang[32], lcountry[32];
+
+ sscanf_s(lcname, "%x", &lcid);
+ GetLocaleInfoA(lcid, LOCALE_SISO639LANGNAME, llang, sizeof(llang));
+ if (0 != _stricmp(llang, get_lang))
+ return TRUE;
+ GetLocaleInfoA(lcid, LOCALE_SISO3166CTRYNAME, lcountry,
sizeof(lcountry));
+ if ('\0' == get_country[0])
+ {
+ if (SUBLANG_DEFAULT == SUBLANGID(LANGIDFROMLCID(lcid)))
+ {
+ glcid = lcid;
+ return FALSE;
+ }
+ return TRUE;
+ }
+ if (0 == _stricmp(lcountry, get_country))
+ {
+ glcid = lcid;
+ return FALSE;
+ }
+ return TRUE;
+ }
+ #endif /* defined(LC_MESSAGES) && (_MSC_VER >= 1400) */
+
+ /*
+ * This function can accept Windows or ISO style locale name.
+ * Calls SetThreadLocale() if neccesary.
+ * Sets the ISO style LC_MESSAGES environment variable using
+ * _putenv() in msvcrt.dll which may be referenced by gettext.
+ * Returns ISO style LC_MESSAGES locale name.
+ */
+ static char *adjust_LC_MESSAGES(const char *locale, char *envbuf, char
*new_locale)
+ {
+ #ifdef _TYPE_LOCALE_T_AVAILABLE
+ char *rtn_locale = locale;
+ bool isClocale = false;
+ LCID lcid = (LCID) -1;
+ int usecategory = LC_CTYPE;
+ _locale_t loct = NULL;
+
+ if (0 == stricmp("c", locale) ||
+ 0 == stricmp("posix", locale))
+ isClocale = true;
+ if (isClocale)
+ loct = _create_locale(usecategory, "C");
+ else
+ loct = _create_locale(usecategory, locale);
+
+ if (NULL != loct)
+ {
+ lcid = loct->locinfo->lc_handle[usecategory];
+ if (0 == lcid)
+ lcid = MAKELCID(MAKELANGID(LANG_ENGLISH,
SUBLANG_ENGLISH_US), SORT_DEFAULT);
+ _free_locale(loct);
+ }
+ else
+ {
+ char del[16];
+ int scount = sscanf_s(locale, "%[^_-.]%[_-.]%[^.]", get_lang,
sizeof(get_lang), del, sizeof(del), get_country, sizeof(get_country));
+ switch (scount)
+ {
+ case 1:
+ case 2:
+ get_country[0] = '\0';
+ break;
+ case 3:
+ if ('.' == del[0])
+ get_country[0] = '\0';
+ break;
+ }
+ glcid = (LCID) -1;
+ EnumSystemLocales(lclist, LCID_SUPPORTED);
+ lcid = glcid;
+ }
+ if ((LCID) -1 == lcid)
+ return NULL;
+ else
+ {
+ /*
+ * Though GNU gettext FAQ says setting the environtment
LC_MESSAGES etc variables
+ * determines the locale used by gettext, it doesn't seem
true for 0.14.4.1952
+ * binary version of libintl3.dll. To make sure we do a
test and set not only the
+ * LC_MESSAGES variable but also the current thread's
locale if the test shows that
+ * the DLL doesn't follow the specification(FAQ).
+ */
+ static bool initCheck = true, setThread = false, setEnv =
true;
+ HMODULE hModule;
+ DLLGETVERSIONFUNC DllGetVersion;
+
+ if (initCheck &&
+ NULL != (hModule = LoadLibrary("libintl3.dll")) &&
+ NULL != (DllGetVersion = (DLLGETVERSIONFUNC)
GetProcAddress(hModule, "DllGetVersion")))
+ {
+ DLLVERSIONINFO2 dvi;
+ HRESULT hr;
+ NLLOCALENAMEPOSIXPROC locale_name_posix;
+
+ dvi.info1.cbSize = sizeof(dvi);
+ hr = DllGetVersion((DLLVERSIONINFO *) &dvi);
+ if (SUCCEEDED(hr) &&
+ MAKEDLLVERULL(0, 14, 4, 1952) == dvi.ullVersion
&&
+ NULL != (locale_name_posix =
(NLLOCALENAMEPOSIXPROC) GetProcAddress(hModule, "_nl_locale_name_posix")))
+ {
+
+ /*
+ * Here we test the DLL's behavior.
+ *
+ * Does the function
_nl_locale_name_posix() which is
+ * internally called by gettext() call
setlocale()?
+ */
+ if (NULL != locale_name_posix(LC_CTYPE,
"ignore_this_value") &&
+ NULL == locale_name_posix(LC_MESSAGES,
"ignore_this_value"))
+ {
+ setThread = true;
+ elog(WARNING, "linking a mal-configured
libintl3.dll?");
+ }
+ }
+ }
+ initCheck = false;
+ if (NULL != hModule)
+ FreeLibrary(hModule);
+ if (setThread)
+ {
+ SetThreadLocale(lcid);
+ }
+ if (setEnv && !isClocale)
+ {
+ char isolang[64], isocrty[64];
+
+ GetLocaleInfoA(lcid, LOCALE_SISO639LANGNAME, isolang,
sizeof(isolang));
+ GetLocaleInfoA(lcid, LOCALE_SISO3166CTRYNAME, isocrty,
sizeof(isocrty));
+ snprintf(new_locale, LC_ENV_BUFSIZE - 1, "%s_%s",
isolang, isocrty);
+ rtn_locale = new_locale;
+ }
+ }
+ #endif /* _TYPE_LOCALE_T_AVAILABLE */
+ #if (_MSC_VER >= 1300)
+ {
+ /*
+ * Each MSVC version has its own _putenv() in its runtime
library msvcrXX.dll.
+ * We call _putenv() in msvcrt.dll so as to be referenced
by GnuWin32 library.
+ */
+ HMODULE hmodule;
+ static PUTENVPROC putenvFunc = NULL;
+
+ if (NULL == putenvFunc)
+ {
+ if (hmodule = GetModuleHandle("msvcrt"), NULL ==
hmodule)
+ return NULL;
+ putenvFunc = (PUTENVPROC)GetProcAddress(hmodule,
"_putenv");
+ }
+ if (NULL == putenvFunc)
+ return NULL;
+ snprintf(envbuf, LC_ENV_BUFSIZE - 1, "%s=%s", "LC_MESSAGES",
rtn_locale);
+ if (putenvFunc(envbuf))
+ return NULL;
+ /* Refresh msgid pool maintained by gettext? */
+ textdomain("postgres");
+ }
+ #endif /* _MSC_VER >= 1300 */
+
+ return rtn_locale;
+ }
+ #endif /* defined(WIN32) && defined(_MSC_VER) */
+
char *
pg_perm_setlocale(int category, const char *locale)
{
char *result;
const char *envvar;
char *envbuf;
+ #ifdef LC_MESSAGES
+ char newlocale[128];
+ #endif /* LC_MESSAGES */
#ifndef WIN32
result = setlocale(category, locale);
***************
*** 147,152 ****
--- 338,347 ----
case LC_MESSAGES:
envvar = "LC_MESSAGES";
envbuf = lc_messages_envbuf;
+ #if defined(WIN32) && defined(_MSC_VER)
+ if (result = adjust_LC_MESSAGES(result, envbuf,
newlocale), NULL == result)
+ return NULL;
+ #endif /* WIN32 */
break;
#endif
case LC_MONETARY:
***************
*** 165,170 ****
--- 360,366 ----
elog(FATAL, "unrecognized LC category: %d", category);
envvar = NULL; /* keep compiler quiet */
envbuf = NULL;
+ return NULL;
break;
}
***************
*** 182,189 ****
if (!SetEnvironmentVariable(envvar, result))
return NULL;
if (_putenv(envbuf))
! return NULL;
! #endif
return result;
}
--- 378,385 ----
if (!SetEnvironmentVariable(envvar, result))
return NULL;
if (_putenv(envbuf))
! result = NULL;
! #endif /* WIN32 */
return result;
}
--
Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-bugs