CodeIgniter子目录部署多语言出错的根本原因是URI路径解析与语言段定位错位,子目录干扰segment索引导致语言码读取错误、路由不匹配及初始化失效,需统一路径解析口径并适配路由与服务器配置。

CodeIgniter多语言在子目录部署出错,核心原因是语言段识别与URL路径解析错位,不是多语言功能本身失效,而是子目录干扰了URI分段逻辑,导致语言码无法被正确提取或误判。
子目录会改变URI段索引位置
CodeIgniter默认从 $this->uri->segment(1) 读取语言码(如 /zh_cn/login 中的 zh_cn)。但若应用部署在子目录(比如 https://example.com/myapp/),而 app.baseURL 配置为 'https://example.com/myapp/',那么实际请求 URL 是 https://example.com/myapp/zh_cn/login。此时:
-
getSegments()解析出的路径段是['zh_cn', 'login'](正常); -
但某些过滤器或手动解析逻辑错误地把
myapp当作 segment(1),把zh_cn推到 segment(2),结果漏掉语言码,后续强行重定向插入默认语言,引发循环重定向。
常见表现:页面反复跳转、地址栏语言前缀不断叠加(如 /en_us/zh_cn/login)、$this->lang->line() 返回空。
路由正则无法匹配带子目录的路径
routes.php 中写的规则如:
$route['^(zh_cn|en_us)/(.+)$'] = '$2';
只匹配根路径下的语言段。当真实 URL 是 /myapp/zh_cn/login 时,该正则根本不会触发——因为开头是 myapp,不是 zh_cn。
Apache 或 Nginx 的重写规则若没把子目录路径剥离干净,请求根本到不了 CodeIgniter 的路由层。
language 文件加载路径不受影响,但加载时机被破坏
application/language/zh_cn/xxx_lang.php 结构本身没问题。问题出在:
- MY_Controller 构造函数里调用
$this->uri->segment(1)时,若未考虑子目录偏移,可能读到myapp而非zh_cn; - 于是跳过语言设置,
$this->config->set_item('language', ...)没执行,后续lang()全用默认语言(甚至为空); - 即使手动
load('common', 'zh_cn'),若控制器已错过初始化时机,视图中仍拿不到翻译。
解决关键:统一路径解析口径
-
不要依赖
segment(1)硬编码:先用parse_url($this->input->server('REQUEST_URI'), PHP_URL_PATH)提取纯路径,再用trim($path, '/')分割,最后按预期位置取语言段(例如去掉myapp前缀后,第一个有效段才是语言码); -
路由规则适配子目录:Apache 的
.htaccess需加RewriteBase /myapp/;Nginx 的location块要确保fastcgi_param SCRIPT_NAME正确,避免 pathinfo 错乱; -
baseURL 和 index_page 配合设对:
$config['base_url'] = 'https://example.com/myapp/';,$config['index_page'] = 'index.php';,且确保index.php不出现在 URL 中(靠重写隐藏); -
过滤器里避免 array_unshift() 破坏索引:检测到缺失语言段时,应拼接新 URL 字符串重定向,而不是修改 segments 数组再
redirect(),否则极易引发二次误判。
本质上,子目录不是“不支持多语言”,而是把原本简单的路径对齐问题,变成了路径上下文感知问题。只要 URI 解析、路由匹配、控制器初始化三者在子目录环境下保持一致,多语言就能稳定运行。


















