32

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

マニュアルには、 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(...);
}
4

4 に答える 4

42

trans フィルターを使用する場合、引数としてロケールを渡すことができます (差分を参照してください: 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'
于 2013-03-14T15:30:33.287 に答える
21

テンプレートをレンダリングする前に、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('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(...);
}

ユーザー メールの一般的な方法は、ユーザーのロケールを User エンティティに格納し、それを翻訳者に直接渡すことです。たとえば、次のコード スニペットのようになります。

$translator->setLocale($recipientUser->getLocale());
于 2015-05-26T09:14:17.093 に答える
2

これが解決策です(サブテンプレートを除いてうまく機能します(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();
}
于 2016-09-16T10:05:11.210 に答える
-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(...);
}
于 2013-03-07T11:04:54.810 に答える