Forcing the Twig Locale

二次信任 提交于 2020-08-21 05:00:13

问题


I would like to use the Twig template system to template my e-mails. The locale of the e-mail should be based on a user setting, not from the session or request locale. How can I force the locale when rendering a Twig template?

The manual does mention how to force the locale for the Translator. But i'd like pass this locale to the render() method, in order to have the translations inside the twig template to be rendered in this locale.

This is different from using into in the template, because I think this forces a translation inside the template in a specific locale.

So, taking the example from Symfony, I'm looking for something like this:

public function indexAction($name)
{
    $message = \Swift_Message::newInstance()
        ->setSubject('Hello Email')
        ->setFrom('send@example.com')
        ->setTo('recipient@example.com')
        ->setBody(
            $this->renderView(
                'HelloBundle:Hello:email.txt.twig',
                array('name' => $name),
                'nl_NL' // <-- This would be nice!
            )
        )
    ;
    $this->get('mailer')->send($message);

    return $this->render(...);
}

回答1:


You can pass the locale through as an argument when you use the trans filter (see diff: https://github.com/symfony/symfony/commit/3ea31a02630412b1c732ee1647a0724378f67665).

So you could pass another user_locale variable in your render method in your controller (or pass through the whole user object instead of passing name and user_locale separately, or use app.user in your template if the user will be logged in, etc... (depending on your application obviously)), then in your email template you can have something like this:

{{ 'greeting' | trans({}, "messages", user_locale) }} {{ name | title }}
{# rest of email template with more translation strings #}

Then in your translation file for that locale (assuming you're using yaml) just have something like this and the translations will work nicely for you on the fly:

# messages.fr.yml    
greeting: 'Bonjour'



回答2:


Get a hold of the Translator component and change its locale before rendering the template. This solution does not require passing an extra value to the parameters' array of the render() method and painfully refactoring all your Twig files.

public function indexAction($name)
{
    $translator = $this->get('translator');

    // Save the current session locale
    // before overwriting it. Suppose its 'en_US'
    $sessionLocale = $translator->getLocale();

    $translator->setLocale('nl_NL');

    $message = \Swift_Message::newInstance()
        ->setSubject('Hello Email')
        ->setFrom('send@example.com')
        ->setTo('recipient@example.com')
        ->setBody(
            $this->renderView(
                'HelloBundle:Hello:email.txt.twig',
                array('name' => $name)
            )
        )
    ;

    $this->get('mailer')->send($message);

    // Otherwise subsequent templates would also
    // be rendered in Dutch instead of English
    $translator->setLocale($sessionLocale);

    return $this->render(...);
}

A common approach to user mailing is storing the user's locale in the User entity and passing it directly to the translator, such as in this code snippet:

$translator->setLocale($recipientUser->getLocale());



回答3:


Here is a solution (it works well, except sub-templates (Twig: render(controller('AppBundle:Invoice/Index:productTotalPartial')))

<?php

namespace Main\BoBundle\Service;

use Symfony\Component\Translation\TranslatorInterface;

/**
 * Class LocaleSwitcher
 *
 * @package Main\BoBundle\Service
 */
class LocaleSwitcher
{
    /**
     * @var TranslatorInterface
     */
    private $translator;

    /**
     * @var string
     */
    private $previousLocale;

    /**
     * @param TranslatorInterface $translator
     */
    public function __construct(TranslatorInterface $translator)
    {
        $this->translator = $translator;
    }

    /**
     * Change the locale
     *
     * @param string $locale
     */
    public function setLocale($locale)
    {
        $this->previousLocale = $this->translator->getLocale();

        $this->translator->setLocale($locale);
        $this->setPhpDefaultLocale($locale);
    }

    /**
     * Revert the locale
     */
    public function revertLocale()
    {
        if ($this->previousLocale === null) {
            return;
        }

        $this->translator->setLocale($this->previousLocale);
        $this->setPhpDefaultLocale($this->previousLocale);

        $this->previousLocale = null;
    }

    /**
     * Use temporary locale in closure function
     *
     * @param string $locale
     * @param \Closure $c
     */
    public function temporaryLocale($locale, \Closure $c)
    {
        $this->setLocale($locale);

        $c();

        $this->revertLocale();
    }

    /**
     * Sets the default PHP locale.
     * Copied from Symfony/Component/HttpFoundation/Request.php
     *
     * @param string $locale
     */
    private function setPhpDefaultLocale($locale)
    {
        // if either the class Locale doesn't exist, or an exception is thrown when
        // setting the default locale, the intl module is not installed, and
        // the call can be ignored:
        try {
            if (class_exists('Locale', false)) {
                /** @noinspection PhpUndefinedClassInspection */
                \Locale::setDefault($locale);
            }
        } catch (\Exception $e) {
        }
    }
}

Example:

if ($this->getLocale()) {
    $this->localeSwitcher->setLocale($this->getLocale());
}

$html = $this->templating->render($templatePath);

if ($this->getLocale()) {
    $this->localeSwitcher->revertLocale();
}



回答4:


u can do this: send a paramater (e.g. locale) to template

public function indexAction($name)
{
    $message = \Swift_Message::newInstance()
        ->setSubject('Hello Email')
        ->setFrom('send@example.com')
        ->setTo('recipient@example.com')
        ->setBody(
            $this->renderView(
                'HelloBundle:Hello:email.txt.twig',
                array('name' => $name, 'locale' => 'nl_NL'),
            )
        )
    ;
    $this->get('mailer')->send($message);

    return $this->render(...);
}


来源:https://stackoverflow.com/questions/15266673/forcing-the-twig-locale

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!