CodeIgniter 4 的本地化需手动补全三部分:语言文件须按 BCP 47 格式置于 app/Language/ 下并以 _lang.php 结尾;路由需用正则提前捕获语言段并正确排序;控制器中须动态设置 language 配置、加载对应语言包并清缓存;数据库多语言内容须通过关联表按 locale 查询,确保前后端语言一致。

CodeIgniter 4 的本地化(locale)和多语言支持不是“开箱即用”的完整方案——它只管静态文本翻译,不管数据库内容、路由前缀或语言切换跳转。你得自己补全这三块:语言文件加载机制、URL 中语言码的提取与传递、数据库内容的按 locale 查询。
语言文件怎么放才被识别
CI4 只认 app/Language/ 下的子目录,且命名必须严格匹配 BCP 47 规范的小写+下划线格式:zh_cn、en_us、ja_jp,不能是 zh-CN 或 zhcn。语言文件必须以 _lang.php 结尾,比如 app/Language/zh_cn/auth_lang.php,里面定义的键名不能含空格或特殊字符:
$lang['login_title'] = '登录'; // ✅ 正确 $lang['login title'] = '登录'; // ❌ 静默失效
漏掉任一条件,$this->lang->line('login_title') 就返回空字符串,不报错也不 fallback。
路由里怎么把语言段提前剥离
CI4 不会自动从 /zh_cn/home 里提取 zh_cn——它默认把整个路径当控制器名处理,结果就是 404。必须在 app/Config/Routes.php 靠前位置加正则规则,且顺序不能错:
- 所有带语言前缀的路由(如
$routes->get('/zh_cn/about', 'Page::about'))必须放在通配符路由(如$routes->get('(:any)', 'Fallback::handle'))之前 - 推荐用高优先级正则统一捕获:
$routes->get('(:segment)/(:any)', 'Router::route/$1/$2'),然后在Router控制器里解析$1为语言码、$2为真实路径 - Apache 的
.htaccess要加[L]标志,否则重写可能被后续规则干扰
控制器里怎么让 $this->lang 真的切换
$config['language'] 在 app/Config/App.php 里设的是默认值,运行时不会随 URL 自动变。必须在基类控制器(如 app/Controllers/BaseController.php)的构造函数中手动处理:
- 先调
parent::__construct(),再用$this->request->getUri()->getSegment(1)读第一个路径段 - 判断是否在支持列表里:
in_array($lang, ['zh_cn', 'en_us']) - 执行
$this->config->setItem('language', $lang),紧接着$this->lang->load('common', $lang) - 如果语言切换后视图没更新,要清掉已加载缓存:
$this->lang->is_loaded = []
数据库内容怎么按语言查
$this->lang 类只管 PHP 数组里的翻译,对数据库字段完全无感。多语言内容必须自己建表结构:
- 推荐分离表:比如
articles存 ID 和时间戳,另建article_translations表,含article_id、locale、title、content字段,联合唯一键(article_id, locale) - 查询时显式 JOIN:
$this->db->join('article_translations', "articles.id = article_translations.article_id AND article_translations.locale = '{$lang}'") - 避免用 JSON 字段存多语言值(如
{"zh_cn":"标题","en_us":"Title"}),除非字段极少、语言不超过 3 种,否则 SQL 查询、索引、排序都会受限
最易被忽略的一点:语言切换后,数据库内容和页面静态文本必须用同一套 $lang 值驱动,否则会出现中文 URL + 英文标题 + 日文按钮这种割裂状态。


















