在 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 扩展(或使用提供它的库)
我在 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 扩展(或使用提供它的库)