private function addCurrencySymbol(string $value, ?string $currency = null): string
    {
        $currency = $currency ?? $this->defaultCurrency;
        $locale = \Locale::getDefault();

        if (!isset(self::$patterns[$locale])) {
            self::$patterns[$locale] = [];
        }

        if (!isset(self::$patterns[$locale][$currency])) {
            $formatter = new \NumberFormatter($locale, \NumberFormatter::CURRENCY);
            $pattern = $formatter->formatCurrency(123.00, $currency);

            // 1=left-position currency, 2=left-space, 3=right-space, 4=left-position currency.
            // With non latin number scripts.
            preg_match(
                '/^([^\s\xc2\xa0]*)([\s\xc2\xa0]*)\p{N}{3}(?:[,.]\p{N}+)?([\s\xc2\xa0]*)([^\s\xc2\xa0]*)$/iu',
                $pattern,
                $matches
            );

            if (!empty($matches[1])) {
                self::$patterns[$locale][$currency] = ['%1$s'.$matches[2].'%2$s', $matches[1]];
            } elseif (!empty($matches[4])) {
                self::$patterns[$locale][$currency] = ['%2$s'.$matches[3].'%1$s', $matches[4]];
            } else {
                throw new \InvalidArgumentException(
                    sprintf('Locale "%s" with currency "%s" does not provide a currency position.', $locale, $currency)
                );
            }
        }

        return sprintf(self::$patterns[$locale][$currency][0], self::$patterns[$locale][$currency][1], $value);
    }
private function addCurrencySymbol(string $value, ?string $currency = null): string
    {
        $currency = $currency ?? $this->defaultCurrency;
        $locale = \Locale::getDefault();

        if (!isset(self::$patterns[$locale])) {
            self::$patterns[$locale] = [];
        }

        if (!isset(self::$patterns[$locale][$currency])) {
            $formatter = new \NumberFormatter($locale, \NumberFormatter::CURRENCY);
            $pattern = $formatter->formatCurrency(123.00, $currency);

            // 1=left-position currency, 2=left-space, 3=right-space, 4=left-position currency.
            // With non latin number scripts.
            preg_match(
                '/^([^\s\xc2\xa0]*)([\s\xc2\xa0]*)\p{N}{3}(?:[,.]\p{N}+)?([\s\xc2\xa0]*)([^\s\xc2\xa0]*)$/iu',
                $pattern,
                $matches
            );

            if (!empty($matches[1])) {
                self::$patterns[$locale][$currency] = ['%1$s'.$matches[2].'%2$s', $matches[1]];
            } elseif (!empty($matches[4])) {
                self::$patterns[$locale][$currency] = ['%2$s'.$matches[3].'%1$s', $matches[4]];
            } else {
                throw new \InvalidArgumentException(
                    sprintf('Locale "%s" with currency "%s" does not provide a currency position.', $locale, $currency)
                );
            }
        }

        return sprintf(self::$patterns[$locale][$currency][0], self::$patterns[$locale][$currency][1], $value);
    }
private function addCurrencySymbol ( string $ value , ? string $ currency = null ) : string { $ currency = $ currency ?? $ this -> defaultCurrency ; $ locale = \ Locale :: getDefault ( ) ; if ( ! isset ( self :: $ patterns [ $ locale ] ) ) { self :: $ patterns [ $ locale ] = [ ] ; } if ( ! isset ( self :: $ patterns [ $ locale ] [ $ currency ] ) ) { $ formatter = new \ NumberFormatter ( $ locale , \ NumberFormatter :: CURRENCY ) ; $ pattern = $ formatter -> formatCurrency ( 123.00 , $ currency ) ; // 1=left-position currency, 2=left-space, 3=right-space, 4=left-position currency. // With non latin number scripts. preg_match ( '/^([^\s\xc2\xa0]*)([\s\xc2\xa0]*)\p{N}{3}(?:[,.]\p{N}+)?([\s\xc2\xa0]*)([^\s\xc2\xa0]*)$/iu' , $ pattern , $ matches ) ; if ( ! empty ( $ matches [ 1 ] ) ) { self :: $ patterns [ $ locale ] [ $ currency ] = [ '%1$s' . $ matches [ 2 ] . '%2$s' , $ matches [ 1 ] ] ; } elseif ( ! empty ( $ matches [ 4 ] ) ) { self :: $ patterns [ $ locale ] [ $ currency ] = [ '%2$s' . $ matches [ 3 ] . '%1$s' , $ matches [ 4 ] ] ; } else { throw new \ InvalidArgumentException ( sprintf ( 'Locale "%s" with currency "%s" does not provide a currency position.' , $ locale , $ currency ) ) ; } } return sprintf ( self :: $ patterns [ $ locale ] [ $ currency ] [ 0 ] , self :: $ patterns [ $ locale ] [ $ currency ] [ 1 ] , $ value ) ; }
Adds the currency symbol when missing.

ICU cannot parse() without a currency,
and decimal doesn't include scale when 0.
Adds the currency symbol when missing .