CodeIgniter多语言切换失败的根源是语言加载器内部缓存未清空;必须在set_item('language', $lang)后、load()前执行$this->lang->is_loaded = [],并确保父类构造函数先调用以获取URI段。

CodeIgniter 多语言切换失败,根源常不在语言包本身,而在缓存没及时更新——特别是 $this->lang->load() 加载的语言文件被缓存后,即使 URL 切换到 zh_cn,视图里 lang('welcome') 仍返回旧语言的翻译。
关键点很明确:语言加载缓存(不是数据库缓存,也不是输出缓存)必须手动重置,否则 $this->lang 会沿用上一次加载的语言内容。
H3 语言类内部缓存必须清空
CodeIgniter 的语言加载器(Lang 类)内部用 $this->is_loaded 数组记录已加载的语言文件。它不会自动识别语言码变更,也不会覆盖已有条目。
你已在 MY_Controller 中调用:
$this->config->set_item('language', $lang);
$this->lang->load('common', $lang);但若 'common' 已在前一次请求中加载过(比如 en_us),$this->lang->load() 会直接返回缓存结果,不再读取 zh_cn/common_lang.php。
✅ 正确做法是加一行强制清空:
$this->lang->is_loaded = []; // 清空已加载记录
$this->lang->load('common', $lang);这个操作必须在 set_item('language', ...) 之后、load() 之前或紧随其后执行,顺序不能颠倒。
H3 路由与控制器初始化时机要卡准
语言切换依赖 URI 第一段(如 /zh_cn/home),但 $this->uri->segment(1) 在 parent::__construct() 之前不可用。
常见错误写法:
class MY_Controller extends CI_Controller {
public function __construct() {
$lang = $this->uri->segment(1); // ❌ segment(1) 还未初始化,返回空
$this->config->set_item('language', $lang);
parent::__construct(); // 才真正初始化 URI 类
}
}✅ 正确顺序:
public function __construct() {
parent::__construct(); // 先调父类构造函数
$lang = $this->uri->segment(1);
if (in_array($lang, ['zh_cn', 'en_us', 'ja_jp', 'ko_kr'])) {
$this->config->set_item('language', $lang);
$this->lang->is_loaded = []; // 清空语言缓存
$this->lang->load('common', $lang);
} else {
// 默认语言,也建议 reload 一次避免残留
$this->lang->is_loaded = [];
$this->lang->load('common');
}
}H3 别漏掉视图层和辅助函数的缓存影响
有些项目会把 lang() 封装成全局函数,或在视图中多次调用 lang('xxx')。只要 $this->lang->is_loaded 没清,所有调用都走旧缓存。
⚠️ 注意:
- 不要用
$this->lang->load('common')不带第二个参数,它会默认加载$config['language'],而该值在config.php里设的是静态默认值,不随 URL 动态变; -
lang()辅助函数底层调用的就是$this->lang实例,所以它完全受$this->lang->is_loaded控制; - 如果用了
language钩子(hook),也要确保钩子里做了is_loaded = [],否则钩子可能比控制器更早触发并固化缓存。
H3 开发期临时规避:关掉语言缓存(仅调试)
如果想快速验证是否为缓存问题,可在 application/config/config.php 末尾临时加:
// 开发时禁用语言缓存(上线务必删掉)
if (ENVIRONMENT === 'development') {
$autoload['language'] = array();
// 并确保 MY_Controller 中每次 load 前都重置 is_loaded
}但正式方案还是坚持 $this->lang->is_loaded = [] + 显式 load('xxx', $lang) 这个组合,最稳定、无副作用。
不复杂但容易忽略。


















