Symfony 4中带参数的Flash消息翻译

4

我在Symfony 4中有一个关于flash消息和翻译的问题。 简单的flash消息翻译正常运行:

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

现在我想给Flash消息添加一些参数,但是我不知道如何处理。我尝试了很多次,但都没有成功。我希望在Flash消息中显示项目标题,例如删除后。例如:

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

但是翻译没有被识别,因为参数在翻译之前已经替换了(我想是这样的)。并且字符串中间也应该可以有参数,不仅仅是在开头或结尾,并且最好能够有多个参数。
我正在我的控制器中使用这个,它扩展自AbstractController。
有人有解决办法吗?
4个回答

5
自 Symfony 5.2 开始,您可以使用 TranslatableMessage 对象来实现此功能。

https://symfony.com/doc/current/translation.html#translatable-objects

use Symfony\Component\Translation\TranslatableMessage;


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

然后在您的Twig模板中,您只需要使用{{ flashMessage|trans }}

这可以在不注入Translator服务或在Twig中搞乱任何内容的情况下工作。


3
通常你会将参数传递给翻译函数,在你的代码片段中应该像第一个例子一样,然后在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消息都需要这些参数。此外,正如您已经提到的那样,当您删除项目时,模板中可能不再可用。

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

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

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

如果您以这种方式进行操作,则不应在模板本身中翻译闪存消息,因为它们已经被翻译过了。这仍然有效,因为当Symfony尝试翻译已经翻译过的消息时,例如You successfully deleted the project "foo".,它将找不到翻译并只打印原始文本,但是您将在日志中收到有关缺少翻译的警告。解决方案是从模板中删除|trans(请参见第一个代码片段)。


1
非常感谢您提供这个非常有用的答案! :)
现在它已经起作用了。我的解决方法是将TranslatorInterface添加为函数参数,代码看起来像这样:
$flashmessage = $translator->trans('flashmessage.project_created_successfully', ['title' => $gdprcontent->getTitle()]); $this->addFlash('success', $flashmessage); 翻译文件中的代码如下:
<trans-unit id=".UV8EG1" resname="flashmessage.project_created_successfully"> <source>flashmessage.project_created_successfully</source> <target>项目创建成功:title</target> </trans-unit>
- Ingrid

1

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

然后,在显示闪存消息时,检查是否存在该额外的闪存,如果存在,则对其进行反序列化并将其用作参数。以下是示例。

在控制器中:

$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 %}

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接