From 448a30939673cb9c219e3eb2cdfc2f044b185274 Mon Sep 17 00:00:00 2001 From: Bertrand Zuchuat Date: Tue, 1 May 2012 00:18:52 +0200 Subject: [PATCH 1/4] Added new filters localizednumber and localizedcurrency on Intl extension --- lib/Twig/Extensions/Extension/Intl.php | 52 +++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/lib/Twig/Extensions/Extension/Intl.php b/lib/Twig/Extensions/Extension/Intl.php index 8014a545..2b58aea8 100644 --- a/lib/Twig/Extensions/Extension/Intl.php +++ b/lib/Twig/Extensions/Extension/Intl.php @@ -13,7 +13,7 @@ class Twig_Extensions_Extension_Intl extends Twig_Extension { public function __construct() { - if (!class_exists('IntlDateFormatter')) { + if (!class_exists('IntlDateFormatter') || !class_exists('NumberFormatter')) { throw new RuntimeException('The intl extension is needed to use intl-based filters.'); } } @@ -27,6 +27,8 @@ public function getFilters() { return array( new Twig_SimpleFilter('localizeddate', 'twig_localized_date_filter', array('needs_environment' => true)), + new Twig_SimpleFilter('localizednumber', 'twig_localized_number_filter'), + new Twig_SimpleFilter('localizedcurrency', 'twig_localized_currency_filter'), ); } @@ -64,3 +66,51 @@ function twig_localized_date_filter(Twig_Environment $env, $date, $dateFormat = return $formatter->format($date->getTimestamp()); } + +function twig_localized_number_filter($number, $style = 'decimal', $format = 'default', $currency = null, $locale = null ) +{ + $formatter = getNumberFormatter( + $locale !== null ? $locale : Locale::getDefault(), + $style + ); + + $formatValues = array( + 'default' => NumberFormatter::TYPE_DEFAULT, + 'int32' => NumberFormatter::TYPE_INT32, + 'int64' => NumberFormatter::TYPE_INT64, + 'double' => NumberFormatter::TYPE_DOUBLE, + 'currency' => NumberFormatter::TYPE_CURRENCY, + ); + + return $formatter->format( + $number, + $formatValues[$format]); +} + +function twig_localized_currency_filter($number, $currency = null, $locale = null) +{ + $formatter = getNumberFormatter( + $locale !== null ? $locale : Locale::getDefault(), + 'currency' + ); + + return $formatter->formatCurrency($number, $currency); +} + +function getNumberFormatter($locale, $style) +{ + $styleValues = array( + 'decimal' => NumberFormatter::DECIMAL, + 'currency' => NumberFormatter::CURRENCY, + 'percent' => NumberFormatter::PERCENT, + 'scientific' => NumberFormatter::SCIENTIFIC, + 'spellout' => NumberFormatter::SPELLOUT, + 'ordinal' => NumberFormatter::ORDINAL, + 'duration' => NumberFormatter::DURATION, + ); + + return NumberFormatter::create( + $locale !== null ? $locale : Locale::getDefault(), + $styleValues[$style] + ); +} From 380f7f00aa192af4b28ec599c8c1b4d71ca8828a Mon Sep 17 00:00:00 2001 From: Bertrand Zuchuat Date: Tue, 1 May 2012 10:23:34 +0200 Subject: [PATCH 2/4] Rename getNumberFormatter to twig_get_number_formatter --- lib/Twig/Extensions/Extension/Intl.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/Twig/Extensions/Extension/Intl.php b/lib/Twig/Extensions/Extension/Intl.php index 2b58aea8..b540a106 100644 --- a/lib/Twig/Extensions/Extension/Intl.php +++ b/lib/Twig/Extensions/Extension/Intl.php @@ -69,7 +69,7 @@ function twig_localized_date_filter(Twig_Environment $env, $date, $dateFormat = function twig_localized_number_filter($number, $style = 'decimal', $format = 'default', $currency = null, $locale = null ) { - $formatter = getNumberFormatter( + $formatter = twig_get_number_formatter( $locale !== null ? $locale : Locale::getDefault(), $style ); @@ -89,7 +89,7 @@ function twig_localized_number_filter($number, $style = 'decimal', $format = 'de function twig_localized_currency_filter($number, $currency = null, $locale = null) { - $formatter = getNumberFormatter( + $formatter = twig_get_number_formatter( $locale !== null ? $locale : Locale::getDefault(), 'currency' ); @@ -97,7 +97,7 @@ function twig_localized_currency_filter($number, $currency = null, $locale = nul return $formatter->formatCurrency($number, $currency); } -function getNumberFormatter($locale, $style) +function twig_get_number_formatter($locale, $style) { $styleValues = array( 'decimal' => NumberFormatter::DECIMAL, From f6c41309571507d9b79f8371e0f10201242e0dfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michae=CC=88l=20Perrin?= Date: Fri, 25 Jul 2014 10:09:01 +0200 Subject: [PATCH 3/4] Add checks on "localizednumber" and "localizedcurrency" filters and small tweaks --- lib/Twig/Extensions/Extension/Intl.php | 59 +++++++++++++++++--------- 1 file changed, 39 insertions(+), 20 deletions(-) diff --git a/lib/Twig/Extensions/Extension/Intl.php b/lib/Twig/Extensions/Extension/Intl.php index b540a106..c41499af 100644 --- a/lib/Twig/Extensions/Extension/Intl.php +++ b/lib/Twig/Extensions/Extension/Intl.php @@ -13,7 +13,7 @@ class Twig_Extensions_Extension_Intl extends Twig_Extension { public function __construct() { - if (!class_exists('IntlDateFormatter') || !class_exists('NumberFormatter')) { + if (!class_exists('IntlDateFormatter')) { throw new RuntimeException('The intl extension is needed to use intl-based filters.'); } } @@ -67,14 +67,9 @@ function twig_localized_date_filter(Twig_Environment $env, $date, $dateFormat = return $formatter->format($date->getTimestamp()); } -function twig_localized_number_filter($number, $style = 'decimal', $format = 'default', $currency = null, $locale = null ) +function twig_localized_number_filter($number, $style = 'decimal', $type = 'default', $locale = null) { - $formatter = twig_get_number_formatter( - $locale !== null ? $locale : Locale::getDefault(), - $style - ); - - $formatValues = array( + static $typeValues = array( 'default' => NumberFormatter::TYPE_DEFAULT, 'int32' => NumberFormatter::TYPE_INT32, 'int64' => NumberFormatter::TYPE_INT64, @@ -82,24 +77,43 @@ function twig_localized_number_filter($number, $style = 'decimal', $format = 'de 'currency' => NumberFormatter::TYPE_CURRENCY, ); - return $formatter->format( - $number, - $formatValues[$format]); + $formatter = twig_get_number_formatter($locale, $style); + + if (!isset($typeValues[$type])) { + throw new Twig_Error_Syntax(sprintf('The type "%s" does not exist. Known types are: "%s"', $type, implode('", "', array_keys($typeValues)))); + } + + return $formatter->format($number, $typeValues[$type]); } function twig_localized_currency_filter($number, $currency = null, $locale = null) { - $formatter = twig_get_number_formatter( - $locale !== null ? $locale : Locale::getDefault(), - 'currency' - ); + $formatter = twig_get_number_formatter($locale, 'currency'); return $formatter->formatCurrency($number, $currency); } +/** + * Gets a number formatter instance according to given locale and formatter + * + * @param string $locale Locale in which the number would be formatted + * @param int $style Style of the formatting + * + * @return NumberFormatter A NumberFormatter instance + */ function twig_get_number_formatter($locale, $style) { - $styleValues = array( + static $formatter, $currentStyle; + + $locale = $locale !== null ? $locale : Locale::getDefault(); + + if ($formatter && $formatter->getLocale() === $locale && $currentStyle === $style) { + // Return same instance of NumberFormatter if parameters are the same + // to those in previous call + return $formatter; + } + + static $styleValues = array( 'decimal' => NumberFormatter::DECIMAL, 'currency' => NumberFormatter::CURRENCY, 'percent' => NumberFormatter::PERCENT, @@ -109,8 +123,13 @@ function twig_get_number_formatter($locale, $style) 'duration' => NumberFormatter::DURATION, ); - return NumberFormatter::create( - $locale !== null ? $locale : Locale::getDefault(), - $styleValues[$style] - ); + if (!isset($styleValues[$style])) { + throw new Twig_Error_Syntax(sprintf('The style "%s" does not exist. Known styles are: "%s"', $style, implode('", "', array_keys($styleValues)))); + } + + $currentStyle = $style; + + $formatter = NumberFormatter::create($locale, $styleValues[$style]); + + return $formatter; } From 76f532d12a551c1c16d51230178445c1e89950eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michae=CC=88l=20Perrin?= Date: Fri, 25 Jul 2014 14:16:53 +0200 Subject: [PATCH 4/4] Add documentation for localizednumber and localizedcurrency filters --- doc/intl.rst | 95 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 85 insertions(+), 10 deletions(-) diff --git a/doc/intl.rst b/doc/intl.rst index e5fae12d..ad03b881 100644 --- a/doc/intl.rst +++ b/doc/intl.rst @@ -50,13 +50,88 @@ Arguments * ``format``: Optional pattern to use when formatting or parsing. Possible patterns are documented in the `ICU user guide`_. -.. _`strtotime`: http://php.net/strtotime -.. _`DateTime`: http://php.net/DateTime -.. _`Unix timestamps`: http://en.wikipedia.org/wiki/Unix_time -.. _`IntlDateFormatter::create()`: http://php.net/manual/en/intldateformatter.create.php -.. _`IntlDateFormatter::NONE`: http://php.net/manual/en/class.intldateformatter.php#intldateformatter.constants.none -.. _`IntlDateFormatter::SHORT`: http://php.net/manual/en/class.intldateformatter.php#intldateformatter.constants.short -.. _`IntlDateFormatter::MEDIUM`: http://php.net/manual/en/class.intldateformatter.php#intldateformatter.constants.medium -.. _`IntlDateFormatter::LONG`: http://php.net/manual/en/class.intldateformatter.php#intldateformatter.constants.long -.. _`IntlDateFormatter::FULL`: http://php.net/manual/en/class.intldateformatter.php#intldateformatter.constants.full -.. _`ICU user guide`: http://userguide.icu-project.org/formatparse/datetime +``localizednumber`` +------------------- + +Use the ``localizednumber`` filter to format numbers into a localized string +representating the number. + +.. code-block:: jinja + + {{ product.quantity|localizednumber }} + +.. note:: + + Internally, Twig uses the PHP `NumberFormatter::create()`_ function for + the number. + +Arguments +~~~~~~~~~ + +* ``style``: Optional date format (default: 'decimal'). Choose one of these formats: + + * 'decimal': `NumberFormatter::DECIMAL`_ + * 'currency': `NumberFormatter::CURRENCY`_ + * 'percent': `NumberFormatter::PERCENT`_ + * 'scientific': `NumberFormatter::SCIENTIFIC`_ + * 'spellout': `NumberFormatter::SPELLOUT`_ + * 'ordinal': `NumberFormatter::ORDINAL`_ + * 'duration': `NumberFormatter::DURATION`_ + +* ``type``: Optional formatting type to use (default: 'default'). Choose one of these types: + + * 'default': `NumberFormatter::TYPE_DEFAULT`_ + * 'int32': `NumberFormatter::TYPE_INT32`_ + * 'int64': `NumberFormatter::TYPE_INT64`_ + * 'double': `NumberFormatter::TYPE_DOUBLE`_ + * 'currency': `NumberFormatter::TYPE_CURRENCY`_ + +* ``locale``: The locale used for the format. If ``NULL`` is given, Twig will + use ``Locale::getDefault()`` + +``localizedcurrency`` +--------------------- + +Use the ``localizedcurrency`` filter to format a currency value into a localized string. + +.. code-block:: jinja + + {{ product.price|localizedcurrency('EUR') }} + +.. note:: + + Internally, Twig uses the PHP `NumberFormatter::create()`_ function for + the number. + +Arguments +~~~~~~~~~ + +* ``currency``: The 3-letter ISO 4217 currency code indicating the currency to use. + +* ``locale``: The locale used for the format. If ``NULL`` is given, Twig will + use ``Locale::getDefault()`` + + +.. _`strtotime`: http://php.net/strtotime +.. _`DateTime`: http://php.net/DateTime +.. _`Unix timestamps`: http://en.wikipedia.org/wiki/Unix_time +.. _`IntlDateFormatter::create()`: http://php.net/manual/en/intldateformatter.create.php +.. _`IntlDateFormatter::NONE`: http://php.net/manual/en/class.intldateformatter.php#intldateformatter.constants.none +.. _`IntlDateFormatter::SHORT`: http://php.net/manual/en/class.intldateformatter.php#intldateformatter.constants.short +.. _`IntlDateFormatter::MEDIUM`: http://php.net/manual/en/class.intldateformatter.php#intldateformatter.constants.medium +.. _`IntlDateFormatter::LONG`: http://php.net/manual/en/class.intldateformatter.php#intldateformatter.constants.long +.. _`IntlDateFormatter::FULL`: http://php.net/manual/en/class.intldateformatter.php#intldateformatter.constants.full +.. _`ICU user guide`: http://userguide.icu-project.org/formatparse/datetime +.. _`NumberFormatter::create()`: http://php.net/manual/en/numberformatter.create.php +.. _`NumberFormatter::DECIMAL`: http://php.net/manual/en/class.numberformatter.php#numberformatter.constants.decimal +.. _`NumberFormatter::CURRENCY`: http://php.net/manual/en/class.numberformatter.php#numberformatter.constants.currency +.. _`NumberFormatter::PERCENT`: http://php.net/manual/en/class.numberformatter.php#numberformatter.constants.percent +.. _`NumberFormatter::SCIENTIFIC`: http://php.net/manual/en/class.numberformatter.php#numberformatter.constants.scientific +.. _`NumberFormatter::SPELLOUT`: http://php.net/manual/en/class.numberformatter.php#numberformatter.constants.spellout +.. _`NumberFormatter::ORDINAL`: http://php.net/manual/en/class.numberformatter.php#numberformatter.constants.ordinal +.. _`NumberFormatter::DURATION`: http://php.net/manual/en/class.numberformatter.php#numberformatter.constants.duration +.. _`NumberFormatter::TYPE_DEFAULT`: http://php.net/manual/en/class.numberformatter.php#numberformatter.constants.type-default +.. _`NumberFormatter::TYPE_INT32`: http://php.net/manual/en/class.numberformatter.php#numberformatter.constants.type-int32 +.. _`NumberFormatter::TYPE_INT64`: http://php.net/manual/en/class.numberformatter.php#numberformatter.constants.type-int64 +.. _`NumberFormatter::TYPE_DOUBLE`: http://php.net/manual/en/class.numberformatter.php#numberformatter.constants.type-double +.. _`NumberFormatter::TYPE_CURRENCY`: http://php.net/manual/en/class.numberformatter.php#numberformatter.constants.type-currency