Forcing the Twig Locale

后端 未结 4 2005
一向
一向 2021-02-03 21:31

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

相关标签:
4条回答
  • 2021-02-03 21:39

    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'
    
    0 讨论(0)
  • 2021-02-03 21:42

    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());
    
    0 讨论(0)
  • 2021-02-03 21:53

    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();
    }
    
    0 讨论(0)
  • 2021-02-03 22:04

    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(...);
    }
    
    0 讨论(0)
提交回复
热议问题