yii需在request解析后、controller实例化前通过getpathinfo提取首段语言码并赋值给yii::$app->language,否则视图、验证器等已按默认语言初始化;url::to()需显式传lang参数,切换链接时须剥离当前语言前缀再拼新前缀。

URL里带 lang 参数时,UrlManager 怎么识别并切换语言
Yii 默认不把 URL 中的参数(比如 /zh-CN/site/index)自动映射到 Yii::$app->language,得手动干预路由解析和语言初始化时机。关键不是“加个参数”,而是让语言在 Request 解析完、Controller 实例化前就生效。
常见错误是把语言设置写在 beforeAction() 里——太晚了,视图、验证器、日期格式等都已按默认语言初始化完毕。
- 在
web.php配置中给urlManager加上enablePrettyUrl和showScriptName,再用rules显式声明带语言段的模式,例如:'rules' => [ '<lang:>/<controller:>/<action:>' => '<controller>/<action>', '<lang:>/<controller:>' => '<controller>/index', '<lang:>/' => 'site/index', ]</lang:></controller></controller:></lang:></action></controller></action:></controller:></lang:> - 在应用入口
web/index.php或bootstrap阶段,从Yii::$app->request->getPathInfo()提取首段作为语言代码,并立即赋值给Yii::$app->language,注意要早于Application::init()后续流程 - 别依赖
$_GET['lang']—— 它在美化 URL 下通常为空;也别在UrlRule子类里改Yii::$app->language,规则匹配发生在语言初始化之后
怎么让 Url::to() 自动生成带当前语言的链接
默认 Url::to() 不知道你正在哪个语言上下文中,它只拼接路由规则,不会自动补 lang 段。必须显式传参或重写默认行为。
最稳的方式是:所有内部跳转都显式带上 lang 参数,比如 Url::to(['site/about', 'lang' => Yii::$app->language])。否则生成的链接会丢掉语言段,用户一点击就回退到默认语言。
- 可以在
UrlManager配置中设suffix或用createUrl()钩子,但不如显式传参可控 - 如果项目大量使用
Url::to(),建议封装一个LangUrl::to()工具方法,默认合并当前Yii::$app->language - 注意
Url::toRoute()和Url::to()行为一致,都需手动传lang,没有例外
语言切换链接怎么避免重复嵌套 lang 段(如 /zh-CN/zh-CN/site/index)
这是路径解析没做前缀剥离导致的典型问题。当用户点「切换为 en-US」时,如果直接拼 /en-US/zh-CN/site/index,说明你没把当前语言段从原始路径中去掉。
正确做法是:先解析当前请求的完整路径,用正则或 explode('/', ...) 切出第一段,确认它是合法语言码后,在生成新链接前把它移除,再拼新语言前缀。
- 别用
str_replace()粗暴替换,/zh-CN/zh-CN会被误伤 - 推荐用
preg_replace('~^/(\w{2}(-\w{2})?)/~', '', $currentPath)提取并剥离首段 - 切换链接的目标路径应始终是“去语言前缀”的相对路径,例如当前是
/zh-CN/user/profile,切换目标应是/en-US/user/profile,而不是/en-US/zh-CN/user/profile
多语言路由下 AssetBundle 路径和 i18n 翻译怎么不出错
语言切换本身不影响资源路径,但如果你在 AssetBundle 的 baseUrl 或 sourcePath 里硬编码了语言相关逻辑,或者在 i18n 配置里用了动态 basePath 却没随语言变化更新,就会加载错翻译文件或 JS/CSS。
核心原则:资源路径与语言无关,翻译内容才与语言有关。Yii 的 i18n 组件默认根据 Yii::$app->language 自动选目录,前提是你的 sourceLanguage 和 basePath 配置稳定。
-
AssetBundle不需要也不应该感知语言;CSS/JS 文件路径不该因语言改变 -
i18n的translations配置里,basePath必须是固定路径(如@app/messages),不能写成@app/messages/zh-CN - 确保
messages/zh-CN/app.php这类文件结构存在,且Yii::$app->language = 'zh-CN'已在早期设置好,否则t()函数会 fallback 到sourceLanguage
最容易被忽略的是:语言切换后,页面里可能缓存了旧语言的 js 变量(比如通过 registerJsVar 注入的翻译包),这些不会自动刷新,得手动清或重新注册。











