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

Reply via email to