src/Intl/MessageFormatter/MessageFormatter.php
private static function parseToken(array $token, array $args, $locale)
    {
        if (!isset($args[$param = trim($token[0])])) {
            return '{'.$param.'}';
        }

        $arg = $args[$param];
        $type = isset($token[1]) ? trim($token[1]) : 'none';
        switch ($type) {
            case 'date': //XXX use DateFormatter?
            case 'time':
            case 'spellout':
            case 'ordinal':
            case 'duration':
            case 'choice':
            case 'selectordinal':
                throw new \DomainException(sprintf('The PHP intl extension is required to use the "%s" message format.', $type));

            case 'number':
                $format = isset($token[2]) ? trim($token[2]) : null;
                if (!is_numeric($arg) || (null !== $format && 'integer' !== $format)) {
                    throw new \DomainException('The PHP intl extension is required to use the "number" message format with non-integer values.');
                }

                $number = number_format($arg); //XXX use NumberFormatter?
                if (null === $format && false !== $pos = strpos($arg, '.')) {
                    // add decimals with unknown length
                    $number .= '.'.substr($arg, $pos + 1);
                }

                return $number;

            case 'none':
                return $arg;

            case 'select':
                /* http://icu-project.org/apiref/icu4c/classicu_1_1SelectFormat.html
                selectStyle = (selector '{' message '}')+
                */
                if (!isset($token[2])) {
                    throw new \DomainException('Message pattern is invalid.');
                }
                $select = self::tokenizePattern($token[2]);
                $c = \count($select);
                $message = false;
                for ($i = 0; 1 + $i < $c; ++$i) {
                    if (\is_array($select[$i]) || !\is_array($select[1 + $i])) {
                        throw new \DomainException('Message pattern is invalid.');
                    }
                    $selector = trim($select[$i++]);
                    if (false === $message && 'other' === $selector || $selector == $arg) {
                        $message = implode(',', $select[$i]);
                    }
                }
                if (false !== $message) {
                    return self::parseTokens(self::tokenizePattern($message), $args, $locale);
                }
                break;

            case 'plural': //TODO make it locale-dependent based on symfony/translation rules
                /* http://icu-project.org/apiref/icu4c/classicu_1_1PluralFormat.html
                pluralStyle = [offsetValue] (selector '{' message '}')+
                offsetValue = "offset:" number
                selector = explicitValue | keyword
                explicitValue = '=' number  // adjacent, no white space in between
                keyword = [^[[:Pattern_Syntax:][:Pattern_White_Space:]]]+
                message: see MessageFormat
                */
                if (!isset($token[2])) {
                    throw new \DomainException('Message pattern is invalid.');
                }
                $plural = self::tokenizePattern($token[2]);
                $c = \count($plural);
                $message = false;
                $offset = 0;
                for ($i = 0; 1 + $i < $c; ++$i) {
                    if (\is_array($plural[$i]) || !\is_array($plural[1 + $i])) {
                        throw new \DomainException('Message pattern is invalid.');
                    }
                    $selector = trim($plural[$i++]);

                    if (1 === $i && 0 === strncmp($selector, 'offset:', 7)) {
                        $pos = strpos(str_replace(array("\n", "\r", "\t"), ' ', $selector), ' ', 7);
                        $offset = (int) trim(substr($selector, 7, $pos - 7));
                        $selector = trim(substr($selector, 1 + $pos, \strlen($selector)));
                    }
                    if (false === $message && 'other' === $selector ||
                        '=' === $selector[0] && (int) substr($selector, 1, \strlen($selector)) === $arg ||
                        'one' === $selector && 1 == $arg - $offset
                    ) {
                        $message = implode(',', str_replace('#', $arg - $offset, $plural[$i]));
                    }
                }
                if (false !== $message) {
                    return self::parseTokens(self::tokenizePattern($message), $args, $locale);
                }
                break;
        }

        throw new \DomainException('Message pattern is invalid.');
    }
private static function parseToken(array $token, array $args, $locale)
    {
        if (!isset($args[$param = trim($token[0])])) {
            return '{'.$param.'}';
        }

        $arg = $args[$param];
        $type = isset($token[1]) ? trim($token[1]) : 'none';
        switch ($type) {
            case 'date': //XXX use DateFormatter?
            case 'time':
            case 'spellout':
            case 'ordinal':
            case 'duration':
            case 'choice':
            case 'selectordinal':
                throw new \DomainException(sprintf('The PHP intl extension is required to use the "%s" message format.', $type));

            case 'number':
                $format = isset($token[2]) ? trim($token[2]) : null;
                if (!is_numeric($arg) || (null !== $format && 'integer' !== $format)) {
                    throw new \DomainException('The PHP intl extension is required to use the "number" message format with non-integer values.');
                }

                $number = number_format($arg); //XXX use NumberFormatter?
                if (null === $format && false !== $pos = strpos($arg, '.')) {
                    // add decimals with unknown length
                    $number .= '.'.substr($arg, $pos + 1);
                }

                return $number;

            case 'none':
                return $arg;

            case 'select':
                /* http://icu-project.org/apiref/icu4c/classicu_1_1SelectFormat.html
                selectStyle = (selector '{' message '}')+
                */
                if (!isset($token[2])) {
                    throw new \DomainException('Message pattern is invalid.');
                }
                $select = self::tokenizePattern($token[2]);
                $c = \count($select);
                $message = false;
                for ($i = 0; 1 + $i < $c; ++$i) {
                    if (\is_array($select[$i]) || !\is_array($select[1 + $i])) {
                        throw new \DomainException('Message pattern is invalid.');
                    }
                    $selector = trim($select[$i++]);
                    if (false === $message && 'other' === $selector || $selector == $arg) {
                        $message = implode(',', $select[$i]);
                    }
                }
                if (false !== $message) {
                    return self::parseTokens(self::tokenizePattern($message), $args, $locale);
                }
                break;

            case 'plural': //TODO make it locale-dependent based on symfony/translation rules
                /* http://icu-project.org/apiref/icu4c/classicu_1_1PluralFormat.html
                pluralStyle = [offsetValue] (selector '{' message '}')+
                offsetValue = "offset:" number
                selector = explicitValue | keyword
                explicitValue = '=' number  // adjacent, no white space in between
                keyword = [^[[:Pattern_Syntax:][:Pattern_White_Space:]]]+
                message: see MessageFormat
                */
                if (!isset($token[2])) {
                    throw new \DomainException('Message pattern is invalid.');
                }
                $plural = self::tokenizePattern($token[2]);
                $c = \count($plural);
                $message = false;
                $offset = 0;
                for ($i = 0; 1 + $i < $c; ++$i) {
                    if (\is_array($plural[$i]) || !\is_array($plural[1 + $i])) {
                        throw new \DomainException('Message pattern is invalid.');
                    }
                    $selector = trim($plural[$i++]);

                    if (1 === $i && 0 === strncmp($selector, 'offset:', 7)) {
                        $pos = strpos(str_replace(array("\n", "\r", "\t"), ' ', $selector), ' ', 7);
                        $offset = (int) trim(substr($selector, 7, $pos - 7));
                        $selector = trim(substr($selector, 1 + $pos, \strlen($selector)));
                    }
                    if (false === $message && 'other' === $selector ||
                        '=' === $selector[0] && (int) substr($selector, 1, \strlen($selector)) === $arg ||
                        'one' === $selector && 1 == $arg - $offset
                    ) {
                        $message = implode(',', str_replace('#', $arg - $offset, $plural[$i]));
                    }
                }
                if (false !== $message) {
                    return self::parseTokens(self::tokenizePattern($message), $args, $locale);
                }
                break;
        }

        throw new \DomainException('Message pattern is invalid.');
    }
private static function parseToken ( array $ token , array $ args , $ locale ) { if ( ! isset ( $ args [ $ param = trim ( $ token [ 0 ] ) ] ) ) { return '{' . $ param . '}' ; } $ arg = $ args [ $ param ] ; $ type = isset ( $ token [ 1 ] ) ? trim ( $ token [ 1 ] ) : 'none' ; switch ( $ type ) { case 'date' : //XXX use DateFormatter? case 'time' : case 'spellout' : case 'ordinal' : case 'duration' : case 'choice' : case 'selectordinal' : throw new \ DomainException ( sprintf ( 'The PHP intl extension is required to use the "%s" message format.' , $ type ) ) ; case 'number' : $ format = isset ( $ token [ 2 ] ) ? trim ( $ token [ 2 ] ) : null ; if ( ! is_numeric ( $ arg ) || ( null !== $ format && 'integer' !== $ format ) ) { throw new \ DomainException ( 'The PHP intl extension is required to use the "number" message format with non-integer values.' ) ; } $ number = number_format ( $ arg ) ; //XXX use NumberFormatter? if ( null === $ format && false !== $ pos = strpos ( $ arg , '.' ) ) { // add decimals with unknown length $ number .= '.' . substr ( $ arg , $ pos + 1 ) ; } return $ number ; case 'none' : return $ arg ; case 'select' : /* http://icu-project.org/apiref/icu4c/classicu_1_1SelectFormat.html
                selectStyle = (selector '{' message '}')+
                */ if ( ! isset ( $ token [ 2 ] ) ) { throw new \ DomainException ( 'Message pattern is invalid.' ) ; } $ select = self :: tokenizePattern ( $ token [ 2 ] ) ; $ c = \ count ( $ select ) ; $ message = false ; for ( $ i = 0 ; 1 + $ i < $ c ; ++ $ i ) { if ( \ is_array ( $ select [ $ i ] ) || ! \ is_array ( $ select [ 1 + $ i ] ) ) { throw new \ DomainException ( 'Message pattern is invalid.' ) ; } $ selector = trim ( $ select [ $ i ++ ] ) ; if ( false === $ message && 'other' === $ selector || $ selector == $ arg ) { $ message = implode ( ',' , $ select [ $ i ] ) ; } } if ( false !== $ message ) { return self :: parseTokens ( self :: tokenizePattern ( $ message ) , $ args , $ locale ) ; } break ; case 'plural' : //TODO make it locale-dependent based on symfony/translation rules /* http://icu-project.org/apiref/icu4c/classicu_1_1PluralFormat.html
                pluralStyle = [offsetValue] (selector '{' message '}')+
                offsetValue = "offset:" number
                selector = explicitValue | keyword
                explicitValue = '=' number  // adjacent, no white space in between
                keyword = [^[[:Pattern_Syntax:][:Pattern_White_Space:]]]+
                message: see MessageFormat
                */ if ( ! isset ( $ token [ 2 ] ) ) { throw new \ DomainException ( 'Message pattern is invalid.' ) ; } $ plural = self :: tokenizePattern ( $ token [ 2 ] ) ; $ c = \ count ( $ plural ) ; $ message = false ; $ offset = 0 ; for ( $ i = 0 ; 1 + $ i < $ c ; ++ $ i ) { if ( \ is_array ( $ plural [ $ i ] ) || ! \ is_array ( $ plural [ 1 + $ i ] ) ) { throw new \ DomainException ( 'Message pattern is invalid.' ) ; } $ selector = trim ( $ plural [ $ i ++ ] ) ; if ( 1 === $ i && 0 === strncmp ( $ selector , 'offset:' , 7 ) ) { $ pos = strpos ( str_replace ( array ( "\n" , "\r" , "\t" ) , ' ' , $ selector ) , ' ' , 7 ) ; $ offset = ( int ) trim ( substr ( $ selector , 7 , $ pos - 7 ) ) ; $ selector = trim ( substr ( $ selector , 1 + $ pos , \ strlen ( $ selector ) ) ) ; } if ( false === $ message && 'other' === $ selector || '=' === $ selector [ 0 ] && ( int ) substr ( $ selector , 1 , \ strlen ( $ selector ) ) === $ arg || 'one' === $ selector && 1 == $ arg - $ offset ) { $ message = implode ( ',' , str_replace ( '#' , $ arg - $ offset , $ plural [ $ i ] ) ) ; } } if ( false !== $ message ) { return self :: parseTokens ( self :: tokenizePattern ( $ message ) , $ args , $ locale ) ; } break ; } throw new \ DomainException ( 'Message pattern is invalid.' ) ; }
Parses pattern based on ICU grammar.

@see http://icu-project.org/apiref/icu4c/classMessageFormat.html#details
Parses pattern based on ICU grammar .