在 Symfony 4 中翻译带有参数的 flash 消息

Translation of flash messages with parameters in Symfony 4

我在 Symfony 4 和翻译中遇到了闪现消息的问题。 简单的即时消息翻译工作正常:

$this->addFlash('success', 'flashmessage.project_deleted');

但是现在我想在闪信中添加一些参数,但我不知道如何处理。我尝试了很多,但没有任何效果。我想在 flash 消息中显示 f.e 之后的项目标题。删除。例如:

$this->addFlash('success', sprintf('flashmessage.project_deleted: %s', $project->getTitle()));

但翻译不被识别,因为参数在翻译发生之前被替换(我认为是这样)。并且还应该可以在字符串中间有参数,而不仅仅是在末尾或开头,理想情况下不止一个参数。

我在扩展 AbstractController 的控制器中使用它。

有人对此有解决方案吗?

查看 ICU 消息格式:https://symfony.com/doc/current/translation/message_format.html

通常你会将参数传递给翻译,所以你的代码片段可能应该看起来像你的第一个例子,然后在 twig 中你会有这样的东西:

{% for message in app.flashes('success') %}
    <div class="alert alert-success">
       {{ message|trans({ 'title': project.title }) }}
    </div>
{% endfor %}

翻译应该包含被替换的参数:

flashmessage:
     project_created: 'The project "%title%" was created successfully.'
     project_deleted: 'You successfully deleted the project "%title%".'
     ...

显然缺点是您必须动态传递变量,这对 flash 消息没有多大意义,因为并非所有消息都需要这些参数。此外,正如您已经提到的,当您删除该项目时,您可能无法再在模板中使用它。

相反,我建议在将消息传递到 flash 包之前对其进行翻译:

$this->addFlash(
    'success',
    $this->translator->translate(
        'flashmessage.project_deleted',
        [
            'title' => $project->getTitle(),
        ]
    )
);

这将要求您将翻译器传递给您的控制器。您可以为此创建类似于 Symfony 的 AbstractController 的自己的基本控制器,并创建类似于 $this->trans() 方法的东西,以便更轻松地在控制器内翻译内容。此外,您仍然必须确保 $project->getTitle() 仍然 return 一个值,因此您可能希望在实际删除条目或将数据存入内存之前调用它。

当你这样做时,你不应该翻译模板本身的 flash 消息,因为它们已经被翻译了。这仍然有效,因为当 Symfony 尝试翻译已经翻译的消息时,例如You successfully deleted the project "foo". 然后它不会找到翻译并只打印原始文本,但您会在日志中收到有关缺少翻译的警告。解决方案是删除模板中的 |trans(请参阅第一个片段)。

一个可能的解决方案是添加另一个带有序列化参数的闪存。

然后,当您显示您的 flash 消息时,检查该额外的 flash 是否存在,如果存在,反序列化它并将其用作参数。 示例如下。

在控制器中:

$this->addFlash('success', 'flashmessage.project_deleted');
$this->addFlash('_params', serialize(['%project%' => $project->getTitle()]));

在模板中:

{% flashMessage = app.session.flashbag.get('info') %}
{% if app.session.flashbag.has('_params') %}
    {% set flashParams = app.session.flashbag.get('_params')|first|unserialize %}
    {{ flashMessage|trans(flashParams) }}
{% else %}
    {{ flashMessage|trans }}
{% endif %}

您需要创建一个定义 unserialize 过滤器的 Twig 扩展(或使用提供它的库)