Better default locale in the terminal
Better default locale in the terminal
- Use
LANGinstead ofLC_ALL(LC_ALLis the highest priority which will override any other end-user settings; when that isn't set things fall back to separateLC_*variables; and when those aren't set things fall back toLANG). [0] - Try taking
LANGfrom the user's environment before falling back toen_US.UTF-8
I'm leaving the comment in place because while I think this PR makes things much better for non-en_US users[1], I have a hunch that it could still be made even more better[2] :)
[0] https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_02
[1] ie, I myself am running a system where en_GB is the system-level default, and I no longer get a ton of "unknown locale: en_US" errors when I'm running things inside zed's terminal
[2] Perhaps the "correct" behaviour is to inherit LANG and all of the LC_* variables? I don't know, I'm not a locale expert, I'm just British
We require contributors to sign our Contributor License Agreement, and we don't have @shish on file. You can sign our CLA at https://zed.dev/cla. Once you've signed, post a comment here that says '@cla-bot check'.
@cla-bot check
(although zed.dev appears to be melting - 90% "internal server error" responses at every step of the CLA signing process...)
The cla-bot has been summoned, and re-checked this pull request!
Heads up that macOS has some "special" locale requirements. Not sure that that applies to this change or not (I don't think it should if you are just changing which variable is set). https://github.com/zed-industries/zed/pull/13691#discussion_r1669973591
I don't have a mac device to test with, but reading the code and the specs, I think this new code should still work there :)
Though reading that thread makes me wonder what's up - that thread seems to imply that the env hashmap should already contain variables inherited from the parent, and only in some specific circumstances (macos + launched from .app) those are missing -- but in my testing (run on linux via cargo run), the env hashmap is always empty, and variables like LANG need to be copied from the parent manually using env::var() (as this PR does)...
Regardless, while I'm not certain what the best fix is, I am pretty confident that this PR is a good step forwards compared to the status quo :)
Hey! Thanks for opening this. I'm not as deep in this topic as you are, so I was wondering whether you think your PR here clashes with what we discussed here: https://github.com/zed-industries/zed/pull/13691#discussion_r1669973591
Hey! Thanks for opening this. I'm not as deep in this topic as you are, so I was wondering whether you think your PR here clashes with what we discussed here: #13691 (comment)
Already mentioned above.
So digging into this even further, I think we're both not-quite-optimal and I had misunderstood what the env hashmap is (looks like it is a list of overrides to be applied on top of the inherited environment, not a complete environment itself)
My gut says that if you launch zed from a terminal, and then launch a terminal inside zed, then the inner terminal should have the same environment as the outside terminal (minus a few zed-specific additions such as ZED_TERM=true) - and if the outer terminal has some kind of locale settings, we should leave those as-is.
For the MacOS case of "sometimes there is no locale set, which breaks things", we probably do want to ensure some kind of fallback locale is set (but using the low-priority LANG instead of the high-priority LC_ALL, so that the user would be able to override it)
So my current code as-is would cover all cases correctly, but not optimally (with the current code, if the user has locale settings, then we copy-paste them into the override list -- it'd be better to leave the override list empty if an override isn't needed)
Actually there are even more layers in this rabbit hole -- looks like the env supplied to this function is supposed to contain the complete parent environment (If I'm reading [0] correctly), not only overrides... but that env is empty for some reason.
[0] https://github.com/zed-industries/zed/blob/9bc4e3b4ae4c248ef0342529caa23bef4593e19b/crates/project/src/terminals.rs#L119-L127
So... the correct-est behaviour would be to fix that inheritance process, and then only set LANG if it doesn't exist inside env already
Looking into "reasons why the zed CLI might report an empty environment", I believe my case is a related-but-separate bug (cargo run in the root results in env being set to an empty HashMap, when the comment says "Start with the environment that we might have inherited from the Zed CLI") - however there are other cases where the environment is intentionally None[0], so we do need to handle that in any case.
[0] https://github.com/zed-industries/zed/blob/596d8b2fe394421f9078fa91834b69fdb47ce251/crates/project/src/project.rs#L736
Already mentioned above.
Man, I swear I didn't see the two comments above mine 🤦 Sorry about that!
Looking into "reasons why the zed CLI might report an empty environment", I believe my case is a related-but-separate bug (
cargo runin the root results inenvbeing set to an emptyHashMap, when the comment says "Start with the environment that we might have inherited from the Zed CLI")
It's not a bug. When you run cargo run, the zed binary is launched with its stdout/stdin being a TTY, in which case the zed process itself inherits the environment of the parent process. And every process launched by Zed inherits the Zed environment. No manual intervention necessary.
When you run the Zed CLI — also called zed, but actually an alias for cli, which is in the cli crate — that spawns the Zed process. If that's the first time it spawns it, environment is inherited. But every other invocation doesn't spawn a new process, so no automatic Unix env inheritance, which means we have to manually add the environment, which is the code you linked to.
(I actually wrote even more about this whole environment stuff here: https://github.com/zed-industries/zed/blob/main/docs/src/environment.md)
Now, all that being said, if you think this change is good and @someone13574 also thinks it makes sense — let's try it?
Thank you for the explanation, that has connected some dots :)
With that deeper understanding, and my misleading part-of-a-comment removed, I think this is good to go
(the only way I can think of to be more-correct would be to look up the OS locale using platform-specific APIs and use that in place of hard-coded en_US.UTF-8 - but that's a lot more work (plus risk of platform-specific bugs) for a lot smaller benefit)
Let's give it a shot!
Looks like it's not working. In terminal.app I have: echo $LANG uk_UA.UTF-8 echo $LC_ALL uk_UA.UTF-8
But in zed terminal still: en_US.UTF-8 in both cases. Or I didn't understand what was fixed?
@josser are you launching zed by clicking the .app? My understanding is that when you do that, zed gets launched with no locale environment variables at all, and "hard-code en_US in all situations whether it's needed or not" was a workaround for that problem. However that then caused problems for me because I'm on linux, where the environment variables are set, but were being ignored.
This PR fixes my problem (ie, it pays attention to the environment variables, when they exist) - however the original problem of "macos launches GUI apps without environment variables, so we need to guess or hardcode something as a fallback" remains