对 Michaël Perrin 的回答进行了更改,以便能够通过将 _year 添加到日期格式来使用新旧方式。
使用以下命令创建文件 app/src/Myproject/MyBundle/Twig/Extension/IntlExtension.php:
<?php
namespace Myproject\MyBundle\Twig\Extension;
/**
* Extension of Twig Intl Extension to add support fo showing 4-digit year. Add
* '_year' to the date format for it to work, i.e. short_year instead of short.
*/
class IntlExtension extends \Twig_Extensions_Extension_Intl
{
/**
* A new filter must be added for this extension to work. Since this extension
* extends an existing one, the filter should be loaded after the original one.
*
* @return array
*/
public function getFilters()
{
$filters = [];
// Add all filters but the localizeddate created by the parent.
foreach (parent::getFilters() as $filter) {
if ('localizeddate' !== $filter->getName()) {
$filters[] = $filter;
}
}
// Add custom version of 'localizeddate' which adds support showing 4-digit years.
$filters[] = new \Twig_SimpleFilter('localizeddate', array($this, 'twigLocalizedDateFilter'), array('needs_environment' => true));
return $filters;
}
/**
* If the date format has _year in it, the format returned by Intl, will be
* changed to show a 4-digit year.
*
* @param \Twig_Environment $env
* @param \DateTime $date
* @param string $dateFormat
* @param string $timeFormat
* @param string $locale
* @param string $timezone
* @param string $format
* @return string
*/
public function twigLocalizedDateFilter(\Twig_Environment $env, $date, $dateFormat = 'medium', $timeFormat = 'medium', $locale = null, $timezone = null, $format = null, $calendar = 'gregorian')
{
$date = twig_date_converter($env, $date, $timezone);
$formatValues = array(
'none' => \IntlDateFormatter::NONE,
'short' => \IntlDateFormatter::SHORT,
'medium' => \IntlDateFormatter::MEDIUM,
'long' => \IntlDateFormatter::LONG,
'full' => \IntlDateFormatter::FULL,
);
$formatter = \IntlDateFormatter::create(
$locale,
$formatValues[$this->getDateFormat($dateFormat)],
$formatValues[$timeFormat],
PHP_VERSION_ID >= 50500 ? $date->getTimezone() : $date->getTimezone()->getName(),
'gregorian' === $calendar ? \IntlDateFormatter::GREGORIAN : \IntlDateFormatter::TRADITIONAL,
$format
);
if ($format === null && $this->showFullYear($dateFormat)) {
// Replace yy to y (but yyy should be kept yyy, and yyyy kept as yyyy)
// This way, years are NEVER shown as "yy" (eg. 14), but always like "yyyy" (eg. 2014)
$pattern = preg_replace(':(^|[^y])y{2,2}([^y]|$):', '$1y$2', $formatter->getPattern());
$formatter->setPattern($pattern);
}
return $formatter->format($date->getTimestamp());
}
/**
* If the given date format has _year in it, true is returned, otherwise false.
*
* @param string $dateFormat
* @return boolean
*/
protected function showFullYear($dateFormat)
{
return (strpos($dateFormat, '_year') !== false);
}
/**
* The date format will be returned without the part '_year' if it contains it.
* @param string $dateFormat
* @return string
*/
protected function getDateFormat($dateFormat)
{
return str_replace('_year', '', $dateFormat);
}
}
当然还有 app/config/config.yml 中的添加
services:
myproject.twig.extension.intl:
class: Myproject\MyBundle\Twig\Extension\IntlExtension
tags:
- { name: twig.extension }