【问题标题】:How to translate emails when sending them asynchronously with Symfony Messenger?使用 Symfony Messenger 异步发送电子邮件时如何翻译电子邮件?
【发布时间】:2020-10-15 01:08:51
【问题描述】:

我将 Symfony 邮件程序配置为使用信使发送电子邮件。

https://symfony.com/doc/current/mailer.html#sending-messages-async

我有两种语言的电子邮件,我依靠请求来检测语言,但现在电子邮件没有翻译。

如何将消息翻译成请求中检测到的语言?

在我的控制器中:

$mailer->send(
            $user->email,
            $this->translator->trans('mails.recover.subject'),
            'email/client/password-recovery.html.twig',
            compact('user', 'hash', 'target')
        );

模板:

{% extends 'email/base.html.twig' %}

{% block content %}
    <h2>{{ 'mails.recover.header' | trans({'%name%': user.name}) }}</h2>

    <p style="margin: 25px 0;">
        {{ 'mails.recover.text1' | trans({'%url%': url('default')}) | raw }}
    </p>

// More code

Messenger 配置:

framework:
    messenger:
        # Uncomment this (and the failed transport below) to send failed messages to this transport for later handling.
        # failure_transport: failed

        transports:
            # https://symfony.com/doc/current/messenger.html#transport-configuration
            async: '%env(MESSENGER_TRANSPORT_DSN)%'
            # failed: 'doctrine://default?queue_name=failed'
            # sync: 'sync://'

        routing:
            # Route your messages to the transports
            # 'App\Message\YourMessage': async
            'Symfony\Component\Mailer\Messenger\SendEmailMessage':  async

如果翻译正确,邮件的主题看起来更好,但邮件的正文却没有

如果我删除该行

'Symfony\Component\Mailer\Messenger\SendEmailMessage':  async

在 messegner 配置中,翻译工作。

【问题讨论】:

  • 似乎消息是首先生成的,异步部分只通过 SMTP 发送已经“渲染”的内容,所以它应该像直接发送邮件一样工作。你怎么翻译?你在使用翻译组件吗?
  • 是的,我的模板如下所示:{{ 'mails.base.about.header'|trans }}
  • 您能显示更多代码吗?特别是 php 中的部分是你发送的消息
  • @Jakumi 我已经更新了问题。
  • 我有点迷茫,通常 MailerInterface::send() 最多接收 2 个参数(RawMessage 和 Envelope)。显然你使用了一些帮助类或其他东西。而且我假设帮助程序类生成一个 TemplatedEmail 或其他东西,并且异步服务使用“新鲜”树枝来实际呈现电子邮件正文,因此只有默认语言。尝试使用$this-&gt;renderView(template, context)(控制器默认功能)渲染主体

标签: php symfony symfony-mailer


【解决方案1】:

您遇到的问题是 Symfony Translator 组件从传入的 request 获取用户的语言环境,并且在实际发送邮件时异步发送邮件时,请求早已完成并且消失了,然后是消息消费者的上下文(命令行)并且没有请求区域设置信息。

对此有两种解决方案:

第一个选项:您将已经翻译的值传递给模板(这就是您对电子邮件主题所做的事情)。

例如像这样:

$mailer->send(
        $user->email,
        $this->translator->trans('mails.recover.subject'),
        'email/client/password-recovery.html.twig',
            [
                'user' => $user,
                'hash' => $hash,
                'target' => $target,
                'labels' => [
                  'header' => $this->translator
                                   ->trans('mails.recover.subject', [ 'name' => $user->getName()]),
                  'text1'  => $this->translator
                                    ->trans('mails.recover.text1', ['url', => $defaulUrl])
            ]
);

然后在您的模板中直接使用这些值:

{% extends 'email/base.html.twig' %}

{% block content %}
    <h2>{{ texts.header }}</h2>
    <p style="margin: 25px 0;">{{ texts.text1 }}</p>
{% endblock %}

这将是我的首选方法,因为它使模板尽可能地笨拙并且易于在不同的上下文中重用。模板本身不需要知道与其内容的实际呈现无关的任何事情。

第二个选项:让模板系统知道你想翻译成什么样的用户区域:

$mailer->send(
        $user->email,
        $this->translator->trans('mails.recover.subject'),
        'email/client/password-recovery.html.twig',
            [
                'user'   => $user,
                'hash'   => $hash,
                'target' => $target,
                'requestLocale' =>  $locale
                // get the locale from the request
                // (https://symfony.com/doc/current/translation/locale.html)
            ]
);

然后您在正在使用的过滤器中使用接收到的语言环境,如here 所述:

<h2>{{ 'mails.recover.header' | trans({'%name%': user.name}, 'app', requestLocale) }}</h2>

虽然我更喜欢第一个,但使用任何一个选项都可以让您获得想要的结果。

【讨论】:

【解决方案2】:

虽然这里的所有这些答案都很有趣,但它们都不适合我,并且包含需要将语言环境等“额外”变量传递到上下文中。

在我的例子中,使用最新的 Symfony 这足以在电子邮件模板中设置:

{% trans_default_domain 'emails' %}

简单的调用:

{{ 'emails.whatevermessage'|trans|raw }}

像魅力一样工作。

【讨论】:

    【解决方案3】:

    只要电子邮件内容不需要翻译,“第二个选项:让模板系统知道您要翻译到的用户语言环境:”是最佳解决方案。

    如果您有包含大量文本的复杂电子邮件,更好的方法是使用多个模板并让应用程序设置区域设置来决定必须使用哪个电子邮件模板。

    或在模板电子邮件中。

    {% if language is defined %}
        {# Language still specified #}    
    {% else %}
        {% set language = 'ne' %}
    {% endif %}
    
    {% if language == "en" %}
        <h1>Ticket for - <code>{{ activity.name }}</code> by participant <code>{{ buyer.name }}</code> </h1>
    {% else %}
        <h1>Kaartje voor - <code>{{ activity.name }}</code> door deelnemer <code>{{ buyer.name }}</code> </h1>
    {% endif %}
    

    【讨论】:

      【解决方案4】:

      我的解决方案也适用于树枝中的url_absolute

      $message = (new TemplatedEmail())
      ...
      
      $renderer = new BodyRenderer($this->twig);
      $renderer->render($message);
      $this->mailer->send(new RawMessage($message->toString()),Envelope::create($message));
      

      使用Environment $twigMailerInterface $mailer

      【讨论】:

        猜你喜欢
        • 2019-02-05
        • 1970-01-01
        • 2022-01-21
        • 1970-01-01
        • 1970-01-01
        • 2011-05-25
        • 2012-12-05
        • 2015-04-16
        • 2017-11-26
        相关资源
        最近更新 更多