16

To format a date in twig you usually use something like:

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

Now, I have to localize this date (US m/d/y, NL d/m/y). What would be the best practice to do this in the twig? I do use Symfony 2, a workaround would be to do the translation in the controller but i would like to do this in the twig.

3

3 Answers 3

40

What about the Intl Twig extension?

Usage in a twig template:

{{ my_date | localizeddate('full', 'none', locale) }}
Sign up to request clarification or add additional context in comments.

5 Comments

Great suggestion. Just don't forget to register the Intl extension, as explained here: nerdpress.org/2011/10/19/… (that page explains installing the Debug extension, but installing the Intl happens analogous)
This should be the accepted answer. See my answer on another question for more information on how to use the Intl extension.
There is a big problem, in twig documentation about this filter, there is no any mention about how to install it!
This answer tells how to install it with composer
Useful, but seems not to be a robust solution as one should change all |date filters in twig files
7

I didn't want to install a whole extensions just for this stuff and need to do a few things automatically: It's also possible to write a helperclass (or expand an existing helper) in Bundle/Twig/Extensions for example like this:

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);
}

twig-Template:

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

The result is "12. February 2014" (or "12. Februar 2014" in de_DE and so on)

2 Comments

I was really looking for something app-wide not just Twig and this helped, thanks!
You're welcome! Thank you for your positive feedback :)
0

I really only wanted the day & month names to be translated according to the locale and wrote this twig extension. It accepts the normal DateTime->format() parameters and converts day & months names using strftime() if needed.

<?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;
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.