Search code examples
phpsymfonytwigintltwig-extension

How to increase decimal precision on percentage format using Twig's Intl extension?


I have a decimal number with 4 digits and a scale of 4. (Max is 0.9999 and min is 0.0000)

I'm using Twig and its intl extension. When I want to render a percent number, decimals are rounded.

{% set decimal = 0.0850 %}
{{ decimal|localizednumber('decimal','double','fr-fr') }} //WILL OUTPUT "0,085"
{{ decimal|localizednumber('decimal','double','zh-cn') }} //WILL OUTPUT "0.085"
{{ decimal|localizednumber('decimal','double','ar-bh') }} //WILL OUTPUT "٠٫٠٨٥"
{{ decimal|localizednumber('percent','double','fr-fr') }} //WILL OUTPUT "8 %"
{{ decimal|localizednumber('percent','double','zh-cn') }} //WILL OUTPUT "8%"
{{ decimal|localizednumber('percent','double','ar-bh') }} //WILL OUTPUT "% ٨"

I would like to see 8,5 % in French, 8.5% in chinese and % ٨٫٥ in arabic.

I tried to add the double parameter, but it does not change the precision.

As I am using Symfony, I tried to declare 2 decimals in number format:

<!-- lang-yml -->
#config/twig.yaml
twig:
    #...
    number_format:
        decimals: 2

It seems that the Intl extension is overriding these settings.

I know that I can do something like

{{ (decimal*100)|localizednumber('decimal','double')}}% 

But the % symbol can be before the result in some languages, in French, there is a non-breaking space before the % symbol.

Do you see my error? Do you have a solution?


Solution

  • Can't be done directly with Twig Intl extension you are using.

    It doesn't have a parameter to set the precision, it simply instantiate the NumberFormatter with the formatting style of your choice, and will use that to format() your value.

    Check the code here.


    There is another extension which does have more options: https://github.com/twigphp/intl-extra

    With this one you can specify all the attributes supported by NumberFormatter, as shown here.

    You would use it like this:

    {% set decimal = 0.0850 %}
    {{ decimal|format_number(style='percent', locale='fr', {min_fraction_digit: 1}) }}
    

    Alternatively, you could write your own extension by leveraging on NumberFormatter.

    The pattern that NumberFormatter::PERCENT uses by default is #,##0 %, which does not include decimal precision. You can define your own pattern following these rules so it does.

    Or simply call to setAttribute(NumberFormatter::MIN_FRACTION_DIGITS, 1) to specify the the minimum number of decimal numbers you are interested in.

    For example:

    $formatter->setAttribute(NumberFormatter::MIN_FRACTION_DIGITS, 1);
    

    The final implementation is up to you, and if you'd need to use it within a Twig template you'd have to create your own (official Symfony docs).

    See more examples here.