translation:extract未提取新字符串,因默认只扫描src/目录且仅识别字面量调用(如trans('key')、{{ 'key'|trans }}),不支持变量调用、拼接、注释或自定义函数;需确保文件在src/下,bundle项目须在translation.yaml中显式配置paths。

translation:extract 命令为什么没提取新字符串?
默认不扫描 src/ 以外的目录,且只识别 trans()、$translator->trans()、Twig 中的 {% trans %} 和 |trans,其他写法(如硬编码拼接、变量名调用)一律忽略。
- 确保目标文件在
src/下;若用 Bundle 结构,需在config/packages/translation.yaml中显式添加路径:translator.paths - Twig 模板里必须用
{% trans %}...或{{ 'key'|trans }},{{ 'key'|trans({}, 'domain') }}才会被识别 - PHP 文件中避免写成
$t = $translator; $t->trans(...)—— 提取器只匹配字面量调用,不解析变量别名 - 自定义函数包装(如
__(...))不会被识别,除非你额外注册一个Extractor实现
PhpAstExtractor 是什么,为什么不能用 PhpExtractor?
PhpExtractor 在 Symfony 7.0 已彻底移除,PhpAstExtractor 是其替代品,基于 PHP-Parser 构建 AST 分析,更准确、更健壮,但也更严格。
- 它不支持动态键名:
$translator->trans($key)中的$key不会被提取 —— 必须是字符串字面量:$translator->trans('login.failed') - 不识别注释中的待翻译文本(不像旧版可配正则匹配注释),想靠注释驱动提取得另写插件
- 若项目含大量 eval()、字符串拼接构造的 key,提取结果会明显变少 —— 这不是 bug,是设计取舍
- 启用方式无需手动配置,只要装了
symfony/translation7.x 就自动使用PhpAstExtractor
如何让 extract 只更新指定 domain 的文件?
直接加 --domain 参数即可,但要注意它只控制输出目标,不控制扫描范围 —— 所有源码仍全量扫描,只是把匹配到的键按 domain 归类写入对应文件。
- 命令示例:
bin/console translation:extract en --domain=validators --output-format=xlf - 若未指定
--output-dir,默认写入translations/下,生成validators.en.xlf - 已有键不会被覆盖或删除,只追加新增项;但若原文件里某个 key 对应的
<source></source>文本变了,extract会保留旧<target></target>并标记为state="needs-translation"(XLIFF 标准行为) - 想清理已删除的 key?得手动删,或配合脚本比对 AST 提取结果与现有文件
提取后 XLIFF 文件里出现 state="new" 却没生成 target 怎么办?
这是 XLIFF 规范要求的行为:state="new" 表示该条目刚加入,尚未翻译,<target></target> 标签为空是正常状态,不是错误。
- 不要手动补空
<target></target>—— 翻译平台(如 POEditor、Lokalise)依赖该状态做任务分发 - 若希望预填原文(即
<target></target>=<source></source>),需加--force-english参数:bin/console translation:extract en --force-english - 注意:
--force-english仅对enlocale 生效,且只影响新条目;已有state="translated"的条目不受影响 - CI 流程中慎用
--force-english,它会让翻译团队误以为“已翻译”,实际只是占位
trans('submit', [], 'admin') 和 trans('submit', [], 'messages') 被当成两个独立 key 处理,但提取器无法判断语义差异,得靠命名规范和人工 review。











