2013-03-07 36 views
25

我想使用樹枝模板系統爲我的電子郵件創建模板。電子郵件的區域設置應該基於用戶設置,而不是來自會話或請求區域設置。渲染枝條模板時如何強制區域設置?強制樹枝區域設置

該手冊確實提到了如何to force the locale for the Translator。但是我想將這個語言環境傳遞給render()方法,以便在該語言環境中呈現樹枝模板內部的翻譯。

這與在模板中將轉換爲不同,因爲我認爲這會強制在特定區域設置的模板內進行翻譯。

因此,採取從Symfony的例子,我在尋找這樣的事情:

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

回答

27

你可以在使用反式過濾器時將區域設置作爲參數傳遞(請參閱diff:https://github.com/symfony/symfony/commit/3ea31a02630412b1c732ee1647a0724378f67665)。

所以你可以在你的控制器的render方法中傳遞另一個user_locale變量(或者通過整個用戶對象而不是單獨傳遞name和user_locale,或者在你的模板中使用app.user,如果用戶登錄,等等...(取決於您的應用程序很明顯)),然後在你的郵件模板,你可以有這樣的事情:

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

然後在該區域設置你的翻譯文件(假設你使用YAML)只是有像這樣的東西和翻譯將很好地爲你工作:

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

U可以做到這一點:發送paramater(如語言環境)到模板

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

是的,但我不認爲模板會自動爲{%trans%}塊使用此區域設置,是不是? – rolandow 2013-03-08 12:52:35

+4

不,你可以強制轉換過濾器使用語言環境,你想'{{「Hello」| trans({},「messages」,locale)}}',翻譯器組件自動使用請求中定義的語言環境,if你想改變它'$ this-> get('translator') - > setLocale($ locale);' – 2013-03-25 09:47:27

12

在呈現模板之前獲取轉換器組件並更改其區域設置。這個解決方案不需要需要傳遞一個額外的值給參數的render()方法的數組,並痛苦地重構所有的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]ple.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(...); 
} 

到用戶的郵件的常用方法是存儲用戶的語言環境中的用戶實體,並直接傳遞給翻譯,如在此代碼段:

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

包含的子模板不受影響 – 2015-11-03 06:11:33

0

這裏是一個溶液(它運作良好,除了子模板(嫩枝:渲染(控制器( '的appbundle:發票/索引: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) { 
     } 
    } 
} 

實施例:

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

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

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