跳转到主内容
极星编程网:以代码为星,赴技术山海!

Symfony国际化i18n和本地化l10n的实现方法

Symfony国际化需在config/packages/framework.yaml中配置framework.translator,设default_locale为兜底值、locales为语言白名单,翻译文件按domain.locale.format命名并置于translations/目录,调用trans()时确保locale在白名单且domain匹配。 Symfony 的国际化(i18n)和 本地化 (l10n)不是“开箱即用”的魔法开关,而是靠明确配置、约定路径和正确调用翻译服务来驱动的。默认只启用英文,其他语言必须显式声明并提供翻译资源,否则
trans()
会原样返回源字符串。 如何在 config/packages/framework.yaml 中启用多语言支持 Symfony 的翻译能力由
framework.translator
配置控制,不写这一段就等于没开翻译功能。关键点是:
default_locale
决定 fallback 行为,
locales
列表才是真正允许切换的语言白名单。 常见错误是只改了
default_locale
却漏掉
locales
,结果
app.request.locale
能读到 fr,但
trans()
仍走 en 翻译——因为 fr 不在白名单里,框架直接忽略。
default_locale: 'en'
是兜底值,不是“默认生效语言”,仅当请求未指定 locale 或 locale 不在白名单时才起作用
locales: ['en', 'fr', 'zh_CN', 'ja']
必须列出所有你打算支持的语言代码,大小写敏感(
zh-cn
无效,得写
zh_CN
) 如果项目用 Twig 模板,确保
framework.assets
下的
base_urls
或 CDN 配置不影响静态资源路径,否则翻译文件加载可能 404 翻译文件该放在哪?命名和格式怎么写才被识别 Symfony 默认按
translations/messages+intl-icu.{locale}.xlf
或
messages.{locale}.php
查找,但最常用且推荐的是 XLIFF 格式,路径必须严格匹配约定:
translations/messages.fr.xlf
→ 法语翻译
translations/messages.zh_CN.xlf
→ 简体中文翻译
translations/validators.en.xlf
→ 仅用于验证器错误信息的英文翻译 容易踩的坑: 文件名中的
messages
是 domain,默认 domain 就是
messages
;如果代码里写
$translator->trans('key', [], 'admin')
,就得放
translations/admin.fr.xlf
XLIFF 文件里
标签内容不能为空,否则 Symfony 会跳过该条目,静默回退到源字符串 不要手动编辑
.mo
或
.po
文件——Symfony 不读它们;
gettext
是另一套体系,和 Symfony Translator 组件互不兼容 如何动态切换当前请求的 locale locale 不是全局变量,它绑定在每个 Request 上。不能靠
setlocale()
或环境变量修改,必须通过 Request 对象或路由参数注入。 本地化jQuery公式加中文键盘 本地化jQuery公式加中文键盘 下载 最可靠的方式是把 locale 当作路由前缀:
framework: router: strict_requirements: null # config/routes.yaml controllers: resource: ../../src/Controller/ type: annotation prefix: /{_locale} requirements: {_locale: '%supported_locales%'}
然后在控制器里用
$request->getLocale()
读取,或直接作为参数注入:
public function index(Request $request, string $_locale): Response { // $_locale 已自动解析为路由参数,如 /fr/xxx → $_locale === 'fr' }
注意: 别在中间件或事件监听器里硬编码
$request->setLocale('fr')
—— Symfony 10+ 已移除该方法,会报
BadMethodCallException
Session 或 Cookie 存的 locale 值,必须在每次请求开始时通过
RequestEvent
显式设置到 request 上,否则
trans()
仍用默认 locale 使用
RedirectResponse
跳转时,记得带上当前 locale 参数,否则用户切语言后点链接又跳回默认语言 为什么 trans() 返回原文而不是翻译?排查三步法 这是最常遇到的问题,本质是“翻译链断了”。按顺序检查: 看日志:启用
debug
模式后,
translator.missing_translation
事件会记录未找到的 key,grep
var/log/dev.log
里的
Translation not found
确认 locale 是否在
framework.yaml
的
locales
列表中,且与文件名后缀完全一致(包括下划线) 运行
bin/console debug:translation fr
(替换为你实际的 locale),它会列出所有已加载的 translation key 及状态(missing / unused),比手动翻文件快得多 真正麻烦的不是找不到翻译,而是翻译存在却因 domain 错误、缓存未清除或 ICU 格式语法错误(比如
{count, plural, =0{...}}
缺少闭合括号)被静默忽略——这种问题不会报错,只会默默返回原文。

相关文章