Repository navigation
locale: honor LC_ALL and LC_MESSAGES precedence over LANG - #13331
costajohnt wants to merge 5 commits into
Conversation
|
GNU testsuite comparison: |
Merging this PR will not alter performance1 warning, 1 note
Comparing Footnotes
|
181d188 to
14822ba
Compare
|
Binary size comparison: |
c557bb2 to
913aa3f
Compare
913aa3f to
12c9701
Compare
detect_system_locale() only read LANG, ignoring LC_ALL and LC_MESSAGES. POSIX message-locale precedence is LC_ALL > LC_MESSAGES > LANG: the first of those that is set and non-empty wins (set-but-empty is treated as unset), falling back to en-US when none qualify. Extract the precedence + encoding-stripping into a pure resolve_locale_string helper that takes an env lookup closure, so the logic is unit-tested without mutating process-global env vars (which race under parallel test threads). detect_system_locale() passes std::env::var through it, preserving the exact old string handling (only which variable supplies the value changed).
The GNU testsuite -mb runs set LANGUAGE=C LANG=C before overriding LC_ALL to fr_FR.UTF-8, and GNU tools stay English there because gettext gives LANGUAGE priority over LC_ALL. Walk LANGUAGE for the first usable entry (trimmed, codeset-stripped); C/POSIX entries and a C/POSIX resolved locale (including C.UTF-8) resolve to English explicitly. Deliberate divergences from gettext's per-catalog walk are documented in the doc comment. Also fix test_env_french and test_chmod_colored_output, which set only LANG and relied on the LANG-only lookup this branch removes; the harness's default LC_ALL=C now correctly outranks it.
Resolve LC_ALL/LC_MESSAGES/LANG plus LANGUAGE into a priority list and try each candidate until one has a translation catalog, instead of keeping the first entry that merely parses. A language-only entry now also matches a catalog of the same language (fr -> fr-FR), and, like gettext, a set LANGUAGE is no longer backed by the resolved locale: an exhausted list means untranslated output.
12c9701 to
508efc9
Compare
Fixes #8922.
Locale detection only read
LANG, soLC_ALLandLC_MESSAGESwere ignored. GNU honors all three, soLC_ALL=fr_FR.UTF-8 sleep --helpprints French there but English in uutils.This applies the POSIX message-locale precedence
LC_ALL>LC_MESSAGES>LANG: the first of those that is set and non-empty wins (a set-but-empty value is treated as unset), otherwise it falls back to the existingen-USdefault. The winning value keeps the same.<encoding>stripping as before (fr_FR.UTF-8->fr_FR), so theLANG-only path is unchanged.The precedence lives in a small pure helper that takes the env lookup as an argument, so it can be unit-tested without mutating process-global env vars (which race under parallel test threads):
detect_system_localejust calls it withstd::env::var.Behavior change
Anyone who has
LC_ALLorLC_MESSAGESset to something other thanLANGwill now get that locale for messages instead ofLANG. That is the intended fix for #8922, but noting it since it is user-visible.Tests
Seven unit tests on the helper:
LC_ALLwins,LC_MESSAGESwhenLC_ALLis unset,LANGstill works, empty treated as unset,LC_ALLoverLANG,LC_ALLoverLC_MESSAGES, and nothing-set fallback.cargo test,cargo clippy --workspace --all-targets --all-features -- -D warnings, andcargo fmt --checkall pass.