2013-03-07 14 views
25

Chciałbym użyć systemu szablonów Twig do szablonu moich wiadomości e-mail. Ustawienia regionalne wiadomości e-mail powinny opierać się na ustawieniach użytkownika, a nie na ustawieniach regionalnych lub sesji. Jak mogę wymusić ustawienia regionalne podczas renderowania szablonu Twig?Wymuszenie lokalizacji gałązki

Instrukcja wspomina, jak to force the locale for the Translator. Ale chciałbym przekazać te ustawienia narodowe do metody render(), aby tłumaczenia w szablonie gałązki były renderowane w tym języku.

To różni się od użycia w w szablonie, ponieważ myślę, że to wymusza tłumaczenie wewnątrz szablonu w określonych ustawieniach narodowych.

Więc, biorąc przykład z Symfony, szukam czegoś takiego:

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

Odpowiedz

27

You może przekazać locale jako argument podczas korzystania z filtra trans (zobacz diff: https://github.com/symfony/symfony/commit/3ea31a02630412b1c732ee1647a0724378f67665).

Tak więc możesz przekazać inną zmienną user_locale w swojej metodzie renderowania w kontrolerze (lub przejść przez cały obiekt użytkownika zamiast przekazywania nazwy i user_locale osobno, lub użyć app.user w swoim szablonie, jeśli użytkownik będzie zalogowany, etc ... (w zależności od aplikacji oczywiście)), a następnie w szablonie e-mail może mieć coś takiego:

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

następnie w pliku tłumaczenia dla tej lokalizacji (zakładając że używasz YAML) po prostu coś takiego, a tłumaczenia będą dobrze działać w Twoim przypadku:

# messages.fr.yml  
greeting: 'Bonjour' 
0

u może to zrobić: wyślij paramater (np lokalizacji) do szablonu

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(...); 
} 
+1

Tak, ale nie sądzę, że szablon automatycznie użyje tego ustawienia narodowego dla bloków {% trans%}, prawda? – rolandow

+4

nie, możesz zmusić filtr trans do używania ustawień narodowych, które chcesz '{{" Hello "| trans ({}," messages ", locale)}}}, komponent translatora użyje ustawień narodowych zdefiniowanych w żądaniu automatycznie, jeśli chcesz to zmienić '$ this-> get ('translator') -> setLocale ($ locale);' –

12

Zatrzymaj komponent Tłumacz i zmień jego ustawienia regionalne przed renderowaniem szablonu. To rozwiązanie wymaga, aby , a nie, przekazywać dodatkową wartość do tablicy parametrów metody render() i boleśnie refaktoryzować wszystkie pliki 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(...); 
} 

Wspólne podejście do mailingu użytkownika jest przechowywanie ustawień regionalnych użytkownika w jednostce użytkownika i przekazanie go bezpośrednio do tłumacza, tak jak w tym fragmencie kodu:

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

zawarte pod-szablony nie uległy zmianie –

0

Oto rozwiązanie (to sprawdza się, poza podstrumieniem szablonów (gałązka: render (kontroler ('AppBundle: faktura/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) { 
     } 
    } 
} 

przykład:

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

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

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