Win32 & NLS
"Magnus Hagander" <[email protected]>
| Newsgroups | gmane.comp.db.postgresql.devel.win32,gmane.comp.db.postgresql.devel.patches |
|---|---|
| Message-ID | <[email protected]> |
Hi!
Working the NLS stuff on win32. Considering I know very little about
this part (don't use it myself, never coded around in it), perhaps
someone else can shed some light?
PostgreSQL responds correctly to whatever the LC_MESSAGES environment
variable is set to upon startup of postgresql - I get my error messages
in swedish, english, german or whatever depending on that.
However, postgresql.conf does not load with the error message:
FATAL: invalid value for parameter "lc_messages": "EN"
This goes for whatever I set lc_messages to, including all the
combinations that work when set in the environment variable. If I
comment it out completely from the config file, things appear to work
with the locale picked up from the environment.
(The error msg of course only shows up when NLS is enabled in configure)
Some quick tracking-down of this shows that the code on line 80-82 of
pg_locale.c:
save = setlocale(category, NULL);
if (!save)
return NULL; /* won't happen, we hope
*/
*does* return NULL...
Now, I really don't know anything about the setlocale() integration, but
from the MSDN documentation
(http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/
html/_crt_setlocale.2c_._wsetlocale.asp) doesn't even list LC_MESSAGES
as a valid identifier. My bet is that's why it returns NULL on
LC_MESSAGES.
Also, some googling lead me to this:
http://www.haible.de/bruno/gettext-FAQ.html#windows_woe32
Which appears to suggest that we should change the locale using putenv()
etc, and not using setlocale() at all... Because setlocale() does not
support LC_MESSAGES, probably.
Attached is a patch with adds a environment variable based version of
locale_messages_assign(). It's not a pretty solution, but I think it's
probably necessary.
Comments?
(There is also a patch for initdb required to work on win32 when
compiled with NLS enabled, but this is the start...)
//Magnus
---------------------------(end of broadcast)---------------------------
TIP 9: the planner will ignore your desire to choose an index scan if your
joining column's datatypes do not match
win32nls.patch
(application/octet-stream, 2.4 KB)
Index: backend/utils/adt/pg_locale.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/utils/adt/pg_locale.c,v
retrieving revision 1.28
diff -c -r1.28 pg_locale.c
*** backend/utils/adt/pg_locale.c 29 Aug 2004 05:06:49 -0000 1.28
--- backend/utils/adt/pg_locale.c 17 Oct 2004 15:28:57 -0000
***************
*** 77,82 ****
--- 77,89 ----
{
char *save;
+ #if defined(WIN32) && defined(LC_MESSAGES)
+ /* On WIN32 there is no way to determine if a value set for
+ * LC_MESSAGES is actually valid */
+ if (category == LC_MESSAGES)
+ return value;
+ #endif
+
save = setlocale(category, NULL);
if (!save)
return NULL; /* won't happen, we hope */
***************
*** 123,128 ****
--- 130,136 ----
const char *
locale_messages_assign(const char *value, bool doit, GucSource source)
{
+ #ifndef WIN32
/*
* LC_MESSAGES category does not exist everywhere, but accept it
* anyway
***************
*** 131,155 ****
if (doit)
{
if (!setlocale(LC_MESSAGES, value))
- {
- #ifdef WIN32
-
- /*
- * Win32 returns NULL when you set LC_MESSAGES to "". So
- * don't complain unless we're trying to set it to something
- * else.
- */
- if (value[0])
- return NULL;
- #else
return NULL;
- #endif
- }
}
else
value = locale_xxx_assign(LC_MESSAGES, value, false, source);
#endif /* LC_MESSAGES */
return value;
}
--- 139,179 ----
if (doit)
{
if (!setlocale(LC_MESSAGES, value))
return NULL;
}
else
value = locale_xxx_assign(LC_MESSAGES, value, false, source);
#endif /* LC_MESSAGES */
return value;
+
+ #else
+ /* Win32 does not have setlocale() for LC_MESSAGES. We can only
+ * use environment variables to change it... (per gettext FAQ)
+ */
+ char env[128];
+
+ if (!doit)
+ /* There is no way to determine if specified language is available,
+ * so we assume it is. */
+ return value;
+
+ if (!value[0])
+ /* "" means set to what's in the environment, and that's already
+ * what is used. So just pretend we changed it. */
+ return value;
+
+ /* We need to modify both the process environment and the cached
+ * version in msvcrt */
+ if (!SetEnvironmentVariable("LC_MESSAGES",value))
+ return NULL;
+
+ ZeroMemory(env,sizeof(env));
+ snprintf(env,sizeof(env)-1,"LC_MESSAGES=%s",value);
+ if (_putenv(env))
+ return NULL;
+
+ return value;
+ #endif
}