From cfa5b7759d20eeec7918c17d1d4a38d2bb13af6e Mon Sep 17 00:00:00 2001
From: sgiehl <stefan@piwik.org>
Date: Sat, 26 Sep 2015 16:55:57 +0200
Subject: [PATCH] improved numberformatter, fixed tests

---
 core/NumberFormatter.php                      | 75 ++++++++++++-------
 .../CoreVisualizations/javascripts/jqplot.js  | 37 +++++----
 plugins/Intl/Commands/GenerateIntl.php        |  4 +-
 plugins/Intl/lang/am.json                     |  3 +-
 plugins/Intl/lang/ar.json                     |  3 +-
 plugins/Intl/lang/be.json                     |  3 +-
 plugins/Intl/lang/bg.json                     |  3 +-
 plugins/Intl/lang/bn.json                     |  3 +-
 plugins/Intl/lang/bs.json                     |  3 +-
 plugins/Intl/lang/ca.json                     |  3 +-
 plugins/Intl/lang/cs.json                     |  3 +-
 plugins/Intl/lang/cy.json                     |  3 +-
 plugins/Intl/lang/da.json                     |  3 +-
 plugins/Intl/lang/de.json                     |  3 +-
 plugins/Intl/lang/el.json                     |  3 +-
 plugins/Intl/lang/en.json                     |  3 +-
 plugins/Intl/lang/es.json                     |  3 +-
 plugins/Intl/lang/et.json                     |  3 +-
 plugins/Intl/lang/eu.json                     |  3 +-
 plugins/Intl/lang/fa.json                     |  3 +-
 plugins/Intl/lang/fi.json                     |  3 +-
 plugins/Intl/lang/fr.json                     |  3 +-
 plugins/Intl/lang/gl.json                     |  3 +-
 plugins/Intl/lang/he.json                     |  3 +-
 plugins/Intl/lang/hi.json                     |  3 +-
 plugins/Intl/lang/hr.json                     |  3 +-
 plugins/Intl/lang/hu.json                     |  3 +-
 plugins/Intl/lang/id.json                     |  3 +-
 plugins/Intl/lang/is.json                     |  3 +-
 plugins/Intl/lang/it.json                     |  3 +-
 plugins/Intl/lang/ja.json                     |  3 +-
 plugins/Intl/lang/ka.json                     |  3 +-
 plugins/Intl/lang/ko.json                     |  3 +-
 plugins/Intl/lang/lt.json                     |  3 +-
 plugins/Intl/lang/lv.json                     |  3 +-
 plugins/Intl/lang/nb.json                     |  3 +-
 plugins/Intl/lang/nl.json                     |  3 +-
 plugins/Intl/lang/nn.json                     |  3 +-
 plugins/Intl/lang/pl.json                     |  3 +-
 plugins/Intl/lang/pt-br.json                  |  3 +-
 plugins/Intl/lang/pt.json                     |  3 +-
 plugins/Intl/lang/ro.json                     |  3 +-
 plugins/Intl/lang/ru.json                     |  3 +-
 plugins/Intl/lang/sk.json                     |  3 +-
 plugins/Intl/lang/sl.json                     |  3 +-
 plugins/Intl/lang/sq.json                     |  3 +-
 plugins/Intl/lang/sr.json                     |  3 +-
 plugins/Intl/lang/sv.json                     |  3 +-
 plugins/Intl/lang/ta.json                     |  3 +-
 plugins/Intl/lang/te.json                     |  3 +-
 plugins/Intl/lang/th.json                     |  3 +-
 plugins/Intl/lang/tl.json                     |  3 +-
 plugins/Intl/lang/tr.json                     |  3 +-
 plugins/Intl/lang/uk.json                     |  3 +-
 plugins/Intl/lang/vi.json                     |  3 +-
 plugins/Intl/lang/zh-cn.json                  |  3 +-
 plugins/Intl/lang/zh-tw.json                  |  3 +-
 .../templates/_jsGlobalVariables.twig         |  3 +-
 .../tests/Integration/DashboardTest.php       |  3 +
 tests/PHPUnit/Unit/Metrics/FormatterTest.php  | 21 ++----
 60 files changed, 138 insertions(+), 167 deletions(-)

diff --git a/core/NumberFormatter.php b/core/NumberFormatter.php
index 0839cb4ba7..5324b552a0 100644
--- a/core/NumberFormatter.php
+++ b/core/NumberFormatter.php
@@ -17,11 +17,8 @@ use Piwik\Container\StaticContainer;
  */
 class NumberFormatter extends Singleton
 {
-    /** @var string language specific pattern for positive numbers */
-    protected $patternPositive;
-
-    /** @var string language specific pattern for negative numbers */
-    protected $patternNegative;
+    /** @var string language specific patterns for numbers */
+    protected $patternNumber;
 
     /** @var string language specific pattern for percent numbers */
     protected $patternPercent;
@@ -50,39 +47,34 @@ class NumberFormatter extends Singleton
     /** @var int language specific size for secondary group numbers */
     protected $secondaryGroupSize;
 
-    /**
-     * @return NumberFormatter
-     */
-    public static function getInstance()
-    {
-        return StaticContainer::get('Piwik\NumberFormatter');
-    }
-
     /**
      * Loads all required data from Intl plugin
      */
     public function __construct()
     {
-        $this->patternPositive = Piwik::translate('Intl_NumberFormat');
-        $this->patternNegative = Piwik::translate('Intl_NumberFormatNegative');
+        $this->patternNumber = Piwik::translate('Intl_NumberFormatNumber');
         $this->patternPercent = Piwik::translate('Intl_NumberFormatPercent');
         $this->symbolPlus = Piwik::translate('Intl_NumberSymbolPlus');
         $this->symbolMinus = Piwik::translate('Intl_NumberSymbolMinus');
         $this->symbolPercent = Piwik::translate('Intl_NumberSymbolPercent');
         $this->symbolGroup = Piwik::translate('Intl_NumberSymbolGroup');
         $this->symbolDecimal = Piwik::translate('Intl_NumberSymbolDecimal');
+    }
 
-        $this->usesGrouping = (strpos($this->patternPositive, ',') !== false);
-        // if pattern has number groups, parse them.
-        if ($this->usesGrouping) {
-            preg_match('/#+0/', $this->patternPositive, $primaryGroupMatches);
-            $this->primaryGroupSize = $this->secondaryGroupSize = strlen($primaryGroupMatches[0]);
-            $numberGroups = explode(',', $this->patternPositive);
-            // check for distinct secondary group size.
-            if (count($numberGroups) > 2) {
-                $this->secondaryGroupSize = strlen($numberGroups[1]);
-            }
+    /**
+     * Parses the given pattern and returns patterns for positive and negative numbers
+     *
+     * @param string $pattern
+     * @return array
+     */
+    protected function parsePattern($pattern)
+    {
+        $patterns = explode(';', $pattern);
+        if (!isset($patterns[1])) {
+            // No explicit negative pattern was provided, construct it.
+            $patterns[1] = '-' . $patterns[0];
         }
+        return $patterns;
     }
 
     /**
@@ -95,8 +87,14 @@ class NumberFormatter extends Singleton
      */
     public function format($value, $maximumFractionDigits=0, $minimumFractionDigits=0)
     {
+        static $positivePattern, $negativePattern;
+
+        if (empty($positivePatter) || empty($negativePattern)) {
+            list($positivePattern, $negativePattern) = $this->parsePattern($this->patternNumber);
+        }
         $negative = (bccomp('0', $value, 12) == 1);
-        $pattern = $negative ? $this->patternNegative : $this->patternPositive;
+        $pattern = $negative ? $negativePattern : $positivePattern;
+
         return $this->formatNumberWithPattern($pattern, $value, $maximumFractionDigits, $minimumFractionDigits);
     }
 
@@ -124,11 +122,21 @@ class NumberFormatter extends Singleton
      */
     public function formatPercent($value, $maximumFractionDigits=0, $minimumFractionDigits=0)
     {
+        static $positivePattern, $negativePattern;
+
+        if (empty($positivePatter) || empty($negativePattern)) {
+            list($positivePattern, $negativePattern) = $this->parsePattern($this->patternPercent);
+        }
+
         $newValue =  trim($value, " \0\x0B%");
         if (!is_numeric($newValue)) {
             return $value;
         }
-        return $this->formatNumberWithPattern($this->patternPercent, $newValue, $maximumFractionDigits, $minimumFractionDigits);
+
+        $negative = (bccomp('0', $value, 12) == 1);
+        $pattern = $negative ? $negativePattern : $positivePattern;
+
+        return $this->formatNumberWithPattern($pattern, $newValue, $maximumFractionDigits, $minimumFractionDigits);
     }
 
     /**
@@ -145,6 +153,19 @@ class NumberFormatter extends Singleton
         if (!is_numeric($value)) {
             return $value;
         }
+
+        $this->usesGrouping = (strpos($pattern, ',') !== false);
+        // if pattern has number groups, parse them.
+        if ($this->usesGrouping) {
+            preg_match('/#+0/', $pattern, $primaryGroupMatches);
+            $this->primaryGroupSize = $this->secondaryGroupSize = strlen($primaryGroupMatches[0]);
+            $numberGroups = explode(',', $pattern);
+            // check for distinct secondary group size.
+            if (count($numberGroups) > 2) {
+                $this->secondaryGroupSize = strlen($numberGroups[1]);
+            }
+        }
+
         // Ensure that the value is positive and has the right number of digits.
         $negative = (bccomp('0', $value, 12) == 1);
         $signMultiplier = $negative ? '-1' : '1';
diff --git a/plugins/CoreVisualizations/javascripts/jqplot.js b/plugins/CoreVisualizations/javascripts/jqplot.js
index 6d55feb023..fac656f5ae 100644
--- a/plugins/CoreVisualizations/javascripts/jqplot.js
+++ b/plugins/CoreVisualizations/javascripts/jqplot.js
@@ -753,19 +753,6 @@ RowEvolutionSeriesToggle.prototype.beforeReplot = function () {
 // ------------------------------------------------------------
 (function($){
 
-    var usesGrouping = (piwik.numbers.patternPositive.indexOf(',') != -1);
-    // if pattern has number groups, parse them.
-    if (usesGrouping) {
-        var primaryGroupMatches = piwik.numbers.patternPositive.match(/#+0/);
-        var primaryGroupSize = primaryGroupMatches[0].length;
-        var secondaryGroupSize = primaryGroupMatches[0].length;
-        var numberGroups = piwik.numbers.patternPositive.split(',');
-        // check for distinct secondary group size.
-        if (numberGroups.length > 2) {
-            secondaryGroupSize = numberGroups[1].length;
-        }
-    }
-
     function replaceSymbols(value) {
         var replacements = {
             '.': piwik.numbers.symbolDecimal,
@@ -799,9 +786,31 @@ RowEvolutionSeriesToggle.prototype.beforeReplot = function () {
         if (!$.isNumeric(value)) {
             return format.replace(/%s/, value);
         }
+        pattern = pattern || piwik.numbers.patternNumber;
+
+        var patterns = pattern.split(';');
+        if (patterns.length == 1) {
+            // No explicit negative pattern was provided, construct it.
+            patterns.push('-' + patterns[0])
+        }
+
         // Ensure that the value is positive and has the right number of digits.
         var negative = value < 0;
-        pattern = pattern || (negative ? piwik.numbers.patternNegative : piwik.numbers.patternPositive);
+        pattern = negative ? patterns[1] : patterns[0];
+
+        var usesGrouping = (pattern.indexOf(',') != -1);
+        // if pattern has number groups, parse them.
+        if (usesGrouping) {
+            var primaryGroupMatches = pattern.match(/#+0/);
+            var primaryGroupSize = primaryGroupMatches[0].length;
+            var secondaryGroupSize = primaryGroupMatches[0].length;
+            var numberGroups = pattern.split(',');
+            // check for distinct secondary group size.
+            if (numberGroups.length > 2) {
+                secondaryGroupSize = numberGroups[1].length;
+            }
+        }
+
         var signMultiplier = negative ? '-1' : '1';
         value = value * signMultiplier;
         // Split the number into major and minor digits.
diff --git a/plugins/Intl/Commands/GenerateIntl.php b/plugins/Intl/Commands/GenerateIntl.php
index 42195ea969..97a00792cc 100644
--- a/plugins/Intl/Commands/GenerateIntl.php
+++ b/plugins/Intl/Commands/GenerateIntl.php
@@ -335,15 +335,13 @@ class GenerateIntl extends ConsoleCommand
             $unitsData = $unitsData['main'][$requestLangCode]['numbers'];
 
             $numberingSystem = $unitsData['defaultNumberingSystem'];
-            $numberFormats   = explode(';', $unitsData['decimalFormats-numberSystem-' . $numberingSystem]['standard']);
 
             $translations['Intl']['NumberSymbolDecimal']  = $unitsData['symbols-numberSystem-' . $numberingSystem]['decimal'];
             $translations['Intl']['NumberSymbolGroup']    = $unitsData['symbols-numberSystem-' . $numberingSystem]['group'];
             $translations['Intl']['NumberSymbolPercent']  = $unitsData['symbols-numberSystem-' . $numberingSystem]['percentSign'];
             $translations['Intl']['NumberSymbolPlus']     = $unitsData['symbols-numberSystem-' . $numberingSystem]['plusSign'];
             $translations['Intl']['NumberSymbolMinus']    = $unitsData['symbols-numberSystem-' . $numberingSystem]['minusSign'];
-            $translations['Intl']['NumberFormat']         = $numberFormats[0];
-            $translations['Intl']['NumberFormatNegative'] = isset($numberFormats[1]) ? $numberFormats[1] : ('-'.$numberFormats[0]);
+            $translations['Intl']['NumberFormatNumber']   = $unitsData['decimalFormats-numberSystem-' . $numberingSystem]['standard'];
             $translations['Intl']['NumberFormatPercent']  = $unitsData['percentFormats-numberSystem-' . $numberingSystem]['standard'];
 
             $output->writeln('Saved number formatting data for ' . $langCode);
diff --git a/plugins/Intl/lang/am.json b/plugins/Intl/lang/am.json
index 88d84d3d11..04f60fcd0a 100644
--- a/plugins/Intl/lang/am.json
+++ b/plugins/Intl/lang/am.json
@@ -539,8 +539,7 @@
         "NMinutesShort": "%s ደቂቃ",
         "NSeconds": "%s ሰከንዶች",
         "NSecondsShort": "%s ሰ",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0%",
         "NumberSymbolDecimal": ".",
         "NumberSymbolGroup": ",",
diff --git a/plugins/Intl/lang/ar.json b/plugins/Intl/lang/ar.json
index a951704cce..e0fe35ab53 100644
--- a/plugins/Intl/lang/ar.json
+++ b/plugins/Intl/lang/ar.json
@@ -555,8 +555,7 @@
         "NMinutesShort": "%s د",
         "NSeconds": "%s ثانية",
         "NSecondsShort": "%s Ø«",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0%",
         "NumberSymbolDecimal": "Ù«",
         "NumberSymbolGroup": "Ù¬",
diff --git a/plugins/Intl/lang/be.json b/plugins/Intl/lang/be.json
index fa8a8a638f..9b23011830 100644
--- a/plugins/Intl/lang/be.json
+++ b/plugins/Intl/lang/be.json
@@ -516,8 +516,7 @@
         "NMinutesShort": "%s хв.",
         "NSeconds": "%s секунды",
         "NSecondsShort": "%sс",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0 %",
         "NumberSymbolDecimal": ",",
         "NumberSymbolGroup": " ",
diff --git a/plugins/Intl/lang/bg.json b/plugins/Intl/lang/bg.json
index 36fedf34ff..ea11785a82 100644
--- a/plugins/Intl/lang/bg.json
+++ b/plugins/Intl/lang/bg.json
@@ -555,8 +555,7 @@
         "NMinutesShort": "%s min",
         "NSeconds": "%s секунди",
         "NSecondsShort": "%s s",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0%",
         "NumberSymbolDecimal": ",",
         "NumberSymbolGroup": " ",
diff --git a/plugins/Intl/lang/bn.json b/plugins/Intl/lang/bn.json
index ec55e36ec2..316a8c1a65 100644
--- a/plugins/Intl/lang/bn.json
+++ b/plugins/Intl/lang/bn.json
@@ -555,8 +555,7 @@
         "NMinutesShort": "%s মিনিট",
         "NSeconds": "%s সেকেন্ড",
         "NSecondsShort": "%s সেকেন্ড",
-        "NumberFormat": "#,##,##0.###",
-        "NumberFormatNegative": "-#,##,##0.###",
+        "NumberFormatNumber": "#,##,##0.###",
         "NumberFormatPercent": "#,##,##0%",
         "NumberSymbolDecimal": ".",
         "NumberSymbolGroup": ",",
diff --git a/plugins/Intl/lang/bs.json b/plugins/Intl/lang/bs.json
index 7b10e44f99..a924c94b9e 100644
--- a/plugins/Intl/lang/bs.json
+++ b/plugins/Intl/lang/bs.json
@@ -555,8 +555,7 @@
         "NMinutesShort": "%s min",
         "NSeconds": "%s sekundi",
         "NSecondsShort": "%s sek",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0%",
         "NumberSymbolDecimal": ",",
         "NumberSymbolGroup": ".",
diff --git a/plugins/Intl/lang/ca.json b/plugins/Intl/lang/ca.json
index d71fe0c7c9..76d45c21ea 100644
--- a/plugins/Intl/lang/ca.json
+++ b/plugins/Intl/lang/ca.json
@@ -555,8 +555,7 @@
         "NMinutesShort": "%s min",
         "NSeconds": "%s segons",
         "NSecondsShort": "%s s",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0%",
         "NumberSymbolDecimal": ",",
         "NumberSymbolGroup": ".",
diff --git a/plugins/Intl/lang/cs.json b/plugins/Intl/lang/cs.json
index db73f1f539..a033223a23 100644
--- a/plugins/Intl/lang/cs.json
+++ b/plugins/Intl/lang/cs.json
@@ -555,8 +555,7 @@
         "NMinutesShort": "%s min",
         "NSeconds": "%s sekund",
         "NSecondsShort": "%s s",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0 %",
         "NumberSymbolDecimal": ",",
         "NumberSymbolGroup": " ",
diff --git a/plugins/Intl/lang/cy.json b/plugins/Intl/lang/cy.json
index f06ab8923a..decf4b5bf0 100644
--- a/plugins/Intl/lang/cy.json
+++ b/plugins/Intl/lang/cy.json
@@ -549,8 +549,7 @@
         "NMinutesShort": "%s mun",
         "NSeconds": "%s eiliad",
         "NSecondsShort": "%s eil",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0%",
         "NumberSymbolDecimal": ".",
         "NumberSymbolGroup": ",",
diff --git a/plugins/Intl/lang/da.json b/plugins/Intl/lang/da.json
index 38e0271cca..cf46661588 100644
--- a/plugins/Intl/lang/da.json
+++ b/plugins/Intl/lang/da.json
@@ -555,8 +555,7 @@
         "NMinutesShort": "%s min.",
         "NSeconds": "%s sekunder",
         "NSecondsShort": "%s s",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0 %",
         "NumberSymbolDecimal": ",",
         "NumberSymbolGroup": ".",
diff --git a/plugins/Intl/lang/de.json b/plugins/Intl/lang/de.json
index b77dd668ed..b2ebb8f027 100644
--- a/plugins/Intl/lang/de.json
+++ b/plugins/Intl/lang/de.json
@@ -555,8 +555,7 @@
         "NMinutesShort": "%s Min.",
         "NSeconds": "%s Sekunden",
         "NSecondsShort": "%s s",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0 %",
         "NumberSymbolDecimal": ",",
         "NumberSymbolGroup": ".",
diff --git a/plugins/Intl/lang/el.json b/plugins/Intl/lang/el.json
index e83407ad6c..7ec469b2ec 100644
--- a/plugins/Intl/lang/el.json
+++ b/plugins/Intl/lang/el.json
@@ -555,8 +555,7 @@
         "NMinutesShort": "%s λεπ.",
         "NSeconds": "%s δευτερόλεπτα",
         "NSecondsShort": "%s δ",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0%",
         "NumberSymbolDecimal": ",",
         "NumberSymbolGroup": ".",
diff --git a/plugins/Intl/lang/en.json b/plugins/Intl/lang/en.json
index 9847168eea..5703605403 100644
--- a/plugins/Intl/lang/en.json
+++ b/plugins/Intl/lang/en.json
@@ -555,8 +555,7 @@
         "NMinutesShort": "%s min",
         "NSeconds": "%s seconds",
         "NSecondsShort": "%ss",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0%",
         "NumberSymbolDecimal": ".",
         "NumberSymbolGroup": ",",
diff --git a/plugins/Intl/lang/es.json b/plugins/Intl/lang/es.json
index 8f8c5dbb64..dd795468a0 100644
--- a/plugins/Intl/lang/es.json
+++ b/plugins/Intl/lang/es.json
@@ -555,8 +555,7 @@
         "NMinutesShort": "%s min",
         "NSeconds": "%s segundos",
         "NSecondsShort": "%ss",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0 %",
         "NumberSymbolDecimal": ",",
         "NumberSymbolGroup": ".",
diff --git a/plugins/Intl/lang/et.json b/plugins/Intl/lang/et.json
index 0898d97706..2455275a6c 100644
--- a/plugins/Intl/lang/et.json
+++ b/plugins/Intl/lang/et.json
@@ -555,8 +555,7 @@
         "NMinutesShort": "%s min",
         "NSeconds": "%s sekundit",
         "NSecondsShort": "%s s",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0%",
         "NumberSymbolDecimal": ",",
         "NumberSymbolGroup": " ",
diff --git a/plugins/Intl/lang/eu.json b/plugins/Intl/lang/eu.json
index 9129f21c20..c544e2ad4e 100644
--- a/plugins/Intl/lang/eu.json
+++ b/plugins/Intl/lang/eu.json
@@ -525,8 +525,7 @@
         "NMinutesShort": "%s min",
         "NSeconds": "%s segundo",
         "NSecondsShort": "%s s",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "% #,##0",
         "NumberSymbolDecimal": ",",
         "NumberSymbolGroup": ".",
diff --git a/plugins/Intl/lang/fa.json b/plugins/Intl/lang/fa.json
index 0267f1cbee..11132366e8 100644
--- a/plugins/Intl/lang/fa.json
+++ b/plugins/Intl/lang/fa.json
@@ -555,8 +555,7 @@
         "NMinutesShort": "%s دقیقه",
         "NSeconds": "%s ثانیه",
         "NSecondsShort": "%s Ø«",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0%",
         "NumberSymbolDecimal": "Ù«",
         "NumberSymbolGroup": "Ù¬",
diff --git a/plugins/Intl/lang/fi.json b/plugins/Intl/lang/fi.json
index 5777563f9c..92dde341a1 100644
--- a/plugins/Intl/lang/fi.json
+++ b/plugins/Intl/lang/fi.json
@@ -555,8 +555,7 @@
         "NMinutesShort": "%s min",
         "NSeconds": "%s sekuntia",
         "NSecondsShort": "%ss",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0 %",
         "NumberSymbolDecimal": ",",
         "NumberSymbolGroup": " ",
diff --git a/plugins/Intl/lang/fr.json b/plugins/Intl/lang/fr.json
index c96ac9964e..fd86bb49e4 100644
--- a/plugins/Intl/lang/fr.json
+++ b/plugins/Intl/lang/fr.json
@@ -555,8 +555,7 @@
         "NMinutesShort": "%s min",
         "NSeconds": "%s secondes",
         "NSecondsShort": "%ss",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0 %",
         "NumberSymbolDecimal": ",",
         "NumberSymbolGroup": " ",
diff --git a/plugins/Intl/lang/gl.json b/plugins/Intl/lang/gl.json
index 53af791d84..d2559979c1 100644
--- a/plugins/Intl/lang/gl.json
+++ b/plugins/Intl/lang/gl.json
@@ -523,8 +523,7 @@
         "NMinutesShort": "%s min",
         "NSeconds": "%s segundos",
         "NSecondsShort": "%s s",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0%",
         "NumberSymbolDecimal": ",",
         "NumberSymbolGroup": ".",
diff --git a/plugins/Intl/lang/he.json b/plugins/Intl/lang/he.json
index ccd7181960..cbd03f933b 100644
--- a/plugins/Intl/lang/he.json
+++ b/plugins/Intl/lang/he.json
@@ -555,8 +555,7 @@
         "NMinutesShort": "%s דק׳",
         "NSeconds": "%s שניות",
         "NSecondsShort": "%s שנ׳",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0%",
         "NumberSymbolDecimal": ".",
         "NumberSymbolGroup": ",",
diff --git a/plugins/Intl/lang/hi.json b/plugins/Intl/lang/hi.json
index e820bc4517..f8b107a293 100644
--- a/plugins/Intl/lang/hi.json
+++ b/plugins/Intl/lang/hi.json
@@ -555,8 +555,7 @@
         "NMinutesShort": "%s मि.",
         "NSeconds": "%s सेकंड",
         "NSecondsShort": "%sसे.",
-        "NumberFormat": "#,##,##0.###",
-        "NumberFormatNegative": "-#,##,##0.###",
+        "NumberFormatNumber": "#,##,##0.###",
         "NumberFormatPercent": "#,##,##0%",
         "NumberSymbolDecimal": ".",
         "NumberSymbolGroup": ",",
diff --git a/plugins/Intl/lang/hr.json b/plugins/Intl/lang/hr.json
index bb1881be4e..631a993b19 100644
--- a/plugins/Intl/lang/hr.json
+++ b/plugins/Intl/lang/hr.json
@@ -555,8 +555,7 @@
         "NMinutesShort": "%s min",
         "NSeconds": "%s sekundi",
         "NSecondsShort": "%s s",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0%",
         "NumberSymbolDecimal": ",",
         "NumberSymbolGroup": ".",
diff --git a/plugins/Intl/lang/hu.json b/plugins/Intl/lang/hu.json
index d3176ed4ee..289f60dfcb 100644
--- a/plugins/Intl/lang/hu.json
+++ b/plugins/Intl/lang/hu.json
@@ -555,8 +555,7 @@
         "NMinutesShort": "%s min",
         "NSeconds": "%s másodperc",
         "NSecondsShort": "%s s",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0%",
         "NumberSymbolDecimal": ",",
         "NumberSymbolGroup": " ",
diff --git a/plugins/Intl/lang/id.json b/plugins/Intl/lang/id.json
index caec4e10b8..702377c9c7 100644
--- a/plugins/Intl/lang/id.json
+++ b/plugins/Intl/lang/id.json
@@ -555,8 +555,7 @@
         "NMinutesShort": "%s mnt",
         "NSeconds": "%s detik",
         "NSecondsShort": "%s dtk",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0%",
         "NumberSymbolDecimal": ",",
         "NumberSymbolGroup": ".",
diff --git a/plugins/Intl/lang/is.json b/plugins/Intl/lang/is.json
index 716de6a460..179a3a5ad7 100644
--- a/plugins/Intl/lang/is.json
+++ b/plugins/Intl/lang/is.json
@@ -553,8 +553,7 @@
         "NMinutesShort": "%s mín.",
         "NSeconds": "%s sekúndur",
         "NSecondsShort": "%s sek.",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0%",
         "NumberSymbolDecimal": ",",
         "NumberSymbolGroup": ".",
diff --git a/plugins/Intl/lang/it.json b/plugins/Intl/lang/it.json
index 2c57a591b8..d4106a67e4 100644
--- a/plugins/Intl/lang/it.json
+++ b/plugins/Intl/lang/it.json
@@ -555,8 +555,7 @@
         "NMinutesShort": "%s min",
         "NSeconds": "%s secondi",
         "NSecondsShort": "%ss",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0%",
         "NumberSymbolDecimal": ",",
         "NumberSymbolGroup": ".",
diff --git a/plugins/Intl/lang/ja.json b/plugins/Intl/lang/ja.json
index 96c3981f50..1237b0837b 100644
--- a/plugins/Intl/lang/ja.json
+++ b/plugins/Intl/lang/ja.json
@@ -555,8 +555,7 @@
         "NMinutesShort": "%s 分",
         "NSeconds": "%s ç§’",
         "NSecondsShort": "%sç§’",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0%",
         "NumberSymbolDecimal": ".",
         "NumberSymbolGroup": ",",
diff --git a/plugins/Intl/lang/ka.json b/plugins/Intl/lang/ka.json
index d719ed4b69..2bcae0c62c 100644
--- a/plugins/Intl/lang/ka.json
+++ b/plugins/Intl/lang/ka.json
@@ -536,8 +536,7 @@
         "NMinutesShort": "%s წთ",
         "NSeconds": "%s წამი",
         "NSecondsShort": "%sწმ",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0 %",
         "NumberSymbolDecimal": ",",
         "NumberSymbolGroup": " ",
diff --git a/plugins/Intl/lang/ko.json b/plugins/Intl/lang/ko.json
index 7b2845c0d4..e42483c59f 100644
--- a/plugins/Intl/lang/ko.json
+++ b/plugins/Intl/lang/ko.json
@@ -555,8 +555,7 @@
         "NMinutesShort": "%së¶„",
         "NSeconds": "%sì´ˆ",
         "NSecondsShort": "%sì´ˆ",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0%",
         "NumberSymbolDecimal": ".",
         "NumberSymbolGroup": ",",
diff --git a/plugins/Intl/lang/lt.json b/plugins/Intl/lang/lt.json
index bcef2fe9d8..d49c6ad54e 100644
--- a/plugins/Intl/lang/lt.json
+++ b/plugins/Intl/lang/lt.json
@@ -555,8 +555,7 @@
         "NMinutesShort": "%s min.",
         "NSeconds": "%s sekundžių",
         "NSecondsShort": "%s s",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0 %",
         "NumberSymbolDecimal": ",",
         "NumberSymbolGroup": " ",
diff --git a/plugins/Intl/lang/lv.json b/plugins/Intl/lang/lv.json
index 939de3e332..e503026355 100644
--- a/plugins/Intl/lang/lv.json
+++ b/plugins/Intl/lang/lv.json
@@ -555,8 +555,7 @@
         "NMinutesShort": "%s min.",
         "NSeconds": "%s sekundes",
         "NSecondsShort": "%ss",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0%",
         "NumberSymbolDecimal": ",",
         "NumberSymbolGroup": " ",
diff --git a/plugins/Intl/lang/nb.json b/plugins/Intl/lang/nb.json
index 4ef7090326..47699e558a 100644
--- a/plugins/Intl/lang/nb.json
+++ b/plugins/Intl/lang/nb.json
@@ -555,8 +555,7 @@
         "NMinutesShort": "%s min",
         "NSeconds": "%s sekunder",
         "NSecondsShort": "%ss",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0 %",
         "NumberSymbolDecimal": ",",
         "NumberSymbolGroup": " ",
diff --git a/plugins/Intl/lang/nl.json b/plugins/Intl/lang/nl.json
index 78df9a1aeb..8ea4f8f24d 100644
--- a/plugins/Intl/lang/nl.json
+++ b/plugins/Intl/lang/nl.json
@@ -555,8 +555,7 @@
         "NMinutesShort": "%s min",
         "NSeconds": "%s seconden",
         "NSecondsShort": "%s s",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0%",
         "NumberSymbolDecimal": ",",
         "NumberSymbolGroup": ".",
diff --git a/plugins/Intl/lang/nn.json b/plugins/Intl/lang/nn.json
index 243b16bddb..2bbaa39b18 100644
--- a/plugins/Intl/lang/nn.json
+++ b/plugins/Intl/lang/nn.json
@@ -551,8 +551,7 @@
         "NMinutesShort": "%s min",
         "NSeconds": "%s s",
         "NSecondsShort": "%s s",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0 %",
         "NumberSymbolDecimal": ",",
         "NumberSymbolGroup": " ",
diff --git a/plugins/Intl/lang/pl.json b/plugins/Intl/lang/pl.json
index a4dc8c2777..779af3f6b2 100644
--- a/plugins/Intl/lang/pl.json
+++ b/plugins/Intl/lang/pl.json
@@ -555,8 +555,7 @@
         "NMinutesShort": "%s min",
         "NSeconds": "%s sekundy",
         "NSecondsShort": "%s s",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0%",
         "NumberSymbolDecimal": ",",
         "NumberSymbolGroup": " ",
diff --git a/plugins/Intl/lang/pt-br.json b/plugins/Intl/lang/pt-br.json
index 53e2a69cff..2fb5c928d6 100644
--- a/plugins/Intl/lang/pt-br.json
+++ b/plugins/Intl/lang/pt-br.json
@@ -555,8 +555,7 @@
         "NMinutesShort": "%s min",
         "NSeconds": "%s segundos",
         "NSecondsShort": "%s s",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0%",
         "NumberSymbolDecimal": ",",
         "NumberSymbolGroup": ".",
diff --git a/plugins/Intl/lang/pt.json b/plugins/Intl/lang/pt.json
index efb4666688..5391e15487 100644
--- a/plugins/Intl/lang/pt.json
+++ b/plugins/Intl/lang/pt.json
@@ -555,8 +555,7 @@
         "NMinutesShort": "%s min",
         "NSeconds": "%s segundos",
         "NSecondsShort": "%s s",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0%",
         "NumberSymbolDecimal": ",",
         "NumberSymbolGroup": " ",
diff --git a/plugins/Intl/lang/ro.json b/plugins/Intl/lang/ro.json
index 74f4db292a..90d7a0bf0d 100644
--- a/plugins/Intl/lang/ro.json
+++ b/plugins/Intl/lang/ro.json
@@ -555,8 +555,7 @@
         "NMinutesShort": "%s min.",
         "NSeconds": "%s de secunde",
         "NSecondsShort": "%s s",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0 %",
         "NumberSymbolDecimal": ",",
         "NumberSymbolGroup": ".",
diff --git a/plugins/Intl/lang/ru.json b/plugins/Intl/lang/ru.json
index 2c3cc02555..e4f78b4513 100644
--- a/plugins/Intl/lang/ru.json
+++ b/plugins/Intl/lang/ru.json
@@ -555,8 +555,7 @@
         "NMinutesShort": "%s мин",
         "NSeconds": "%s секунды",
         "NSecondsShort": "%s с",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0 %",
         "NumberSymbolDecimal": ",",
         "NumberSymbolGroup": " ",
diff --git a/plugins/Intl/lang/sk.json b/plugins/Intl/lang/sk.json
index 0b18395e65..2dd65c7397 100644
--- a/plugins/Intl/lang/sk.json
+++ b/plugins/Intl/lang/sk.json
@@ -555,8 +555,7 @@
         "NMinutesShort": "%s min",
         "NSeconds": "%s sekúnd",
         "NSecondsShort": "%s s",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0 %",
         "NumberSymbolDecimal": ",",
         "NumberSymbolGroup": " ",
diff --git a/plugins/Intl/lang/sl.json b/plugins/Intl/lang/sl.json
index 8eb7e00cfe..748bbc3592 100644
--- a/plugins/Intl/lang/sl.json
+++ b/plugins/Intl/lang/sl.json
@@ -553,8 +553,7 @@
         "NMinutesShort": "%s min",
         "NSeconds": "%s sekund",
         "NSecondsShort": "%s s",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0%",
         "NumberSymbolDecimal": ",",
         "NumberSymbolGroup": ".",
diff --git a/plugins/Intl/lang/sq.json b/plugins/Intl/lang/sq.json
index 22d4471d39..b54d001958 100644
--- a/plugins/Intl/lang/sq.json
+++ b/plugins/Intl/lang/sq.json
@@ -507,8 +507,7 @@
         "NMinutesShort": "%s min.",
         "NSeconds": "%s sekonda",
         "NSecondsShort": "%s sek.",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0%",
         "NumberSymbolDecimal": ",",
         "NumberSymbolGroup": " ",
diff --git a/plugins/Intl/lang/sr.json b/plugins/Intl/lang/sr.json
index b5c090b680..8d9ef65100 100644
--- a/plugins/Intl/lang/sr.json
+++ b/plugins/Intl/lang/sr.json
@@ -555,8 +555,7 @@
         "NMinutesShort": "%s мин",
         "NSeconds": "%s секунди",
         "NSecondsShort": "%s сек",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0%",
         "NumberSymbolDecimal": ",",
         "NumberSymbolGroup": ".",
diff --git a/plugins/Intl/lang/sv.json b/plugins/Intl/lang/sv.json
index 5188d9eb88..c92a3e1ebf 100644
--- a/plugins/Intl/lang/sv.json
+++ b/plugins/Intl/lang/sv.json
@@ -555,8 +555,7 @@
         "NMinutesShort": "%s min",
         "NSeconds": "%s sekunder",
         "NSecondsShort": "%ss",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0 %",
         "NumberSymbolDecimal": ",",
         "NumberSymbolGroup": " ",
diff --git a/plugins/Intl/lang/ta.json b/plugins/Intl/lang/ta.json
index 8b5a6cb4f5..477950426b 100644
--- a/plugins/Intl/lang/ta.json
+++ b/plugins/Intl/lang/ta.json
@@ -555,8 +555,7 @@
         "NMinutesShort": "%s நிமிட",
         "NSeconds": "%s விநாடிகள்",
         "NSecondsShort": "%s வி.",
-        "NumberFormat": "#,##,##0.###",
-        "NumberFormatNegative": "-#,##,##0.###",
+        "NumberFormatNumber": "#,##,##0.###",
         "NumberFormatPercent": "#,##,##0%",
         "NumberSymbolDecimal": ".",
         "NumberSymbolGroup": ",",
diff --git a/plugins/Intl/lang/te.json b/plugins/Intl/lang/te.json
index d7d87bba08..fc54933b61 100644
--- a/plugins/Intl/lang/te.json
+++ b/plugins/Intl/lang/te.json
@@ -555,8 +555,7 @@
         "NMinutesShort": "%s నిమి.",
         "NSeconds": "%s సెకన్లు",
         "NSecondsShort": "%sసె",
-        "NumberFormat": "#,##,##0.###",
-        "NumberFormatNegative": "-#,##,##0.###",
+        "NumberFormatNumber": "#,##,##0.###",
         "NumberFormatPercent": "#,##0%",
         "NumberSymbolDecimal": ".",
         "NumberSymbolGroup": ",",
diff --git a/plugins/Intl/lang/th.json b/plugins/Intl/lang/th.json
index 68ff72125a..0f827fac72 100644
--- a/plugins/Intl/lang/th.json
+++ b/plugins/Intl/lang/th.json
@@ -555,8 +555,7 @@
         "NMinutesShort": "%s นาที",
         "NSeconds": "%s วินาที",
         "NSecondsShort": "%sวิ",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0%",
         "NumberSymbolDecimal": ".",
         "NumberSymbolGroup": ",",
diff --git a/plugins/Intl/lang/tl.json b/plugins/Intl/lang/tl.json
index 467e9e36e6..71abdf6151 100644
--- a/plugins/Intl/lang/tl.json
+++ b/plugins/Intl/lang/tl.json
@@ -525,8 +525,7 @@
         "NMinutesShort": "%s min.",
         "NSeconds": "%s na segundo",
         "NSecondsShort": "%ss",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0%",
         "NumberSymbolDecimal": ".",
         "NumberSymbolGroup": ",",
diff --git a/plugins/Intl/lang/tr.json b/plugins/Intl/lang/tr.json
index 8540c88797..7a0ae90c1c 100644
--- a/plugins/Intl/lang/tr.json
+++ b/plugins/Intl/lang/tr.json
@@ -555,8 +555,7 @@
         "NMinutesShort": "%s dk.",
         "NSeconds": "%s saniye",
         "NSecondsShort": "%ssn",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "%#,##0",
         "NumberSymbolDecimal": ",",
         "NumberSymbolGroup": ".",
diff --git a/plugins/Intl/lang/uk.json b/plugins/Intl/lang/uk.json
index a0b5df3c27..cdc38219de 100644
--- a/plugins/Intl/lang/uk.json
+++ b/plugins/Intl/lang/uk.json
@@ -555,8 +555,7 @@
         "NMinutesShort": "%s хв",
         "NSeconds": "%s секунди",
         "NSecondsShort": "%s с",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0%",
         "NumberSymbolDecimal": ",",
         "NumberSymbolGroup": " ",
diff --git a/plugins/Intl/lang/vi.json b/plugins/Intl/lang/vi.json
index 2510231ab3..cfaa336635 100644
--- a/plugins/Intl/lang/vi.json
+++ b/plugins/Intl/lang/vi.json
@@ -555,8 +555,7 @@
         "NMinutesShort": "%s phút",
         "NSeconds": "%s giây",
         "NSecondsShort": "%s giây",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0%",
         "NumberSymbolDecimal": ",",
         "NumberSymbolGroup": ".",
diff --git a/plugins/Intl/lang/zh-cn.json b/plugins/Intl/lang/zh-cn.json
index 414f9c0776..be28705106 100644
--- a/plugins/Intl/lang/zh-cn.json
+++ b/plugins/Intl/lang/zh-cn.json
@@ -555,8 +555,7 @@
         "NMinutesShort": "%s分钟",
         "NSeconds": "%sç§’é’Ÿ",
         "NSecondsShort": "%sç§’",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0%",
         "NumberSymbolDecimal": ".",
         "NumberSymbolGroup": ",",
diff --git a/plugins/Intl/lang/zh-tw.json b/plugins/Intl/lang/zh-tw.json
index 3ac8261ab0..7084fe5d59 100644
--- a/plugins/Intl/lang/zh-tw.json
+++ b/plugins/Intl/lang/zh-tw.json
@@ -555,8 +555,7 @@
         "NMinutesShort": "%s 分鐘",
         "NSeconds": "%s ç§’",
         "NSecondsShort": "%sç§’",
-        "NumberFormat": "#,##0.###",
-        "NumberFormatNegative": "-#,##0.###",
+        "NumberFormatNumber": "#,##0.###",
         "NumberFormatPercent": "#,##0%",
         "NumberSymbolDecimal": ".",
         "NumberSymbolGroup": ",",
diff --git a/plugins/Morpheus/templates/_jsGlobalVariables.twig b/plugins/Morpheus/templates/_jsGlobalVariables.twig
index ed38f98e67..9602890c16 100644
--- a/plugins/Morpheus/templates/_jsGlobalVariables.twig
+++ b/plugins/Morpheus/templates/_jsGlobalVariables.twig
@@ -5,8 +5,7 @@
     piwik.cacheBuster = "{{ cacheBuster }}";
 
     piwik.numbers = {
-        patternPositive: "{{ 'Intl_NumberFormat'|translate }}",
-        patternNegative: "{{ 'Intl_NumberFormatNegative'|translate }}",
+        patternNumber: "{{ 'Intl_NumberFormatNumber'|translate }}",
         patternPercent: "{{ 'Intl_NumberFormatPercent'|translate }}",
         symbolPlus: "{{ 'Intl_NumberSymbolPlus'|translate }}",
         symbolMinus: "{{ 'Intl_NumberSymbolMinus'|translate }}",
diff --git a/plugins/MultiSites/tests/Integration/DashboardTest.php b/plugins/MultiSites/tests/Integration/DashboardTest.php
index ca59b119d5..7c79ce93e9 100644
--- a/plugins/MultiSites/tests/Integration/DashboardTest.php
+++ b/plugins/MultiSites/tests/Integration/DashboardTest.php
@@ -13,6 +13,7 @@ use Piwik\Period;
 use Piwik\Plugins\MultiSites\Dashboard;
 use Piwik\Tests\Framework\Fixture;
 use Piwik\Tests\Framework\TestCase\IntegrationTestCase;
+use Piwik\Translate;
 
 /**
  * @group MultiSites
@@ -37,6 +38,8 @@ class DashboardTest extends IntegrationTestCase
             Fixture::createWebsite('2012-12-12 00:00:00', $ecommerce = 0, 'Site ' . $i);
         }
 
+        Translate::loadAllTranslations();
+
         $this->dashboard = $this->getMockBuilder('Piwik\Plugins\MultiSites\Dashboard')
                                 ->setMethods(null)
                                 ->disableOriginalConstructor()
diff --git a/tests/PHPUnit/Unit/Metrics/FormatterTest.php b/tests/PHPUnit/Unit/Metrics/FormatterTest.php
index f0f1e618a9..e0ecfacccd 100644
--- a/tests/PHPUnit/Unit/Metrics/FormatterTest.php
+++ b/tests/PHPUnit/Unit/Metrics/FormatterTest.php
@@ -7,7 +7,7 @@
  */
 namespace Piwik\Tests\Unit\Metrics;
 
-use Piwik\Intl\Locale;
+use Piwik\Container\StaticContainer;
 use Piwik\Metrics\Formatter;
 use Piwik\Translate;
 use Piwik\Plugins\SitesManager\API as SitesManagerAPI;
@@ -57,6 +57,7 @@ class FormatterTest extends \PHPUnit_Framework_TestCase
 
     public function tearDown()
     {
+        StaticContainer::get('Piwik\NumberFormatter')->unsetInstance();
         Translate::reset();
         $this->unsetSiteManagerApiMock();
     }
@@ -74,13 +75,8 @@ class FormatterTest extends \PHPUnit_Framework_TestCase
      */
     public function test_getPrettyNumber_ReturnsCorrectResult_WhenLocaleIsEuropean($number, $expected)
     {
-        $locale = setlocale(LC_ALL, array('de-AT', 'de_DE', 'de', 'ge', 'de_DE.utf8'));
-        if (empty($locale)) {
-            $this->markTestSkipped("de_DE locale is not present on this system");
-        }
-
+        StaticContainer::get('Piwik\Translation\Translator')->setCurrentLanguage('de');
         $this->assertEquals($expected, $this->formatter->getPrettyNumber($number, 2));
-        Locale::setDefaultLocale();
     }
 
     /**
@@ -137,12 +133,11 @@ class FormatterTest extends \PHPUnit_Framework_TestCase
     public function getPrettyNumberLocaleTestData()
     {
         return array(
-            array(0.14, '0,14'),
-            array(0.14567, '0,15'),
-            array(100.1234, '100,12'),
-            // Those last two are commented because locales are platform dependent, on some platforms the separator is '' instead of '.'
-//            array(1000.45, '1.000,45'),
-//            array(23456789.00, '23.456.789,00'),
+            array(0.14, '0.14'),
+            array(0.14567, '0.15'),
+            array(100.1234, '100.12'),
+            array(1000.45, '1,000.45'),
+            array(23456789.00, '23,456,789.00'),
         );
     }
 
-- 
GitLab