Question


I'm using the Intl libary to format numbers with currency symbol.

$number = new NumberFormatter('es_ES', NumberFormatter::CURRENCY);
echo $number->format('234234.234324');

My local php version:

version 1.1.0
ICU version 50.1.2
ICU Data version    50.1

Server:

version 1.1.0
ICU version 50.1.2

Results:
My version:234.234,23 €
Server version:€ 234.234,23

The currency symbol should be at the end of the number instead of being at the beginning of the number

Thanks

Was it helpful?

Solution

I made it as a helper.

/**
 * Number format wrapper
 */
class NumberFormat extends Helper\NumberFormat {
    private $serviceLocator;

    public function setServiceLocator($service) {
        $this->serviceLocator = $service;
    }
    /**
     * Number format
     * @param type $number
     * @param type $decimals
     * @param type $formatStyle
     * @param string $currency
     * @param type $locale
     * @return string
     */
    public function __invoke(
        $number,
        $decimals    = null,
        $formatStyle = null,
        $currency  = null,
        $locale      = null
    ) {

        $currency = strtoupper($currency);
        //get current locale
        $currentLocale = $this->serviceLocator->get('translator')->getLocale();
        $config  =  $this->serviceLocator->get('config');

        //mapping between countries
        if(isset($config['application-options']['currency-symbol-map'][$currentLocale])) {
            $currenciesMapping = $config['application-options']['currency-symbol-map'];
            $localeCurrency = $currenciesMapping[$currentLocale];
            //England pound != euro
            if(strtolower($currency) != $localeCurrency) {
                $locale = array_search($currency,$currenciesMapping);
            }
        };

        if (!$locale) {
            $locale = $currentLocale;
        }
        if (null === $formatStyle) {
            $formatStyle = $this->getFormatStyle();
        }

        if (!is_int($decimals) || $decimals < 0) {
            $decimals = $this->getDecimals();
        }
        // 6.000000 should be 6.00 and decimals more than 2
        $numberExplode = explode('.',$number);

        if($decimals > 2 && $numberExplode[1] == 0) {
            $decimals = 2;
        }

        $formatType = $this->getFormatType();

        $formatterId = md5($formatStyle . "\0" . $locale . "\0" . $decimals);

        if (!isset($this->formatters[$formatterId])) {
            $this->formatters[$formatterId] = new NumberFormatter(
                $locale,
                $formatStyle
            );

            if ($decimals !== null) {
                $this->formatters[$formatterId]->setAttribute(NumberFormatter::MIN_FRACTION_DIGITS, $decimals);
                $this->formatters[$formatterId]->setAttribute(NumberFormatter::MAX_FRACTION_DIGITS, $decimals);
            }
        }

        //modify pattern
        //always at the begining
        if($formatStyle == \NumberFormatter::CURRENCY) {
            $pattern = str_replace('¤','',$this->formatters[$formatterId]->getPattern());
            $this->formatters[$formatterId]->setPattern('¤'.$pattern);
        }
        if($currency == null)
            return  $this->formatters[$formatterId]->format($number, $formatType);
        else
            return $this->formatters[$formatterId]->formatCurrency($number,$currency);
    }
}

OTHER TIPS

I was having the exact same problem with the intl extension installed by Plesk with PHP 7.1.

$ /opt/plesk/php/7.1/bin/php -a
Interactive shell

php > $a = new \NumberFormatter("es_ES", \NumberFormatter::CURRENCY);
php > echo $a->format(12345.12345);
€ 12.345,12

Those were the versions of ICU it was using as seen with /opt/plesk/php/7.1/bin/php -i:

version  => 1.1.0
ICU version  => 4.2.1

To solve it I had to compile from source a newer version of ICU (the most recent I was able to compile without errors was 58.2) and then compile also from source the intl extension for my PHP version using that ICU (as I'm using Plesk the binaries of PHP are the ones used by it):

wget http://download.icu-project.org/files/icu4c/58.2/icu4c-58_2-src.tgz
tar xzvf icu4c-58_2-src.tgz
cd icu/source/
CXXFLAGS="-std=c++0x" ./runConfigureICU Linux --prefix=/opt/icu4c-58_2
make
sudo make install

cd ../../

wget http://php.net/distributions/php-7.1.22.tar.gz
tar xzvf php-7.1.22.tar.gz
cd php-7.1.22/ext/intl
/opt/plesk/php/7.1/bin/phpize
./configure --with-php-config=/opt/plesk/php/7.1/bin/php-config --enable-intl --with-icu-dir=/opt/icu4c-58_2
make
sudo make install

Then make sure the extension is loaded, in my case in /opt/plesk/php/7.1/etc/php.d/intl.ini:

; Enable intl extension module
extension=intl.so

Then restart or reload httpd, Apache, PHP-FPM or whatever is loading PHP:

sudo service httpd restart

The versions shown by /opt/plesk/php/7.1/bin/php -i now:

version => 1.1.0
ICU version => 58.2
ICU Data version => 58.2

Now the currency is properly displayed:

$ /opt/plesk/php/7.1/bin/php -a
Interactive shell

php > $a = new \NumberFormatter("es_ES", \NumberFormatter::CURRENCY);
php > echo $a->format(12345.12345);
12.345,12 €
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top