symfony translation:extract 默认不扫描 twig 模板,因仅识别 php 中的 trans() 等调用;需安装 symfony/twig-bridge、在 translation.yaml 中启用 twig extractor、指定 --format=xlf 并用 --dir 显式包含 templates/ 路径。

Symfony translation:extract 命令默认不扫描 Twig 模板文件,直接运行会漏掉 {{ 'hello'|trans }} 或 {% trans %}hello{% endtrans %} 这类模板内字符串——这是众包翻译前最常踩的坑。
为什么 extract 命令不提取 Twig 模板?
Symfony 默认只识别 PHP 文件中的 trans()、transChoice() 和 TranslatableMessage 调用。Twig 是独立语法层,需要显式启用解析器支持。
关键点在于:translation:extract 依赖 PhpAstExtractor,而 Twig 提取需额外注册 TwigExtractor —— 它不是开箱即用的组件,必须手动激活。
- 确保已安装
symfony/twig-bridge(含TwigExtractor):composer require symfony/twig-bridge - 在
config/packages/translation.yaml中显式启用 Twig 支持:framework: translator: extractors: ['twig'] - 运行提取时必须指定
--format=xlf(XLIFF 是唯一支持 Twig 提取的格式)
如何让 extract 命令扫描 .twig 文件?
命令本身不区分文件后缀,靠 extractor 配置决定扫描逻辑。启用 twig extractor 后,需用 --dir 显式包含模板路径:
- 典型模板路径是
templates/或src/Resources/views/,不能只写src/ - 正确命令示例:
php bin/console translation:extract en --dir=templates --format=xlf --output-dir=translations - 若项目混用 PHP 和 Twig 消息,建议分两次提取:先扫
src/(PHP),再扫templates/(Twig),避免冲突 -
--keep参数对 Twig 提取无效——XLIFF 的<source></source>是键名而非原文,重复提取会覆盖<target></target>空值
众包翻译前必须处理的 XLIFF 特性
XLIFF 是众包平台(如 Crowdin、Weblate)的标准格式,但 Symfony 生成的 XLIFF 默认不含 <note></note> 上下文注释,协作时容易误译。
- 添加上下文注释需自定义 extractor 或 patch
TwigExtractor:在transfilter 或 tag 后加注释,例如{{ 'user.email'|trans }} {# Email address shown in profile page #} - 确保
<file></file>标签中source-language="en"正确,否则众包平台可能拒绝导入 - 不要手动编辑
<trans-unit id="..."></trans-unit>的id属性——它由 extractor 自动生成,修改会导致合并失败 - 导出后检查
<source></source>内容是否为键名(如user.email)而非原文;若看到原文,说明 extractor 未生效或格式选错
真正麻烦的不是提取动作本身,而是 XLIFF 文件里那些看不见的命名空间和域(domain)绑定——比如 validators.en.xlf 里的键只对验证器生效,模板里调用 trans('required', domain: 'validators') 才能命中,漏写 domain 参数会让众包译文完全失效。











