elixir-cldr / cldr_numbers

CLDR Number localisation and formatting
Other
41 stars 23 forks source link

Always show the group separator #5

Closed rbngzlv closed 6 years ago

rbngzlv commented 6 years ago

Hi, sorry for bother you, but I can't get the correct code to always show the group separator.

iex(22)> Cldr.Number.to_string 11345.32, format: "#,##0.00 ¤;-#,##0.00 ¤", currency: :EUR
{:ok, "11.345,32 €"}
iex(23)> Cldr.Number.to_string 1345.32, format: "#,##0.00 ¤;-#,##0.00 ¤", currency: :EUR
{:ok, "1345,32 €"}

I tried some variants to also show the group separator in the second example, but without luck. I'm lost here, I don't know if this is related to the pattern, a bad configuration or to some internals of the library.

I have also take a look in the CLDR unicode site to see if this is by "design". I have not found anything concrete to this, but some examples of my case:

http://cldr.unicode.org/translation/number-patterns For example: #,##0.00¤;(#,##0.00¤) is used to make negative currencies appear like "(1'234,56£)" instead of "-1'234,56£". That is used for formatting currency amounts in English, but not for general-purpose decimal numbers.

http://cldr.unicode.org/translation/number-symbols

screen shot 2018-07-04 at 10 30 43

Can someone give me a clue on this, please? Thanks for the great library

kipcole9 commented 6 years ago

My apologies for the inconvenience. Thank you too for taking the time to dig a little deeper. I will investigate in the next few hours and revert with either a finding around the source data or a potential bug in my code.

—Kip

kipcole9 commented 6 years ago

Apologies for the slow response. I did some exploration of a few locales to see if I could replicate what you are seeing:

iex> Cldr.Number.to_string 1345.32, format: "#,##0.00 ¤;-#,##0.00 ¤", currency: :EUR, locale: "de"
{:ok, "1.345,32 €"}
iex> Cldr.Number.to_string 1345.32, format: "#,##0.00 ¤;-#,##0.00 ¤", currency: :EUR, locale: "es"
{:ok, "1345,32 €"}
iex> Cldr.Number.to_string 1345.32, format: "#,##0.00 ¤;-#,##0.00 ¤", currency: :EUR, locale: "fr"
{:ok, "1 345,32 €"}
iex> Cldr.Number.to_string 1345.32, format: "#,##0.00 ¤;-#,##0.00 ¤", currency: :EUR, locale: "en"
{:ok, "1,345.32 €"}

And I can see with the locale es I get the same result you see - is that the locale you had in affect?

The reference for handling grouping in CLDR is TR35 in the section on minimum grouping digits.

If you scroll back a few lines from that link you will see how it handles grouping depending on the locales definition of "minimum grouping digits". You can find out what that is:

iex> Cldr.Number.Format.minimum_grouping_digits_for "en"        
{:ok, 1}
iex> Cldr.Number.Format.minimum_grouping_digits_for "fr"
{:ok, 1}
iex> Cldr.Number.Format.minimum_grouping_digits_for "de"
{:ok, 1}
iex> Cldr.Number.Format.minimum_grouping_digits_for "es"
{:ok, 2}

You can see that for the locale es the minimum_grouping_digits is 2 which, per TR35, means that 2 is added to the number of grouping digits in the format which, in your example, is 3. Adding 2 + 3 = 5. Therefore at least 5 digits are required before grouping is performed. Which is why 1345.32 is formatted as 1345,32 €. I checked and it is the same for all the es-* locales as well.

Therefore it appears to be formatting as intended by the standard - but clearly not the way you want it.

The only solution I can see is to support a parameter that overrides the CLDR standard for grouping digits that you can then set - definitely doable but i can't promise an immediate update.

kipcole9 commented 6 years ago

A new release v1.5.0 is available with a new option to Cldr.Number.to_string/2. It is also released on hex.

This allows you to format the following:

# Default format
iex> Cldr.Number.to_string 1345.32, currency: :EUR, locale: "es"                            
{:ok, "1345,32 €"}
# Using the :minimum_grouping_digits options
iex> Cldr.Number.to_string 1345.32, currency: :EUR, locale: "es", minimum_grouping_digits: 1
{:ok, "1.345,32 €"}

Hope that delivers what you're after.

rbngzlv commented 6 years ago

And I can see with the locale es I get the same result you see - is that the locale you had in affect?

Yes, that is :)

You can see that for the locale es the minimum_grouping_digits is 2 which, per TR35, means that 2 is added to the number of grouping digits in the format which, in your example, is 3. Adding 2 + 3 = 5. Therefore at least 5 digits are required before grouping is performed. Which is why 1345.32 is formatted as 1345,32 €. I checked and it is the same for all the es-* locales as well.

Very friendly explanation, many thanks for your time investigating this.

A new release v1.5.0 is available with a new option to Cldr.Number.to_string/2. It is also released on hex.

Thanks for adding the feature so fast.