2

I have the following code:

$lang="de-AT";
$currency="3333";
$formatter = new NumberFormatter($lang, NumberFormatter::DECIMAL);
$formatter->setAttribute(NumberFormatter::MAX_FRACTION_DIGITS, 2);

echo $formatter->format($currency);

can be run in here with copy/paste:online php (though I don't know the php version of this site)

which outputs: 3.333 and is exactly what I've expected.

But on my local host with PHP 7.0.20 and PHPUnit 6.2.1 the Unit test gives me as result: 3 333. phpunit output

Any idea what's new or why?

hakre
  • 193,403
  • 52
  • 435
  • 836
Edwin
  • 2,146
  • 20
  • 26

1 Answers1

2

The difference you see here for the locales de-AT:

3.333

and

3 333

is just that with a bare string comparison, there is a difference.

For written language, there is not. Both forms are correct in that locale and show the same number.

However, you'd like to configure that more explicitly, for that, command the number-formatter to use the dot '.' as thousands separator (instead of using the compiled in locale information):

$formatter->setSymbol(NumberFormatter::GROUPING_SEPARATOR_SYMBOL, '.');

Configuration Data

The underlying cause is that the PHP intl extension next to the actual code ships with language data (from the CLDR project) which consists of the formatting information in form of symbols and rules. That means, that the formatting can change (as you found out in your Phpunit test) even if the extension version is the same. Derived from your example:

  • Output for hhvm-3.15.4 - 3.19.0, 7.2.0alpha1

    3.333 1.1.0

  • Output for 5.6.0 - 5.6.30, 7.0.0 - 7.1.6

    3 333 1.1.0

The line which is causing the space instead of the dot is:

http://unicode.org/cldr/trac/browser/trunk/common/main/de_AT.xml#L120 (@13494)

The concrete change:

http://unicode.org/cldr/trac/changeset/11798/trunk/common/main/de_AT.xml

Previously the number group symbol was taken over from parent locale which has the dot.

That is in Changeset 11798 Timestamp: 07/13/15 12:38:02 (2 years ago) - Releases take time, so this is why you see this only in the later releases of the library.

I can only stress the point that this is configuration data.

Dealing with Configuration in (Unit-) Tests

In a unit-test you normally don't want to test for that. In a configuration test, you might want to test for that. Your Phpunit-test did reveal that the expectation you had so far is not matched any longer. So this might require either a code-change (that is to make your configuration expectation working again) or a change in the test, as you were testing locale specific configuration you might have not been what you were looking for.

From your question I can imagine that both is possible. In the end, the test reflects your expectation and might have revealed a hidden dependency, here the locale configuration data.

A fix could be as little as switching the locale to "de" instead of "de-AT": https://3v4l.org/hB15n

  • Output for 5.6.0 - 5.6.30, hhvm-3.15.4 - 3.19.0, 7.0.0 - 7.2.0alpha1

    3.333 1.1.0

But keep in mind that this would also hide the underlying issue that you might have tested for the wrong thing. So better keep the failing test as a note to ask yourself about the expectations you had and if the code does for what you have it written for.

hakre
  • 193,403
  • 52
  • 435
  • 836
  • but this exactly code works for other php versions (like V7.0.12 or 5.6.x), the thing I did now is just to update the php version and then the unit test failed. – Edwin Jun 14 '17 at 11:22
  • That is library specific to the compilation of the intl library/ies. This information comes from CLDR and can change between releases. You would need to track the changes there and compare with INTL releases and then with the PHP intl module releases. If you found the upstream change, you can start to learn more about *why* this changed in specific and better decide whether this construes a flaw or not. As far as the language/locale is concerned, both numbers could be argued as being equally well and therefore "no" change was introduced. – hakre Jun 14 '17 at 11:25
  • @Edwin: I added an example line of code which you can make use of to change taht explicitly (based on your example code). – hakre Jun 14 '17 at 11:30
  • 1
    And for your test: Better check against a regex as otherwise you would check for the concrete locale configuration which does render locale abstraction sort of superfluous, as long as this is not a configuration/integration test. – hakre Jun 14 '17 at 11:36
  • 1
    @Edwin: Added the infos what is causing this. I can't say from your question alone what the correct way to handle this in your code or test-code is, this depends on your expectations. So far I can only explain why this happens and outline the difference between configuration and code. Depends a lot on what you want. I also can't say if this is worth a report with CLDR, the entry is marked as draft (at least in the XML file) and I'm no Austrian locale specialist to say whether this construes a configuration flaw or not. All I know that fixes to CLDR can take quite long until they end up in PHP. – hakre Jun 14 '17 at 12:16
  • nice research on the topic and btw the `GROUPING_SEPARATOR_SYMBOL` will not be correct if I'll have another locale like en and then the formatter will lose its purpose. – Edwin Jun 14 '17 at 12:46
  • another thing if I use only `at` instead of `de-AT` works as expected, isn't this strange? – Edwin Jun 14 '17 at 12:54
  • This is not strange, it is the underlying configuration data. And it is hard to argue that space is incorrect. I'll ask a "native" Austrian how common the space is for grouping. I know that for German it is correct to use a space as separator for number groups as well. This is also part of the DIN/ISO norm for numbers. More references with Wikipedia: https://de.wikipedia.org/wiki/Schreibweise_von_Zahlen – hakre Jun 14 '17 at 16:33
  • Also there is a formatter in Intl for currency if that is what you're looking for. But you might find a space as separator there as well, just saying. http://php.net/numberformatter.formatcurrency – hakre Jun 14 '17 at 16:36