🌐 多语言

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}.phpRbacAccess 在路由中间件中加载
项目全局语言包lang/{lang}.phpRbacAccess 在路由中间件中加载,适合放项目公共翻译
应用或插件语言包当前应用或插件的 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.php
  • think-library/src/lang/zh-tw.php
  • think-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;
}

菜单是否完整翻译取决于当前语言包是否包含对应键。系统不会自动为任意语言生成菜单翻译;新增语言时,需要在语言包文件中自行定义或自行读取对应数据字典类型。

新增语言

新增语言需要同时处理配置和语言包:

  1. config/lang.phpallow_lang_list 中加入语言名称,如 ja-jp
  2. 如需短参数切换,在 accept_language 中增加映射,如 'ja' => 'ja-jp'
  3. 在目标应用、插件或项目全局 lang/ 目录中创建 ja-jp.php
  4. 如果后台菜单也需要翻译,补充 menus_... 对应翻译。
  5. 如果语言包里读取了数据字典,修改字典后清理缓存或等待缓存过期。

示例:

<?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_varlang,因此可以通过 URL 参数尝试切换:

/admin/index/index?lang=en

但能否切换成功取决于 allow_lang_list。默认只允许 zh-cn,启用英文后才会使用 accept_languageen 映射到 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_... 键。若一个语言既要翻译页面文案,也要翻译菜单,就需要同时补齐两类翻译。

最近更新:
Contributors: 邹景立, Anyon