🌐 多语言
ThinkAdmin 的多语言能力基于 ThinkPHP 语言包机制实现。框架负责语言识别、语言包加载和 lang() 翻译调用,ThinkAdmin 在此基础上补充了核心组件语言包、项目全局语言包,以及英文、繁体语言包从数据字典读取部分翻译的能力。
当前默认配置只启用 zh-cn。如果需要英文、繁体或其他语言,需要先在 config/lang.php 中加入对应语言,再准备语言包文件。
默认配置
项目默认语言配置位于 config/lang.php:
<?php
return [
'default_lang' => 'zh-cn',
'allow_lang_list' => ['zh-cn'],
'accept_language' => [
'en' => 'en-us',
'zh-hans-cn' => 'zh-cn',
],
'detect_var' => 'lang',
'cookie_var' => '__lang_disabled__',
'header_var' => 'lang',
'use_cookie' => false,
'allow_group' => false,
'extend_list' => [],
];关键点:
default_lang默认是zh-cn。allow_lang_list默认只有zh-cn,因此?lang=en默认不会切到英文。accept_language只负责把短名称或浏览器语言映射为语言包名称,映射结果仍必须在allow_lang_list内。use_cookie默认是false,并且cookie_var被设置为__lang_disabled__,不会默认持久化用户语言选择。
启用英文示例:
return [
'default_lang' => 'zh-cn',
'allow_lang_list' => ['zh-cn', 'en-us'],
'accept_language' => [
'en' => 'en-us',
'en-us' => 'en-us',
'zh-hans-cn' => 'zh-cn',
],
'detect_var' => 'lang',
'cookie_var' => '__lang_disabled__',
'header_var' => 'lang',
'use_cookie' => false,
'allow_group' => false,
'extend_list' => [],
];加载来源
标准后台页面会注册 ThinkPHP 的 LoadLangPack 中间件,并在 MultAccess 解析出当前应用或插件后重新切换当前语言,以便加载当前应用语言包。
实际常见来源如下:
| 来源 | 文件位置 | 说明 |
|---|---|---|
| 核心组件语言包 | think-library/src/lang/{lang}.php | 由 RbacAccess 在路由中间件中加载 |
| 项目全局语言包 | lang/{lang}.php | 由 RbacAccess 在路由中间件中加载,适合放项目公共翻译 |
| 应用或插件语言包 | 当前应用或插件的 lang/{lang}.php | 当前应用解析后由 ThinkPHP 语言包机制加载 |
接口模式、RPC 模式或请求中带 not_init_session 时,系统不会注册会话和 LoadLangPack 中间件。此类接口若依赖应用语言包,应自行验证当前请求是否已经加载了需要的语言包。
语言包文件
语言包文件是返回数组的 PHP 文件:
<?php
// app/admin/lang/en-us.php 或插件 lang/en-us.php
return [
'用户管理' => 'Users',
'保存成功!' => 'Saved successfully.',
'welcome_user' => 'Welcome, {name}.',
];使用时通过 lang() 读取:
echo lang('用户管理');
echo lang('welcome_user', ['name' => 'John']);模板中也可以直接调用:
<span>{:lang('用户管理')}</span>
<span>{:lang('welcome_user', ['name' => $user.name])}</span>建议在业务代码中优先使用中文文案作为语言键。当前语言包没有命中时,ThinkPHP 通常会返回原语言键,页面仍能显示可读文本。
内置英文与繁体
ThinkAdmin 当前内置了核心组件的英文与繁体语言包:
think-library/src/lang/en-us.phpthink-library/src/lang/zh-tw.phpthink-plugs-admin/src/lang/en-us.php
其中 think-library/src/lang/en-us.php 会读取数据字典:
| 数据字典类型 | 用途 |
|---|---|
英文字典 | 普通英文翻译,code 为语言键,name 为英文翻译 |
英文菜单 | 后台菜单英文翻译,读取后会加上 menus_ 前缀 |
think-library/src/lang/zh-tw.php 会读取数据字典:
| 数据字典类型 | 用途 |
|---|---|
繁体中文 | 普通繁体翻译,code 为语言键,name 为繁体翻译 |
繁体菜单 | 后台菜单繁体翻译,读取后会加上 menus_ 前缀 |
这些动态字典读取结果会缓存 360 秒:
$langs = array_column(SystemBase::items('英文字典'), 'name', 'code');
$menuItems = array_column(SystemBase::items('英文菜单'), 'name', 'code');
foreach ($menuItems as $key => $name) {
$langs["menus_{$key}"] = $name;
}修改数据字典翻译后,需要等待缓存过期,或清理系统缓存后再验证。
菜单翻译
后台菜单翻译使用 menus_ 前缀。语言包里可以直接写静态菜单翻译:
return [
'menus_系统管理' => 'System',
'menus_系统用户管理' => 'Users',
];也可以从数据字典读取后拼接前缀:
$menus = array_column(SystemBase::items('英文菜单'), 'name', 'code');
foreach ($menus as $key => $name) {
$langs["menus_{$key}"] = $name;
}菜单是否完整翻译取决于当前语言包是否包含对应键。系统不会自动为任意语言生成菜单翻译;新增语言时,需要在语言包文件中自行定义或自行读取对应数据字典类型。
新增语言
新增语言需要同时处理配置和语言包:
- 在
config/lang.php的allow_lang_list中加入语言名称,如ja-jp。 - 如需短参数切换,在
accept_language中增加映射,如'ja' => 'ja-jp'。 - 在目标应用、插件或项目全局
lang/目录中创建ja-jp.php。 - 如果后台菜单也需要翻译,补充
menus_...对应翻译。 - 如果语言包里读取了数据字典,修改字典后清理缓存或等待缓存过期。
示例:
<?php
// lang/ja-jp.php 或 app/admin/lang/ja-jp.php
use think\admin\Library;
use think\admin\model\SystemBase;
$cacheKey = 'lang-ja-jp';
$langs = Library::$sapp->cache->get($cacheKey, []);
if (empty($langs)) {
$langs = array_column(SystemBase::items('日文字典'), 'name', 'code');
$menus = array_column(SystemBase::items('日文菜单'), 'name', 'code');
foreach ($menus as $key => $name) {
$langs["menus_{$key}"] = $name;
}
Library::$sapp->cache->set($cacheKey, $langs, 360);
}
return array_merge([
'用户管理' => 'ユーザー',
'保存成功!' => '保存しました。',
], $langs);切换方式
默认 detect_var 是 lang,因此可以通过 URL 参数尝试切换:
/admin/index/index?lang=en但能否切换成功取决于 allow_lang_list。默认只允许 zh-cn,启用英文后才会使用 accept_language 把 en 映射到 en-us。
也可以在代码中使用 ThinkPHP 的语言接口:
use think\facade\Lang;
Lang::setLangSet('en-us');
echo lang('用户管理');如果只想读取指定语言,可以传入第三个参数:
echo lang('用户管理', [], 'en-us');常见问题
?lang=en 为什么没有切到英文?
检查 config/lang.php:
allow_lang_list是否包含en-us。accept_language是否包含'en' => 'en-us'。- 当前请求是否走了语言包中间件,接口模式下不要默认假设应用语言包已经加载。
修改数据字典后为什么不生效?
英文和繁体核心语言包读取数据字典后会缓存 360 秒。可清理缓存后再验证:
php think clear语言包应该放在哪里?
公共翻译可以放在项目根 lang/{lang}.php。某个应用或插件专用翻译放在对应应用或插件的 lang/{lang}.php。不要把应用语言包写到不存在的 app/lang/ 目录里。
是否必须同时配置字典和菜单?
不是强制要求。普通文案只需要普通语言键;后台菜单需要 menus_... 键。若一个语言既要翻译页面文案,也要翻译菜单,就需要同时补齐两类翻译。
