翻译不生效主因是缓存未更新:Symfony 4 默认启用翻译缓存且不自动感知XLIFF变更;开发环境应清缓存、删var/cache/dev/translations、配null缓存池,并检查路径、格式、locale传递是否正确。

翻译不生效,大概率不是漏翻了,而是缓存拦住了新内容——Symfony 4 默认启用翻译缓存,但缓存不会自动感知 XLIFF 文件变更,改完翻译文件却看不到效果,正是这个机制在起作用。
确认缓存是否真在作祟
开发环境下(APP_ENV=dev),Symfony 本应禁用翻译缓存、每次读取最新文件。如果仍不生效,先排除缓存干扰:
- 执行 php bin/console cache:clear,不只是清应用缓存,也刷新翻译资源索引
- 检查 var/cache/dev/translations/ 目录是否存在;若存在且有 .php 文件,说明缓存已生成,删掉整个 translations/ 子目录再试
- 临时在 config/packages/translation.yaml 中加一行:cache: 'pool: translation_pool',然后定义一个无缓存的池(见下文)
禁用或替换翻译缓存池
Symfony 4 使用 PSR-6 缓存池管理翻译加载,默认复用 cache.app。要彻底绕过缓存,可配置一个“空池”:
- 在 config/packages/cache.yaml 中添加:
cache:
pool:
translation_pool:
adapter: cache.adapter.null
- 再回到 translation.yaml,绑定该池:cache: 'pool: translation_pool'
- 这样每次
trans()都会重新解析 XLIFF,适合开发调试
检查路径与命名是否触发缓存误判
缓存键基于文件路径、域、locale 和 loader 类型生成。一处不匹配,缓存就查不到,但也不会报错,只会静默回退到原文:
- 确保 translations/messages.fr.xlf 文件真实存在,且 XML 格式合法(
内有) - 确认 translation.yaml 中 translator.default_path 指向正确目录(如
'%kernel.project_dir%/translations') - 不要混用格式:Symfony 4 支持 XLIFF、PHP、YAML,但同一项目建议统一用 XLIFF;若用了
messages.fr.yaml,需确认已启用 YAML 加载器(symfony/yaml包已安装且未被禁用)
验证 locale 是否真正传递到 Translator
缓存生效的前提是 locale 正确。即使 URL 是 /fr/contact,若请求对象没设置 _locale,Translator 仍用默认 locale 查缓存:
- 在控制器中加 dump($this->getParameter('kernel.default_locale'), $request->get('_locale')) 看实际值
- 确认路由已声明 locale 参数,例如:
defaults: { _locale: '%kernel.default_locale%' },且prefix: '/{_locale}' - 若用 Twig,别写
{{ 'hello'|trans({}, 'messages', app.request.get('_locale')) }}—— 这样每次调用都重算 locale,反而绕过缓存设计;应让 Translator 自动从 RequestStack 获取,更可靠











