多语言路由必须显式暴露语言码为url首段,如/en/about,通过route::rule()捕获并由中间件调用lang::setlang()提前切换语言;控制器内设置无效,因翻译缓存已在前置流程锁定。

多语言路由必须显式暴露语言码作为 URL 第一段
ThinkPHP 不会自动把浏览器语言或 Session 里的语言偏好塞进 URL 路由参数里。/en/about 能匹配的前提,是 :lang 真实出现在 URL 路径第一段,且被 Route::rule() 或 Route::group() 显式捕获。
- 正确写法:
Route::rule(':lang/about', 'Page/about')->pattern(['lang' => '[a-z]{2}(-[a-z]{2})?']); - 错误写法:
Route::get('about', 'Page/about')—— 这根本没接收:lang,lang()调用时还是默认语言 - 别指望
allow_url_lang => true能让 /about?lang=en-us 自动变成 /en-us/about —— 它只影响Lang::detect()的参数读取,不改 URL 结构 - 正则
[a-z]{2}(-[a-z]{2})?比[a-z\-]+更安全,避免匹配到非法值如xx-yy-zz
语言切换必须在中间件中调用 Lang::setLang()
控制器里写 \think\Lang::setLang($lang) 是无效的——因为框架在进入控制器前,已加载验证提示、系统提示等默认语言文本,翻译缓存已锁定。
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
- 新建中间件
app/middleware/Lang.php,handle()方法开头就执行:\think\Lang::setLang($request->param('lang', $request->session('lang', config('app.default_lang')))); - 确保该中间件注册在
app/middleware.php全局数组最前面(或至少早于其他可能触发lang()的中间件) -
$request->param('lang')读的是 URL 路径段(如 /en/about 中的en),不是 query string;若想同时支持/about?lang=ja,得自己解析并 fallback - Linux 下路径大小写敏感,
lang/EN-US/和lang/en-us/是两个目录,后者才有效
伪静态配置错误会导致请求根本进不了路由层
开了多语言路由但访问 /en/about 直接 404?90% 不是路由写错了,而是 Nginx/Apache 根本没把请求转发给 index.php,Route::rule() 压根没机会执行。
- Nginx 正确配置(放在
server块内):location / {<br> if (!-e $request_filename) {<br> rewrite ^(.*)$ /index.php?s=$1 last;<br> }<br>} - Apache 必须开启
mod_rewrite,且.htaccess中RewriteBase要与实际部署路径一致(子目录部署时不能是/,得是/subdir/) - TP8 默认用
URL_MODEL => 2(PATHINFO),Nginx 下必须配fastcgi_split_path_info,否则$_SERVER['PATH_INFO']为空,路由无法解析:lang - 改完 Web 服务器配置后,必须
nginx -s reload或重启 Apache;Swoole 环境下还要php think swoole:restart
路由定义顺序和变量约束直接影响多语言路径匹配
如果 /zh-cn/user/123 匹配到了 user/:id 而不是 :lang/user/:id,说明路由注册顺序或变量规则出了问题。
- 把带
:lang的路由写在所有无语言前缀的路由之前,例如:Route::rule(':lang/user/:id', ...)必须排在Route::get('user/:id', ...)前面 - 为
:lang加严格 pattern:->pattern(['lang' => '[a-z]{2}(-[a-z]{2})?']),防止/admin/user/123被误判成:lang = admin - 别用
.*匹配语言码,它会贪婪吞掉后续路径段;\S+也慎用,可能破坏中文路径解析 - 执行
php think route:list确认:lang路由已注册,且 Method 列显示对应请求类型(GET/ANY)
lang('welcome') 就永远返回英文原词,还不会报错。php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










