web-dev-qa-db-fra.com

Forcer la locale de brindille

Je voudrais utiliser le système de modèles Twig pour modéliser mes courriels. Les paramètres régionaux du courrier électronique doivent être basés sur un paramètre utilisateur et non sur les paramètres régionaux de la session ou de la demande. Comment puis-je forcer les paramètres régionaux lors du rendu d'un modèle Twig?

Le manuel mentionne comment pour forcer les paramètres régionaux du traducteur . Mais j'aimerais passer cette locale à la méthode render (), afin que les traductions à l'intérieur du modèle de brindille soient rendues dans cette locale.

Cela diffère de l'utilisation de into dans le modèle, car je pense que cela force une traduction à l'intérieur du modèle dans des paramètres régionaux spécifiques.

Donc, prenant l'exemple de Symfony, je cherche quelque chose comme ceci:

public function indexAction($name)
{
    $message = \Swift_Message::newInstance()
        ->setSubject('Hello Email')
        ->setFrom('[email protected]')
        ->setTo('[email protected]')
        ->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(...);
}
28
rolandow

Vous pouvez transmettre les paramètres régionaux en tant qu'argument lorsque vous utilisez le filtre trans (voir diff: https://github.com/symfony/symfony/commit/3ea31a02630412b1c732ee1647a0724378f67665 ).

Ainsi, vous pouvez transmettre une autre variable user_locale dans votre méthode de rendu dans votre contrôleur (ou passer à travers l'objet utilisateur entier au lieu de transmettre name et user_locale séparément, ou utiliser app.user dans votre modèle si l'utilisateur sera connecté, etc. (selon votre application évidemment)), puis dans votre modèle de courrier électronique, vous pouvez avoir quelque chose comme ceci:

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

Ensuite, dans votre fichier de traduction pour cette langue (en supposant que vous utilisez yaml), ayez quelque chose comme cela et les traductions fonctionneront bien pour vous à la volée:

# messages.fr.yml    
greeting: 'Bonjour'
32
Mark

Récupérez le composant Translator et modifiez ses paramètres régionaux avant de rendre le modèle. Cette solution ne not nécessite de passer une valeur supplémentaire au tableau de paramètres de la méthode render () et de refactoriser péniblement tous vos fichiers Twig.

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('[email protected]')
        ->setTo('[email protected]')
        ->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(...);
}

Une approche courante du mailing utilisateur consiste à stocker les paramètres régionaux de l'utilisateur dans l'entité User et à les transmettre directement au traducteur, comme dans l'extrait de code suivant:

$translator->setLocale($recipientUser->getLocale());
15
Marcel Hernandez

Voici une solution (cela fonctionne bien, sauf les sous-modèles (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) {
        }
    }
}

Exemple:

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

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

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

vous pouvez faire ceci: envoyer un paramètre (par exemple locale) au modèle

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

    return $this->render(...);
}
0
Lhassan Baazzi