Adventures in localization

When a linuxcnc developer reported testsuite failures, a fellow developer discovered that our tests don't run right in non-English locales—in particular, locales like de_DE where the decimal separator is "," instead of ".". But I'm not here to talk about how to fix the testsuite. Instead, get a load of this behavior inside a bash that was started with LC_ALL=C:
$ printf "%f\n" 1.23
$ LC_ALL=de_DE.UTF-8 printf "%f\n" 1.23
$ env LC_ALL=de_DE.UTF-8 printf "%f\n" 1.23
here, we see that the internal bash printf doesn't respond to a 'local' setting of LC_ALL. Or maybe it doesn't respond to localization at all? Let's check:
$ LC_ALL=de_DE.UTF-8 bash -c 'printf "%f\n" 1.23'
bash: Zeile 0: printf: 1.23: Ungültige Zahl.
$ LC_ALL=de_DE.UTF-8 bash -c 'printf "%f\n" 1,23'
That output makes sense; intuitively, printf should both parse and print numbers according to the rules of de_DE. Unfortuantely,
$ LC_ALL=de_DE.UTF-8 bash -c 'env printf "%f\n" 1,23'
printf: 1,23: Wert nicht vollständig konvertiert
$ LC_ALL=de_DE.UTF-8 bash -c 'env printf "%f\n" 1.23'
the external printf (/usr/bin/printf) doesn't: it parses numbers according to the C locale and then prints them according to the user's locale. (The messages in German mean approximately 'Invalid number' and 'Value not completely converted')

Incidentally, it appears that /usr/bin/printf is in the right and bash's internal printf and my own intuition are in the wrong when it comes to parsing numeric arguments in locales other than C: an argument corresponding to %f "shall be evaluated as a C constant, as described by the ISO C standard" (Open Group Base Specifications)

Entry first conceived on 6 March 2013, 13:59 UTC, last modified on 16 March 2013, 3:12 UTC
Website Copyright © 2004-2014 Jeff Epler