You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Twig中带键值的翻译直接传递至JavaScript对象?

问题描述

我想通过Twig模板批量传递键值对形式的翻译字符串,不用逐个手动赋值。我的翻译文件存在translations/messages.fr.yaml,内容示例如下:

entity:
  foo: some translation
  bar: another translation
  third:
    title: one more

目前我是在JavaScript代码块里用Twig的trans过滤器逐个传递翻译:

const translations = {
  foo: "{{'entity.foo'|trans}}",
  bar: "{{'entity.bar'|trans}}",
  third: {
    title: "{{'entity.third.title'|trans}}"
  }
}

有没有办法直接传递entity下的所有属性?能不能把翻译作为对象获取,再通过JSON传入变量(用Twig变量或者必要时用<?php ... ?>输出)?我知道可以用AJAX,但希望直接在模板里完成数据传递。


解决方法

方法1:Symfony控制器直接传递翻译数组

如果你基于Symfony框架开发,可以直接在控制器里获取整个entity节点的翻译数组,传给Twig后转成JSON输出到JS:

1. 控制器中获取翻译数据

// 控制器方法
public function yourAction(TranslatorInterface $translator)
{
    $locale = $translator->getLocale();
    // 加载对应语言的翻译文件
    $loader = new YamlFileLoader();
    $resource = __DIR__.'/../translations/messages.'.$locale.'.yaml';
    
    $catalogue = new MessageCatalogue($locale);
    $loader->load($resource, $locale, 'messages');
    
    // 取出entity节点的所有翻译内容
    $entityTranslations = $catalogue->get('entity');
    
    return $this->render('your_template.html.twig', [
        'entity_translations' => $entityTranslations,
    ]);
}

2. Twig模板输出为JSON

<script>
const translations = {{ entity_translations|json_encode|raw }};
</script>

这样就能直接拿到完整的entity翻译对象,不用再逐个手动赋值。

方法2:自定义Twig函数批量翻译节点

如果不想在控制器里处理,可以写个Twig扩展函数,直接在模板里获取指定节点的翻译:

1. 创建Twig扩展类

// src/Twig/TranslationExtension.php
namespace App\Twig;

use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;
use Symfony\Component\Translation\TranslatorInterface;
use Symfony\Component\Translation\Loader\YamlFileLoader;
use Symfony\Component\Translation\MessageCatalogue;

class TranslationExtension extends AbstractExtension
{
    private $translator;
    private $transDir;

    public function __construct(TranslatorInterface $translator, string $transDir)
    {
        $this->translator = $translator;
        $this->transDir = $transDir;
    }

    public function getFunctions(): array
    {
        return [
            new TwigFunction('trans_node', [$this, 'translateNode']),
        ];
    }

    public function translateNode(string $nodePath): array
    {
        $locale = $this->translator->getLocale();
        $resource = $this->transDir.'/messages.'.$locale.'.yaml';
        
        $loader = new YamlFileLoader();
        $catalogue = new MessageCatalogue($locale);
        $loader->load($resource, $locale, 'messages');
        
        // 递归定位到目标节点
        $parts = explode('.', $nodePath);
        $translations = $catalogue->all('messages');
        foreach ($parts as $part) {
            if (!isset($translations[$part])) return [];
            $translations = $translations[$part];
        }
        
        // 递归翻译所有子节点
        return $this->translateNestedArray($translations, $nodePath);
    }

    private function translateNestedArray(array $array, string $prefix): array
    {
        $result = [];
        foreach ($array as $key => $value) {
            if (is_array($value)) {
                $result[$key] = $this->translateNestedArray($value, $prefix.'.'.$key);
            } else {
                $result[$key] = $this->translator->trans($prefix.'.'.$key);
            }
        }
        return $result;
    }
}

2. Twig模板中调用函数

<script>
const translations = {{ trans_node('entity')|json_encode|raw }};
</script>

这个方法更灵活,直接在模板里调用就能拿到整个节点的翻译对象。

方法3:简易版(Twig直接解析YAML)

如果是快速测试场景,也可以用Twig的YAML扩展直接读取翻译文件,再递归翻译:

{% set rawTrans = yaml_parse(file_get_contents('translations/messages.' ~ app.request.locale ~ '.yaml')) %}

{% macro translateArr(arr, prefix) %}
    {% set result = {} %}
    {% for key, val in arr %}
        {% if val is iterable %}
            {% set result = result|merge({(key): _self.translateArr(val, prefix ~ '.' ~ key)}) %}
        {% else %}
            {% set result = result|merge({(key): (prefix ~ '.' ~ key)|trans}) %}
        {% endif %}
    {% endfor %}
    {{ result|json_encode|raw }}
{% endmacro %}

<script>
const translations = {{ _self.translateArr(rawTrans.entity, 'entity') }};
</script>

注意:这个方法没有缓存机制,适合临时测试,不推荐生产环境大量使用。


内容的提问来源于stack exchange,提问作者chris_cm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 23:05:22