November 01, 2019
On Friday, 1 November 2019 at 17:02:53 UTC, H. S. Teoh wrote:
> I think it has to do with the LC_* environment variables, at least on a *nix system. You can set LC_ALL to get the same settings across all categories, or you can separately set one or more of the LC_* to get different settings in each category. (Caveat: I've never actually done this myself before, so I could be misunderstanding how it works.)

Yeah, POSIX, so POSIX-compliant C compilers should support it...

https://docs.oracle.com/cd/E19253-01/817-2521/overview-39/index.html

Other languages do not have to follow it, of course.

November 02, 2019
On 2019-11-01 18:02, H. S. Teoh wrote:

> That would be a better solution. It would be different from snprintf,
> though, and we'd have to document it well so that people can find it.

It depends on what the goal is. If it is to have 100% compatible drop-in replacement to snprintf then we need to include the localization.

But if the goal is just to have a function that converts values to a string, which is implemented in D, then have the opportunity to make a better interface.

-- 
/Jacob Carlborg
November 03, 2019
On Friday, 1 November 2019 at 17:02:53 UTC, H. S. Teoh wrote:
> On Fri, Nov 01, 2019 at 01:01:21PM +0000, Jacob Carlborg via Digitalmars-d wrote:
>> On Thursday, 31 October 2019 at 15:58:08 UTC, H. S. Teoh wrote:
>> [...]

https://github.com/mpv-player/mpv/commit/1e70e82baa9193f6f027338b0fab0f5078971fbe

This is kind of relevant to the whole issue with locales, and how they simply don't work as they should. Probably best to not replicate at all, and instead just pass in the necessary localisation to the format function, if necessary.
November 04, 2019
On Saturday, 2 November 2019 at 16:59:15 UTC, Jacob Carlborg wrote:
> On 2019-11-01 18:02, H. S. Teoh wrote:
>
>> That would be a better solution. It would be different from snprintf,
>> though, and we'd have to document it well so that people can find it.
>
> It depends on what the goal is. If it is to have 100% compatible drop-in replacement to snprintf then we need to include the localization.
>
> But if the goal is just to have a function that converts values to a string, which is implemented in D, then have the opportunity to make a better interface.

+1

That's actually, what I ask myself all the time. I personally prefer the second approach.

And a similar question arrises with the rounding problem, which is even a little bit more difficult, because the IEEE standard interferes here too.
November 04, 2019
On Saturday, 2 November 2019 at 16:59:15 UTC, Jacob Carlborg wrote:
>
> It depends on what the goal is. If it is to have 100% compatible drop-in replacement to snprintf then we need to include the localization.
>
> But if the goal is just to have a function that converts values to a string, which is implemented in D, then have the opportunity to make a better interface.

+1 this is important since we've had localization bug and I suspect it's very easy to have such bugs.

Warning: `format` is affected too! (perhaps only when using the %f format specifier?)

https://github.com/AuburnSounds/printed/issues/22
ugly fix: https://github.com/AuburnSounds/printed/commit/797343c0fc213ea34aa5b79b61cdc1164ae189df


There is a non-zero chance that people _are_ relying on `format` and `snprintf` being localization-aware. So a "drop-in" replacement need to fix this mess by being bug-compatible, or not being drop-in.
November 06, 2019
On Thursday, 31 October 2019 at 10:14:59 UTC, Guillaume Piolat wrote:
> Moreover, actual printf implementations seems to depend upon the locale. This creates bugs (say "1,4" instead of "1.4") so this behaviour depends if you want to be bug-compatible. We've been hit by that in `printed` when used with a Russian locale.

Meanwhile, my implementation for the f (and F) qualifier is (almost) finished. Yet, the locale-stuff is missing and I do not manage to implement it. Maybe someone can help me:

a) I need to create some test. As far as I know, I've to execute "export LANG=de_DE.UTF-8" (in bash, debian) to make it use the german locale, which should replace the dot by a comma. Unfortunately writefln!"%.10f"(0.1) still writes a dot instead of the expected ",". Instead of "LANG" I tried several other stuff, like LC_ALL or LC_NUMERIC. Any idea what I do wrong here?

b) How to query the current locale from D? Actually I only need the number-separator in the current locale as a dchar. I found core.stdc.locale but do not know how to use it.


November 06, 2019
On Wednesday, 6 November 2019 at 13:25:38 UTC, berni44 wrote:
> On Thursday, 31 October 2019 at 10:14:59 UTC, Guillaume Piolat wrote:
>> [...]
>
> Meanwhile, my implementation for the f (and F) qualifier is (almost) finished. Yet, the locale-stuff is missing and I do not manage to implement it. Maybe someone can help me:
>
> a) I need to create some test. As far as I know, I've to execute "export LANG=de_DE.UTF-8" (in bash, debian) to make it use the german locale, which should replace the dot by a comma. Unfortunately writefln!"%.10f"(0.1) still writes a dot instead of the expected ",". Instead of "LANG" I tried several other stuff, like LC_ALL or LC_NUMERIC. Any idea what I do wrong here?
>
> b) How to query the current locale from D? Actually I only need the number-separator in the current locale as a dchar. I found core.stdc.locale but do not know how to use it.

I think the best way to go is to make it locale-independent and simply provide a way for user to specify the decimal separator (and other related locale details, if any).
November 06, 2019
On Wednesday, 6 November 2019 at 13:25:38 UTC, berni44 wrote:
> On Thursday, 31 October 2019 at 10:14:59 UTC, Guillaume Piolat wrote:
>> Moreover, actual printf implementations seems to depend upon the locale. This creates bugs (say "1,4" instead of "1.4") so this behaviour depends if you want to be bug-compatible. We've been hit by that in `printed` when used with a Russian locale.
>
> Meanwhile, my implementation for the f (and F) qualifier is (almost) finished. Yet, the locale-stuff is missing and I do not manage to implement it. Maybe someone can help me:
>
> a) I need to create some test. As far as I know, I've to execute "export LANG=de_DE.UTF-8" (in bash, debian) to make it use the german locale, which should replace the dot by a comma. Unfortunately writefln!"%.10f"(0.1) still writes a dot instead of the expected ",". Instead of "LANG" I tried several other stuff, like LC_ALL or LC_NUMERIC. Any idea what I do wrong here?
>
> b) How to query the current locale from D? Actually I only need the number-separator in the current locale as a dchar. I found core.stdc.locale but do not know how to use it.

This question comes late, but did you considered to just do an 1 to 1 translation of snprintf from C to D? Of course the second step would be to provide an idiomatic D version with the mentioned suggestions.
But having a translation would already be fantastic.

Kind regards
Andre
November 06, 2019
On Wednesday, 6 November 2019 at 13:25:38 UTC, berni44 wrote:
> a) I need to create some test. As far as I know, I've to execute "export LANG=de_DE.UTF-8" (in bash, debian) to make it use the german locale, which should replace the dot by a comma. Unfortunately writefln!"%.10f"(0.1) still writes a dot instead of the expected ",". Instead of "LANG" I tried several other stuff, like LC_ALL or LC_NUMERIC. Any idea what I do wrong here?

If D wishes to behave the same as C, this is correct behavior. C requires the locale "C" to be activated at program startup.
The C-way to use the environment's locale is to call setlocale for the relevant category with an empty string for the locale value.
e. g. setlocale(LC_ALL, "")

> b) How to query the current locale from D? Actually I only need the number-separator in the current locale as a dchar. I found core.stdc.locale but do not know how to use it.

You can query the current locale of a given category by calling setlocale with a null-pointer for the locale, it will return the currently set locale as a C-string.

The formatting-information is returned by localeconv(). Not sure why the docs don't show the members of lconv, but it contains decimal_point, which is a C-string of the decimal separator.
setlocale(LC_ALL, "de_DE.UTF-8");
localeconv.decimal_point.fromStringz.writeln;
prints ","
November 06, 2019
On Wed, Nov 06, 2019 at 04:17:32PM +0000, Petar via Digitalmars-d wrote:
> On Wednesday, 6 November 2019 at 13:25:38 UTC, berni44 wrote:
[...]
> > b) How to query the current locale from D? Actually I only need the number-separator in the current locale as a dchar. I found core.stdc.locale but do not know how to use it.
> 
> I think the best way to go is to make it locale-independent and simply provide a way for user to specify the decimal separator (and other related locale details, if any).

Yes, I think in the long run this will be the more viable approach. Depending on locale as a global state is problematic because it forces formatting to be impure, and also forces users to implement hacks when they need to temporarily change the locale. E.g., in a system like snprintf, if you need to format German text with snippets of English quotations, you will have to temporarily override LC_* somehow in order to print a number with two different separators, or hack it with string postprocessing, etc..

It's better to let the user pass in the desired separator as a parameter -- the ',' flag in std.format already does this via the optional '?' modifier, for example:

	writefln("%,?d", '_', 12345678); // 12_345_678
	writefln("%,?d", '|', 12345678); // 12|345|678

Conceivably one could extend the '.' flag with a '?' modifier as well, so something like this:

	writefln("%.2?d", ',', 3.141592); // 3,14
	writefln("%.2?d", '_', 3.141592); // 3_14
	writefln("%.2?d", ':', 3.141592); // 3:14

Then programs that want to support locales can just do this:

	writefln("%.2?d", curLocale.separator, 3.141592);


T

-- 
I don't trust computers, I've spent too long programming to think that they can get anything right. -- James Miller