Принуждение языка Twig
Я хотел бы использовать шаблонную систему Twig для создания шаблонов моих электронных писем. Языковой стандарт электронной почты должен основываться на пользовательской настройке, а не на локали сеанса или запроса. Как я могу заставить локаль при рендеринге шаблона Twig?
В руководстве упоминается, как принудительно установить языковой стандарт для переводчика. Но я бы хотел передать этот язык в метод 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(...);
}
Ответы
Ответ 1
Вы можете передать локаль через аргумент, когда используете транс-фильтр (см. diff: https://github.com/symfony/symfony/commit/3ea31a02630412b1c732ee1647a0724378f67665).
Таким образом, вы можете передать другую переменную user_locale в свой метод визуализации в своем контроллере (или пройти через весь пользовательский объект вместо передачи имени и 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'
Ответ 2
Захватите компонент 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(...);
}
Обычный подход к почтовой рассылке пользователей - это сохранение пользовательской локали в объекте User и передача его непосредственно переводчику, например, в этом фрагменте кода:
$translator->setLocale($recipientUser->getLocale());
Ответ 3
u может сделать это: отправить paramater (например, locale) в шаблон
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(...);
}
Ответ 4
Вот решение (оно работает хорошо, кроме подшаблонов (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) {
}
}
}
Пример:
if ($this->getLocale()) {
$this->localeSwitcher->setLocale($this->getLocale());
}
$html = $this->templating->render($templatePath);
if ($this->getLocale()) {
$this->localeSwitcher->revertLocale();
}