GNOME Bugzilla – Bug 164303
gnome-panel messes up languages if you have LC_COLLATE="C". Why?
Last modified: 2005-02-03 17:03:24 UTC
I don't subscribe to the theory that I should have to start from a fresh account on every new release. I have been carting home directories around since (mumblemumble). So I have a lot of cruft in all manner of dot files. To cut a long story short, this is what I get when I run Gnome in the normal way. Fedora Core 3, booting to "text login". Then I do "startx". ~/.i18n, /etc/sysconfig/i18n and ~/.bash_profile all show LANG=cy_GB.UTF-8. The only "odd" thing is that I still have LC_COLLATE=C, because I am used to capital letters coming first. Also, if I change it, all my scripts break. :) http://www.linux.org.uk/~telsa/tmp/2-langs.png (If you have problems viewing that, let me know: the site has issues atm. It shows the "right-click" menu for the clock. The bottom three entries in it (Remove from panel, Close, Move) are in Welsh as expected. All the other entries are in English. It's weird.) Almost everything else in Gnome is in Welsh. It's the panel which is confused. Launchers are in Welsh. "Remove from panel, close, move" are in Welsh in every menu. The right-click menu for the panel of "Add to this panel, delete panel, etc" is in Welsh. But half of the panel applet right-click menus are in English, all the preferences are in English, and the date is in English. I don't understand how this is happening. What I _want_ is this: http://www.linux.org.uk/~telsa/tmp/1-lang.png I got this to happen by killing the panel and restarting it with an LC_COLLATE of cy_GB.UTF-8. I know you're going to say that I should not have things like LC_COLLATE=C in my .bash_profile, but I have :) I expect things to sort like that. I think this is a bug. Why is the panel looking at LC_COLLATE? What is it doing with that? I have had a quick peek at the module in the hope of something like "collate" or "locale" being obvious, but I can't see anything.
I would think this is a bonobo issue since it's only happening for applets. But I really don't know what is the problem... Maybe Mark has an idea of what's happening.
If you attach the contents of /proc/$(pid)/environ for gnome-panel, bonobo-activation-server and clock-applet for the working and non-working cases, that should help us figure out what's going on
Created attachment 36130 [details] /proc/(various/environ when clock doing half a translation In .gz format: bugzilla eats binaries.
Created attachment 36131 [details] /proc/(various)/environ for clock all in one language In .gz format; bugzilla eats binaries.
Bugzilla thinks those are "x-tar". They're just gzipped. I killed off the all-in-Welsh panel and when it restarted, it went back to English-and-Welsh. And the weather applet crashed. This was quite good. First I got a dialogue telling me this and asking if I wanted to report a bug. In English. After dismissing that, I got one asking me if I wanted to reload it. In Welsh. Just in case that helps!
Okay, the clock is being launched with a screwed up environment: LC_ALL=LC_CTYPE=cy_GB.UTF-8;LC_NUMERIC=cy_GB.UTF-8;.... whereas in the second case, you get: LC_ALL=cy_GB.UTF-8 Now, it must be bonobo-activation-server that's doing this, so moving there. One thing of interest is that in the first case gnome-panel gets run with LANG=cy_GB.UTF-8, but in the second case it gets run with LC_ALL=cy_GB.UTF-8
Oh, that's my fault. In order to get it to do one language, I did gnome-session-properties (and set it to not respawn, and saved that) killall gnome-panel LC_ALL=cy_GB.UTF-8 gnome-panel & I was in Gnome all the time. I don't restart a lot. This machine is zippy enough when running X, but it does take a while to start up. I thought that LC_ALL would override LC_COLLATE (which it seems to), whereas I am not sure that LANG will.
I see I also claimed to do this with LC_ALL and LC_COLLATE. I'm sorry! I've used both. Both seem to work. Alas, I don't remember which I had used when I started the panel that was running when I did the attachment. Sorry about that. I can re-start it again (and again, and..) with LC_COLLATE or LC_ALL or whatever if you want? Sorry for the confusion. I honestly don't recall which was set now.
I grepped for processes with "LC_ALL=LC" in their environment. The panel didn't show up because of course I restarted that with the "right" locale. The other processes were hobbit 5446 0.0 0.8 19556 4260 ? S Jan06 0:44 /usr/libexec/gnome-settings-daemon --oaf-activate-iid=OAFIID:GNOME_SettingsDaemon --oaf-ior-fd=22 hobbit 5452 0.0 0.3 2724 1688 ? S Jan06 2:17 /usr/libexec/gam_server hobbit 5461 0.0 0.2 4444 1428 ? S Jan06 2:53 xscreensaver -nosplash hobbit 30947 0.0 0.2 2476 1008 ? Ss Jan26 0:00 /usr/bin/esd -terminate -nobeeps -as 2 -spawnfd 35 I don't know what started them, but is bonobo-activation-server a reasonable guess?
This bug is definitely caused by LC_ALL being (incorrectly) set by bonobo-activation. I had the same problem (ie: i'd get the environment setting LC_ALL="[huge string of uselessless]"). For me, I could see it, though because I was using the quicklounge applet (which gets spawned by activation) to launch terminals (and then my locale settings inside the terminal would be screwed). This workaround fixes the problem: in bonobo-activation-fork-server.c: static void bonobo_activation_setenv (const char *name, const char *value) { /* START ADDED LINES */ if( !strcmp( name, "LC_ALL" ) ) return; /* END ADDED LINES */ #if HAVE_SETENV setenv (name, value, 1); #else char *tmp; tmp = g_strconcat (name, "=", value, NULL); putenv (tmp); #endif } So somehow some badness is getting into the environment that bonobo-activation is setting up. I'm not sure where the problem really happens, though, so this is obviously not the correct solution.
The values that bonobo-activation sets for clients come from the environment of one of the launchers; so - somewhere, somehow someone is setting a 'badness' to LC_ALL - and that's really outside bonobo-activation's control. I guess we need to find what values LC_ALL is being set to, by whom etc. I'm guessing if the base panel is getting this environment then it's being done pretty early in the process - during login sometime perhaps.
So; yes bonobo-activation server launches gnome-settings-daemon, that in turn launches esd and xscreensaver I guess. However - b-a-s itself is (normally) launched by gnome-session; I guess the question is how LC_ALL can get screwed up from that. There is no special casing for LC_ALL in bonobo-activation/ or activation-server/ beyond the fact that it takes precedence (if set) over the various other LC_ messages. Ultimately, IMHO having a desktop that can activate components or applications with a different locale to 'the desktop' is prolly a disaster - and AFAIR this is the wat D/BUS is going: a mandatory single language desktop. What concerns me is that this should work; of course - it's possible that your ~/.bash_profile is not being read on gnome-session startup - and hence not interpreted until later - at which stage (perhaps) it is inherited from the client [ ie. b-a-s is doing the right thing, but it is not what you expect ]. Out of interest - I believe GDM has some language-selection list - why can that not be used in favour of tweaking some set of different config files ? or is that what /etc/sysconfig/i18n does ? ;-)
Created attachment 36775 [details] [review] Fixer. The problem comes from the fact that bonobo calls setlocale() and uses its return value to setenv(). setlocale() is documented as returning "an opaque string". In the event of calling setlocale(LC_ALL, NULL); with a non-homogeneous locale (eg: LC_COLLATE set to something different than LANG) it returns a string of the form "LC_CTYPE=cy_GB.UTF-8;LC_NUMERIC=cy_GB.UTF-8;"... Bonobo then sets this as the environment for the launched server (in bonobo-activation-fork-server.c). I think the best solution is to just get the locale strings for the environment of the server by just calling getenv() (which will always return something that's appropriate to set as an environment variable). In this case, you'll call getenv("LC_ALL") and get NULL (instead of the semicolon-delimited string). Then the LANG and LC_COLLATE options will be set properly. The attached patch does just that. Can I commit this?
Mark ? - this is really your forte - you wrote the code. Ryan - nice patch; have you read the cvs log comments on that file / looked at the annotations there; there were a number of relevant related bugs in the past here that would be good to review. AFAIR - yes, it's an opaque string, but it was the best thing we had I think; sigh.
Created attachment 36869 [details] [review] better fixer Hmm, what brand of crack was I on? I can't see why I was using setlocale() instead of the values from the environment. I must have just been trying to be too clever or something. Ryan's patch looks right, but might as well remove the setlocale() special casing altogher. Not tried my patch - Ryan, could you ?
There is one small functional difference between your patch and the originally intended behaviour: In the original code, if "LC_ALL" is set then none of the other environment variables are sent since LC_ALL overrides them. In your code, they're still all sent. That being said, any program that looks at locale information will see "LC_ALL" set alongside the others and do the right thing, and it's probably best to leave the environment like the user set it anyway. Patch works great here as far as I can tell. Thanks :)
Mark - please can you commit to HEAD ? - also, I've no idea what's happening with releases here anymore, but ... I guess we'll need a new one for gnome 2.10 :-) Thanks muchly.
Thanks again Ryan: 2005-02-03 Mark McLoughlin <mark@skynet.ie> Fix problem with locale env variables getting cocked up. Based on patch from Ryan Lortie <desrt@desrt.ca> in bug #164303 * bonobo-activation/bonobo-activation-activate.c: (bonobo_activation_init_activation_env): treat LC_* just the same as all other environment variables rather than trying to be clever with selocale().
*** Bug 158387 has been marked as a duplicate of this bug. ***
*** Bug 60701 has been marked as a duplicate of this bug. ***
Mark, I believe your patch is wrong: the application may have set the locale itself by setlocale(LC_XXX, "SOME_LOCALE"). IMO the activating application's current locale settings should be propagated to the activated application, not the ones inherited from the environment. I think my patch in bug #158387 handles it better: it obtains the settings of all the available locale categories in the activating app using setlocale (be it inherited from the environment or set inside the app) and propagates them to the activated app.
rkagan: There are a couple of problems with your patch. It still relies on undocumented behaviour of setlocale that seems likely to break (ie: trusting that its opaque data is useable as environment variables). Also, instead of setting the LANG environment variable in the children (if that's the only one the user has set) it individually sets every single LC_ category with a separate environment variable. In my case, where terminals are spawned (indirectly) by activation, I'd find this annoying and confusing (almost to the same extent as I was originally annoyed and confused by this bug). ie: Assume I'm a person who only uses LANG= and doesn't do LC_...= overrides. All of the sudden for some reason I feel like typing 'LANG=fr_CA.UTF-8 ls --help' but because of all of the specific overrides set by bonobo, my LANG variable that I set is now completely ignored. Your idea of unsetting the LC_ALL environment variable in the forked server is probably good, though since it could easily blow away LANG or anything else we send over. To adjust for the fact that we're not always sending all of LC_* the code should probably be adjusted to unset all of these variables (unless the environment is already being cleared elsewhere).
Oh, eep, yes. I do use "LANG=whatever gnome-app" a lot: * someone on IRC wants to know the order through the menus, perhaps. I can't tell them the Welsh order -- well, I can but it's not going to help -- so I run the app in English to check. * checking whether a translation is right, or running something side by side in two different languages. * taking fancy pictures of Gnome running four applications in four locales at once. Et cetera. I think they are all good reasons why I expect "LANG=whatever gnome-app" to run gnome-app in whatever language. I would be sad if that went away.
2 Ryan Lortie (desrt): > It still relies on undocumented behaviour of setlocale that seems likely to break (ie: trusting that its opaque data is useable as environment variables). Exactly the opposite: setlocale(LC_XXX, NULL) is supposed to always return a valid locale name for any category _except_ LC_ALL, no matter how you set it: using LANG, LC_*, setlocale, or a combination thereof. That's why I take the complete snapshot of the current locale settings by calling setlocale for _all_the_individual_ categories, and propagate them to the activated app via the corresponding environment variables. It doesn't matter if you use LANG or LC_* or a combination thereof:
[ Ups, sorry, accidentally hit "commit" while editing. Please ignore the last line of the previous comment ] Given that LC_ALL environment variable takes precedence over specific LC_*, I have to unset it in b-a-s. Also, since LC_* in turn take precedence over LANG, and I propagate the complete set of locale categories, there's no point propagating LANG.
As to your second point, I can see only one way around it: not using LC_* environment variables to propagate the locale info altogether. Instead, the return value of setlocale(LC_ALL, NULL) in the activating app can be passed to the activated app in a special environment variable, say BONOBO_LC_ALL, and then be used to set the locale in the activated one without messing with the locale-related environment at all. E.g. add setlocale(LC_ALL, getenv("BONOBO_LC_ALL")); to the main() of the activated app.
Created attachment 36928 [details] [review] Pass the locale settings via a special environment var This patch makes bonobo propagate the locale settings from the activating app to the activated one via a special environment variable BONOBO_LC_ALL. This way the activated app inherits the complete locale setting from the activating one without messing with the locale-related environment controlled by the user.
I'm not sure if I put the setlocale call for the activated apps in the right place. Mark and/or Michael should know better.