Skip to content

locale: honor LC_ALL and LC_MESSAGES precedence over LANG#13331

Open
costajohnt wants to merge 5 commits into
uutils:mainfrom
costajohnt:fix/8922-lc-all-locale-precedence
Open

locale: honor LC_ALL and LC_MESSAGES precedence over LANG#13331
costajohnt wants to merge 5 commits into
uutils:mainfrom
costajohnt:fix/8922-lc-all-locale-precedence

Conversation

@costajohnt

Copy link
Copy Markdown

Fixes #8922.

Locale detection only read LANG, so LC_ALL and LC_MESSAGES were ignored. GNU honors all three, so LC_ALL=fr_FR.UTF-8 sleep --help prints 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 existing en-US default. The winning value keeps the same .<encoding> stripping as before (fr_FR.UTF-8 -> fr_FR), so the LANG-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):

fn resolve_locale_string(lookup: impl Fn(&str) -> Option<String>) -> String

detect_system_locale just calls it with std::env::var.

Behavior change

Anyone who has LC_ALL or LC_MESSAGES set to something other than LANG will now get that locale for messages instead of LANG. That is the intended fix for #8922, but noting it since it is user-visible.

Tests

Seven unit tests on the helper: LC_ALL wins, LC_MESSAGES when LC_ALL is unset, LANG still works, empty treated as unset, LC_ALL over LANG, LC_ALL over LC_MESSAGES, and nothing-set fallback.

cargo test, cargo clippy --workspace --all-targets --all-features -- -D warnings, and cargo fmt --check all pass.

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).
@github-actions

github-actions Bot commented Jul 10, 2026

Copy link
Copy Markdown

GNU testsuite comparison:

Skip an intermittent issue tests/date/date-locale-hour (fails in this run but passes in the 'main' branch)
Skip an intermittent issue tests/misc/io-errors (fails in this run but passes in the 'main' branch)
Note: The gnu test tests/tail/tail-n0f is now being skipped but was previously passing.

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.
@codspeed-hq

codspeed-hq Bot commented Jul 12, 2026

Copy link
Copy Markdown

Merging this PR will degrade performance by 4.5%

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

❌ 2 regressed benchmarks
✅ 337 untouched benchmarks
⏩ 46 skipped benchmarks1

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
Simulation unexpand_large_file[10] 282.3 ms 295.6 ms -4.5%
Simulation unexpand_many_lines[100000] 134.7 ms 141.1 ms -4.5%

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing costajohnt:fix/8922-lc-all-locale-precedence (6390f88) with main (3aa5f8a)

Open in CodSpeed

Footnotes

  1. 46 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

l10n: LC_ALL is ignored

1 participant