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.

--
``The lyf so short, the craft so long to lerne.'' - Chaucer
                 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRU    [email protected]    http://tiswww.cwru.edu/~chet/

Attachment: OpenPGP_signature.asc
Description: OpenPGP digital signature

Reply via email to