Numeric representations can vary by locale. As a simple example, in the UK one would see the number three million, eighty thousand, five hundred and twelve, and ninety-two one hundredths as follows:
3,080,512.92.
In France, however, the same number might appear like so:
3 080 512,92
Before you can represent a number in a locale-specific manner, you need to determine the locale. This can be accomplished using the Application\I18n\Locale class discussed in the previous recipe. The locale can be set manually or from header information.
format() method of the NumberFormatter class, to both output and parse numbers in a locale-specific format. First we add a property that will contain an instance of the NumberFormatter class:use NumberFormatter; protected $numberFormatter;
Our initial thought would be to consider using the PHP function setlocale() to produce numbers formatted according to locale. The problem with this legacy approach, however, is that everything will be considered based on this locale. This could introduce problems dealing with data that is stored according to database specifications. Another issue with setlocale() is that it is based on outdated standards, including RFC 1766 and ISO 639. Finally, setlocale() is highly dependent on operating system locale support, which will make our code non-portable.
$numberFormatter in the constructor. The problem with this approach, in the case of our Application\I18n\Locale class, is that we would end up with a top-heavy class, as we will also need to perform currency and date formatting as well. Accordingly, we add a getter that first checks to see whether an instance of NumberFormatter has already been created. If not, an instance is created and returned. The first argument in the new NumberFormatter is the locale code. The second argument, NumberFormatter::DECIMAL, represents what type of formatting we need:public function getNumberFormatter()
{
if (!$this->numberFormatter) {
$this->numberFormatter = new NumberFormatter($this->getLocaleCode(), NumberFormatter::DECIMAL);
}
return $this->numberFormatter;
}public function formatNumber($number)
{
return $this->getNumberFormatter()->format($number);
}FALSE on parse failure depending on the server's ICU version:public function parseNumber($string)
{
$result = $this->getNumberFormatter()->parse($string);
return ($result) ? $result : self::ERROR_UNABLE_TO_PARSE;
}Make the additions to the Application\I18n\Locale class as discussed in the preceding bullet points. You can then create a chap_08_formatting_numbers.php file, which sets up autoloading and uses this class:
<?php require __DIR__ . '/../Application/Autoload/Loader.php'; Application\Autoload\Loader::init(__DIR__ . '/..'); use Application\I18n\Locale;
For this illustration, create two Locale instances, one for the UK, the other for France. You can also designate a large number to be used for testing:
$localeFr = new Locale('fr_FR');
$localeUk = new Locale('en_GB');
$number = 1234567.89;
?>Finally, you can wrap the formatNumber() and parseNumber() methods in the appropriate HTML display logic and view the results:
<!DOCTYPE html>
<html>
<head>
<title>PHP 7 Cookbook</title>
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<link rel="stylesheet" type="text/css" href="php7cookbook_html_table.css">
</head>
<body>
<table>
<tr>
<th>Number</th>
<td>1234567.89</td>
</tr>
<tr>
<th>French Format</th>
<td><?= $localeFr->formatNumber($number); ?></td>
</tr>
<tr>
<th>UK Format</th>
<td><?= $localeUk->formatNumber($number); ?></td>
</tr>
<tr>
<th>UK Parse French Number: <?= $localeFr->formatNumber($number) ?></th>
<td><?= $localeUk->parseNumber($localeFr->formatNumber($number)); ?></td>
</tr>
<tr>
<th>UK Parse UK Number: <?= $localeUk->formatNumber($number) ?></th>
<td><?= $localeUk->parseNumber($localeUk->formatNumber($number)); ?></td>
</tr>
<tr>
<th>FR Parse FR Number: <?= $localeFr->formatNumber($number) ?></th>
<td><?= $localeFr->parseNumber($localeFr->formatNumber($number)); ?></td>
</tr>
<tr>
<th>FR Parse UK Number: <?= $localeUk->formatNumber($number) ?></th>
<td><?= $localeFr->parseNumber($localeUk->formatNumber($number)); ?></td>
</tr>
</table>
</body>
</html>Here is the result as seen from a browser:

Note that if the locale is set to fr_FR, a UK formatted number, when parsed, does not return the correct value. Likewise, when the locale is set to en_GB, a French formatted number does not return the correct value upon parsing. Accordingly, you might want to consider adding a validation check before attempting to parse the number.
setlocale() please refer to this page: http://php.net/manual/en/function.setlocale.php.