2013-03-07 13 views
25

Twigテンプレートシステムを使用して電子メールのテンプレートを作成したいと考えています。電子メールのロケールは、セッションまたは要求ロケールからではなく、ユーザー設定に基づいている必要があります。 Twigテンプレートをレンダリングするとき、どのようにロケールを強制できますか?Twigロケールを強制する

マニュアルにはどのように言及していますか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

あなたをテンプレートにのparamater(例えばロケール)を送りますトランスフィルタを使用するときに引数としてロケールを渡すことができます(diff:https://github.com/symfony/symfony/commit/3ea31a02630412b1c732ee1647a0724378f67665参照)。

コントローラ内のレンダリングメソッドに別の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はこれを行うことができます:

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

+4

いいえ、トランスフィルターは、 '{{" Hello "| trans({}、" messages "、locale}}}'を使用するロケールを強制的に使用できますが、トランスレータコンポーネントはリクエストで定義されたロケールを自動的に使用します$ this-> get( 'translator') - > setLocale($ locale); ' –

12

Translatorコンポーネントを保持し、テンプレートをレンダリングする前にロケールを変更します。この解決策はではありません。では、パラメータの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]') 
     ->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

includeサブテンプレートは影響を受けません –

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(); 
} 
関連する問題