关键在于语言标识作为uri第一段需被路由、控制器、语言加载协同识别:路由用$route['(en|zh)(/:any)'] = '$2'透传路径,my_controller中取segment(1)设语言并重载文件,.htaccess规则须含[l]且排除静态资源,语言文件名必须含_lang.php、load()第二参数须匹配目录名,任一环节标识不一致即中断。

CodeIgniter 实现多语言 URL(如 /en/about、/zh/contact)的关键不在「加个参数」,而在于让语言标识成为 URI 第一段,并被路由、控制器、语言加载三者协同识别——否则会出现 404、语言不切换、URL 回退带多余段等典型问题。
怎么配置路由让 /en/xxx 正确匹配控制器
不能只靠 $route['(en|zh)'] = 'home'; 这类静态规则,必须捕获语言段并透传后续路径:
-
$route['(en|zh)(/:any)'] = '$2';—— 匹配带子路径的情况,如/en/blog/post/123 -
$route['(en|zh)'] = 'home';—— 单独访问语言根路径时指向首页 - 这两条必须放在
routes.php靠前位置,且在$route['default_controller']之后、其他泛匹配规则之前,否则会被$route['(:any)']提前吞掉 - 注意:正则括号里不要加空格,
(en|zh)有效,(en | zh)会导致匹配失败
为什么继承 MY_Controller 比用 Hook 更可控
用 pre_controller 或 post_controller_constructor Hook 加载语言,容易在重定向、AJAX 请求或 CLI 调用中出错;而控制器基类能确保每次 HTTP 请求都走同一套逻辑:
- 在
MY_Controller::__construct()中用$this->uri->segment(1)取第一段,判断是否为合法语言码(需提前定义$allowed_langs = ['en', 'zh', 'ja']) - 调用
$this->config->set_item('language', $lang)后,必须紧接着$this->lang->load(),否则视图中lang()仍读默认语言文件 - 别忘了设置
$this->config->set_item('lang_path', "$lang/");,否则生成的base_url()或site_url()不会自动补上前缀 - 如果控制器没继承
MY_Controller(比如直接继承CI_Controller),语言切换就完全失效——这点极易被忽略
.htaccess 里 RewriteRule 的顺序和标志直接影响多语言 URL 是否生效
Apache 重写规则不是“写了就通”,顺序和标志错一个,/en/about 就可能变成 index.php?/en/about 或直接 404:
- 必须启用
RewriteEngine On,且确保 Apache 已加载mod_rewrite - 关键规则要写成:
RewriteRule ^(.+)$ index.php?/$1 [L]—— 注意末尾的[L]表示“最后一条”,防止后续规则干扰 -
RewriteCond %{REQUEST_FILENAME} !-f和!-d必须存在,否则静态资源(如/en/assets/css/app.css)也会被转发到 PHP,导致 500 错误 - 若项目部署在子目录(如
http://example.com/myapp/),RewriteRule中的路径要补上子目录名:RewriteRule ^(.+)$ /myapp/index.php?/$1 [L]
语言文件加载和 lang() 调用的常见断裂点
即使 URL 和路由都对了,lang('welcome') 还是显示英文,大概率卡在这几个环节:
- 语言文件路径必须严格为
application/language/en/welcome_lang.php,其中$lang['welcome'] = 'Hello';—— 文件名必须含_lang,变量名必须是$lang -
$this->lang->load('welcome', 'en')的第二个参数是语言目录名,不是语言码;如果目录叫english,这里就得传'english',而非'en' - 视图中用
lang('welcome')前,控制器必须已执行过load();不能依赖 config 中的默认语言设置来“兜底” - 缓存问题:CI 默认缓存语言文件,改完
welcome_lang.php后要清application/cache/下相关文件,否则看不到更新
真正难的不是写几行路由或加个 _lang.php,而是所有环节——从 Apache 重写、CI 路由解析、控制器语言感知、到视图函数调用——必须用同一套语言标识逻辑串起来。任意一环把 en 当字符串处理、另一环当目录名处理,就会断在中间。










