Re: How to set locale dynamicly under GTK-win application?



Especially thank Tor for spending time to explain this. It is very instructive!
And thank you all for the help. 
Both putenv() and g_setenv() work. :-)




----- Original Message ----
From: Tor Lillqvist <tml iki fi>
To: Marvin Zhang <marvin2yuer yahoo com>
Cc: Daniel Atallah <daniel atallah gmail com>; gtk-app-devel-list gnome org
Sent: Tuesday, May 13, 2008 5:59:22 AM
Subject: Re: How to set locale dynamicly under GTK-win application?

But how to change the locale in the application?

First you should say what locale exactly you mean, or preferably what
end effect exactly you want to achieve... On Windows the locale
concept is not as straightforward as on Unixes. I assume what you want
is for the locale in the gettext sense to change, i.e. that localised
GTK+ widgets use another language than that of your Windows session
(or more correctly, process)?

Please note that there are at least two "locale" concepts in a process
of a C language program on Windows: Each thread can have a separate
locale from the operating system's point of view, and the process has
a locale from the C library's point of view. These are not necessarily
always in sync... which can lead to interesting effects. Although,
GTK+ tries to keep them in sync when it touches them at
initialisation.

I specifically say "C language program" above, because unlike Unix,
where the C library is very much a system library used by practically
every program, even if they are not written in C, on Windows the
situation is different. The C library does not have this status, it is
just a library that happens to be used by some programs. In fact,
there are several different shared C libraries and then static ones
that programs written in C (or C++) might use... But I digress.

I set but it still doesn't work.

   SetEnvironmentVariable("LANG", "zh_CN");
   SetEnvironmentVariable("LC_ALL", "zh_CN");

Unfortunately the concept of environment variables in Windows is
slightly screwed up (hah, anybody surprised?).

For a C program, there are two different "environments" or environment
variable blocks. There is the one maintained by the operating system,
and accessed with SetEnvironmentVariable(), GetEnvironmentVariable()
etc. Then there is the one maintained by the C library, accessed with
getenv(),  putenv() and _environ. (And then to further complicate
matters, there are then separate "ANSI" and "Unicode" versions of
these APIs.)

And... that's not all. As I said earlier, there are several
alternative C runtime libraries, and not surprisingly then, each has
its own environment variable block... It is possible that the .exe of
a process uses one C runtime (for instance msvcr90.dll if it has been
compiled with MSVS2008 without any special tricks) while GTK+ and the
GNU gettext-runtime intl.dll use msvcrt.dll.

(Note: Don't confuse the "system" and "user" environment variables you
see in the Control Panel's "System" applet with the two environment
variable blocks I mentioned above. That "system/user" dichotomy is
something unrelated, and has to do with how initial values for
environment variables are stored in the Registry between sessions, I
think.)

The C library environment variable block is obviously initialised from
the system-maintained  one when the process starts, but changes to the
system-maintained environment variable block don't propagate to the C
library one. So even if you set an environment variable with
SetEnvironmentVariable(), a getenv() will not retrieve that value.

(See http://mail.gnome.org/archives/gtk-devel-list/2004-December/msg00101.html
for some more rambling about this subject.)

The code in the GNU gettext-runtime that decides what message catalogs
to use calls getenv() to check for values of LC_ALL or LANG
environment variables. So, what you should do is simply:

putenv ("LANG=zh_CN")

at the start of your main(). (Note here that unless your code uses the
msvcrt.dll C runtime, this putenv() will not be seen by the getenv()
in intl.dll...)

This will also then have the side-effect that GTK+ will set the
thread's locale from the Win32 point of view with
SetThreadLocale(0x804) (which means Chinese (PRC), i.e. Simplified
Chinese), and also set the process's locale from the C library point
of view with setlocale(LC_ALL,"Chinese_People's Republic of China").
See the enum_locale_proc() function in gtkmain.c.

(Yes, the locale names as used by setlocale() in the Microsoft C
library is different from that typically used on Unix. The Microsoft C
library uses full English names of languages and countries, not ISO639
and ISO3166 codes.)

--tml



      


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]