2012-02-28 4 views
15

Для форматирования даты в веточке вы обычно используете что-то вроде:Localize даты сучьев с использованием Symfony 2

{{ meeting.date|date("m/d/Y") }} 

Теперь, я должен локализовать эту дату (США м/д/у, NL d/м/у). Какая была бы лучшая практика для этого в ветке? Я использую Symfony 2, обходным решением было бы сделать перевод в контроллере, но я бы хотел сделать это на веточке.

+0

возможно дубликат [Как визуализировать объект DateTime в шаблоне Twig] (http://stackoverflow.com/questions/8318914/how-to-render- a-datetime-object-in-a-twig-template) –

+0

Для этого с sf2 существует комплект: https://github.com/sonata-project/SonataIntlBundle –

+0

@YohanG., Предоставленный комплект не изменяет поведение фильтра '| date'. Он определяет новые фильтры, которые не являются желательным по отношению к вопросу ОП. – Trix

ответ

39

Как насчет the Intl Twig extension?

Использование в шаблоне веточку:

{{ my_date | localizeddate('full', 'none', locale) }} 
+0

Отличное предложение. Просто не забудьте зарегистрировать расширение Intl, как описано здесь: http://nerdpress.org/2011/10/19/symfony-2-twig-enabling-native-twig-extensions/ (на этой странице объясняется установка Debug расширение, но установка Intl аналогична) – Martijn

+2

Это должен быть принятый ответ. См. [Мой ответ на другой вопрос] (http://stackoverflow.com/a/23424315/1001110) для получения дополнительной информации о том, как использовать расширение Intl. –

+1

Существует большая проблема, связанная с документацией об этом фильтре, нет никаких упоминаний о том, как ее установить! – SaidbakR

4

Я не хочу, чтобы установить целые расширения только для этого материала и нужно сделать несколько вещей автоматически: Также можно написать вспомогательный класс (или расширить существующий помощник) в Bundle/Twig/Extensions, например, так:

public function foo(\Datetime $datetime, $lang = 'de_DE', $pattern = 'd. MMMM Y') 
{ 
    $formatter = new \IntlDateFormatter($lang, \IntlDateFormatter::LONG, \IntlDateFormatter::LONG); 
    $formatter->setPattern($pattern); 
    return $formatter->format($datetime); 
} 

веточка-шаблона:

{{ yourDateTimeObject|foo('en_US', 'd. MMMM Y') }} 

Результат: 12. Февраль 2014" (или „12. Februar 2014“ в de_DE и так далее)

+0

Я действительно искал что-то приложение не просто Twig, и это помогло, спасибо! –

+0

Добро пожаловать! Спасибо за ваш положительный отзыв :) – Franziska

0

Я действительно хотел только имена дня & месяца, чтобы быть переведен в соответствии с локалью и написал это расширение ветки. Он принимает нормальные DateTime->format() параметров и преобразует день & месяцев имена, используя strftime() при необходимости.

<?php 

namespace AppBundle\Twig\Extension; 

use Twig_Extension; 
use Twig_SimpleFilter; 
use DateTimeZone; 
use DateTime; 

class LocalizedDateExtension extends Twig_Extension 
{ 
    protected static $conversionMap = [ 
     'D' => 'a', 
     'l' => 'A', 
     'M' => 'b', 
     'F' => 'B', 
    ]; 

    public function getFilters() 
    { 
     return [ 
      new Twig_SimpleFilter('localizeddate', [$this, 'localizeDate']), 
     ]; 
    } 

    protected static function createLocalizableTodo(&$formatString) 
    { 
     $newFormatString = ''; 
     $todo = []; 

     $formatLength = mb_strlen($formatString); 
     for ($i = 0; $i < $formatLength; $i++) { 
      $char = $formatString[$i]; 
      if ('\'' === $char) { 
       $newFormatString = $formatString[++$i]; //advance and add new character 
      } 
      if (array_key_exists($char, static::$conversionMap)) { 
       $newFormatString.= '\!\L\O\C\A\L\I\Z\E\D\\'; //prefix char 
       $todo[$char] = static::$conversionMap[$char]; 
      } 
      $newFormatString.= $char; 
     } 
     $formatString = $newFormatString; 
     return $todo; 
    } 

    public function localizeDate(DateTime $dateTime, $format, $timezone = null, $locale = null) 
    { 
     if (null !== $timezone && $dateTime->getTimezone()->getName() !== $timezone) { 
      $dateTime = clone $dateTime; 
      $dateTime->setTimezone(new DateTimeZone($timezone)); 
     } 

     $todo = static::createLocalizableTodo($format); 
     $output = $dateTime->format($format); 

     //no localizeable parameters? 
     if (0 === count($todo)) { 
      return $output; 
     } 

     if ($locale !== null) { 
      $currentLocale = setlocale(LC_TIME, '0'); 
      setlocale(LC_TIME, $locale); 
     } 
     if ($timezone !== null) { 
      $currentTimezone = date_default_timezone_get(); 
      date_default_timezone_set($timezone); 
     } 

     //replace special parameters 
     foreach ($todo as $placeholder => $parameter) { 
      $output = str_replace('!LOCALIZED'.$placeholder, strftime('%'.$parameter, $dateTime->getTimestamp()), $output); 
     } 
     unset($parameter); 

     if (isset($currentLocale)) { 
      setlocale(LC_TIME, $currentLocale); 
     } 
     if (isset($currentTimezone)) { 
      date_default_timezone_set($currentTimezone); 
     } 

     return $output; 
    } 
}