ThinkPHP多语言路由需显式暴露语言码为URL首段(如/zh-cn/article/123),通过Route::rule()捕获并由控制器调用Lang::setLang()提前切换语言;伪静态须正确配置Nginx/Apache转发至index.php,且确保PATH_INFO完整传递;404多因Web服务器未转发请求至框架,而非路由定义问题。

ThinkPHP 多语言路由怎么写
多语言路由不是靠“自动识别语言+拼接前缀”就能跑通的,它必须显式把语言码作为路由参数暴露出来,并在后续逻辑里提前消费——否则 lang() 会按默认语言加载,翻译就失效了。
最稳妥的做法是把语言码作为第一个 URL 段,比如 /zh-cn/article/123 或 /en/article/123,然后用 Route::rule() 或 Route::group() 显式捕获:
Route::rule(':lang/article/:id', 'Article/detail')->pattern(['lang' => '[a-z]{2}-[a-z]{2}', 'id' => '\d+']);- 控制器方法要接收
$lang参数,并立刻调用\think\Lang::setLang($lang),且必须在任何lang()调用之前 - 别指望
:lang自动进 Session 或 Cookie;它只是 URL 参数,不保存、不透传,每次请求都要重新解析 - 如果用
Route::group(['prefix' => ':lang']),注意prefix不支持变量占位符(TP6.0+ 才支持),老版本得用rule写死或手写正则
ThinkPHP 伪静态规则怎么配(Nginx / Apache)
伪静态本质是让 Web 服务器把看起来像目录的 URL 转发给入口文件(如 index.php),而不是真去查文件系统。配置错,URL_MODEL 设再高也没用。
Nginx 常见错误是 location 块没覆盖所有路径,或 rewrite 规则漏了 ? 导致 query string 丢失:
立即学习“PHP免费学习笔记(深入)”;
开箱即用的技能链路由引擎。13 条预定义链覆盖搜索、开发、审查、MLOps、法律、创意等场景,三层路由架构(触发词→SAD反馈→DAG编排),recall@10=96.97%。配置驱动(chains.yaml),零代码扩展。pip install skill-weave-chains 一键安装。
- 正确写法(放在 server 块内):
location / {<br> if (!-e $request_filename) {<br> rewrite ^(.*)$ /index.php?s=$1 last;<br> }<br>} - Apache 需确保
.htaccess可读,且mod_rewrite已启用;规则中RewriteBase /必须与部署路径一致(子目录部署时要改成RewriteBase /subdir/) - TP6 的
URL_MODEL => 2(PATHINFO)依赖服务器转发完整 PATH_INFO,Nginx 下必须用fastcgi_split_path_info拆分,否则$_SERVER['PATH_INFO']为空 - 改完配置必须 reload Nginx / restart Apache,Swoole 环境下还要
php think swoole:restart,缓存不清理的话旧规则还在内存里
为什么开了多语言 + 伪静态,/en/about 还是 404
不是路由没写,而是请求根本没进到 ThinkPHP 路由层——90% 是 Web 服务器配置拦截了,或入口文件没被正确调用。
排查顺序很关键:
- 直接访问
/index.php/en/about,能打开说明路由定义没问题,问题出在伪静态转发 - 查看 Nginx error log,搜
rewrite or internal redirection cycle,代表 rewrite 循环,通常是last和break混用或条件写错 - TP6 中检查
app/config/app.php是否设置了'url_route_must' => true,开启后所有 URL 必须匹配到路由,没定义的直接 404,连__call都不走 - 多应用模式下,
/en/about默认会去找en应用,而不是当前应用下的:lang参数——得确认是否误启用了多应用,或没在route/app.php里 import 对应路由文件
lang() 不生效,但 URL 显示 /zh-cn/xxx
语言包加载和路由是两件事。URL 里有 zh-cn 只代表你拿到了这个字符串,不代表框架已切换语言上下文。
最容易被忽略的点:
-
\think\Lang::setLang('zh-cn')必须在控制器 action 方法开头、或中间件 handle 中第一行执行;在构造函数、initialize()里调用都太晚 - 语言包路径必须是
lang/zh-cn/common.php,不能是lang/zh_CN/common.php或config/lang.php;Linux 下大小写敏感,zh-cn≠ZH-CN - 如果用了 Swoole 或 RoadRunner,语言包只在进程启动时加载一次,
setLang()只切换当前请求上下文,但包内容不会重载;所以common.php里不能有运行时逻辑(如读数据库),只能 return 数组 -
lang('missing_key')默认返回原 key 字符串,不是空或报错,很容易误判为“生效了”,实际是 key 拼错了或没写进语言包


















