On Wed, Jun 24, 2026, 16:53 Chet Ramey <[email protected]> wrote: > > On 6/19/26 5:32 PM, Grisha Levit wrote: > > On Fri, Jun 19, 2026 at 3:39 PM Chet Ramey via Bug reports for the GNU > > Bourne Again SHell <[email protected]> wrote: > >> I can't reproduce your results with bash-5.3, but I am not using Homebrew. > > > > I can reproduce this if, in System Settings : Language & Region, I have: > > * "Region" set to "Germany" > > * "English" as the first entry in "Preferred Languages" > > Note that the language has to be "English" (or "English (UK)"), and not > > "English (US)". > > > > $ defaults read -g AppleLocale > > en_DE > > OK, I was able to reproduce this with the same settings. > > The default locale returned by setlocale(LC_ALL, "") is > > "de_DE/UTF-8/de_DE/de_DE/de_DE/C" > > which is supposedly an opaque string that can be fed back to setlocale(). > > libintl setlocale also saves a copy of the default locale as returned by > > CFPreferencesCopyAppValue (CFSTR ("AppleLocale"), > kCFPreferencesCurrentApplication); > > This returns "en_DE" (see below). > > > > > $ env -i ./bash -c \ > > "printf '%f\n' 1; LC_NUMERIC=C printf '%f\n' 2; printf '%f\n' 3" > > 1,000000 > > 2.000000 > > ./bash: line 1: warning: setlocale: LC_NUMERIC: cannot change locale > > (): No such file or directory > > This happens because setlocale(LC_NUMERIC, "") ends up (down in libintl) > attempting to set LC_NUMERIC to "en_DE" (the cached value saved above from > the "AppleLocale" preference), which fails and returns NULL. > > Since it returns NULL, the current locale (C) remains unchanged. However, > even if bash used the return value from setlocale() when it sets LC_NUMERIC > from the temporary environment assignment, the results would not change, > because that returns "C". > > > > Setting LANG or LC_ALL instead of LC_NUMERIC in the temp env works as > > expected though: > > > > $ env -i ./bash -c \ > > "printf '%f\n' 1; LC_ALL=C printf '%f\n' 2; printf '%f\n' 3" > > 1,000000 > > 2.000000 > > 3,000000 > > I suspect the reason is that bash sets all the locale variables itself > when LC_ALL is changed. In this case, it tries to set everything to "", > including LC_NUMERIC, and everything fails except LC_ALL, which succeeds > and sets the locale back to en_DE. > > Bash does this because setlocale (...) works with environment variables, > not shell variables, and bash can't guarantee that it can replace getenv(). > > > > > As does setting LC_NUMERIC as a non-temp env variable: > > > > $ env -i ./bash -c \ > > "printf '%f\n' 1; LC_NUMERIC=C; printf '%f\n' 2; printf '%f\n' 3" > > 1,000000 > > 2.000000 > > 3.000000 > > Well, of course. This should change the LC_NUMERIC category to "C" for the > shell process until it gets changed again. > > > I think the only unexpected behavior here is that undoing an LC category > > change done in the temp env doesn't work correctly. > > Because the return value from setlocale() (the current locale) isn't > something that can be fed back to setlocale() without an error.
I think this behavior might just be a gnulib bug? AFAICT, what happens in this case (no relevant variables in the environment, System Preferences Language/Region set such that they do not match a valid locale): libintl_setlocale(LC_ALL,"") will set the LC_NUMERIC category (and others) by: * checking the value of the "AppleLocale" preference value (en_DE) * calling the system setlocale with this value (which fails) * finding an appropriate locale name based on the territory (de_DE) * calling the system setlocale with this value libintil_setlocale(LC_NUMERIC, "") uses a different code path, which does not do the last two steps, and so will just fail.
