我想使用Twig模板系统来模拟我的电子邮件。电子邮件的区域设置应基于用户设置,而不是基于会话或请求区域设置。如何在渲染Twig模板时强制语言环境?
手册确实提到了to force the locale for the Translator。但我想将此语言环境传递给render()方法,以便在此区域设置中呈现树枝模板内的翻译。
这与在模板中使用到不同,因为我认为这会强制在特定区域设置中模板内的翻译。
所以,以Symfony为例,我正在寻找类似的东西:
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),
'nl_NL' // <-- This would be nice!
)
)
;
$this->get('mailer')->send($message);
return $this->render(...);
}
答案 0 :(得分:34)
使用trans过滤器时,可以将语言环境作为参数传递(参见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'
答案 1 :(得分:17)
获取转换程序组件并在呈现模板之前更改其区域设置。这个解决方案不需要将额外的值传递给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('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(...);
}
用户邮件的常用方法是将用户的区域设置存储在用户实体中,并将其直接传递给翻译器,例如在此代码段中:
$translator->setLocale($recipientUser->getLocale());
答案 2 :(得分:2)
这是一个解决方案(它运行良好,除了子模板(Twig:render(控制器('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) {
}
}
}
示例:
if ($this->getLocale()) {
$this->localeSwitcher->setLocale($this->getLocale());
}
$html = $this->templating->render($templatePath);
if ($this->getLocale()) {
$this->localeSwitcher->revertLocale();
}
答案 3 :(得分:-1)
你可以这样做:将参数(例如语言环境)发送到模板
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(...);
}