Xiuno BBS 采用关联数组方式实现多语言,核心是 PHP 原生的 return array() 结构。
Accept-Language 自动选择语言| 代码 | 语言 | 目录 |
|---|---|---|
| zh-cn | 简体中文 | lang/zh-cn/ |
| zh-tw | 繁体中文 | lang/zh-tw/ |
| en-us | English | lang/en-us/ |
| ru-ru | Русский | lang/ru-ru/ |
| th-th | lang/th-th/ |
lang/
├── zh-cn/
│ ├── bbs.php ← 前台语言统一入口(include 子模块)
│ ├── bbs_common.php ← 通用词汇(登录、提交、删除等)
│ ├── bbs_user.php ← 用户相关(注册、个人资料等)
│ ├── bbs_thread.php ← 帖子相关(发表、回复、收藏等)
│ ├── bbs_forum.php ← 版块相关
│ ├── bbs_search.php ← 搜索相关
│ ├── bbs_theme.php ← 主题/外观相关
│ ├── bbs_social.php ← 社交相关(关注、通知、动态等)
│ ├── bbs_friendlink.php ← 友情链接
│ ├── bbs_misc.php ← 其他杂项
│ ├── bbs_admin.php ← 后台管理
│ └── bbs_install.php ← 安装程序
├── zh-tw/
│ └── ... ← 同上结构
├── en-us/
│ └── ...
├── ru-ru/
│ └── ...
└── th-th/
└── ...
<?php
$lang = array();
$_lang_dir = APP_PATH . "lang/{$conf['lang']}";
// 按模块 include 子文件
$lang += include _include("$_lang_dir/bbs_common.php");
$lang += include _include("$_lang_dir/bbs_user.php");
$lang += include _include("$_lang_dir/bbs_thread.php");
// ... 其他模块
// hook lang_zh_cn_bbs.php ← 插件语言注入点
// 编译时,插件的 hook 文件内容会追加到这里
return $lang;
注意:必须使用 _include() 而非 include,确保:
tmp/ 目录| 文件 | 内容 | 示例 key |
|---|---|---|
| bbs_common.php | 通用操作 | login, logout, submit, delete, success, error |
| bbs_user.php | 用户功能 | register, user_center, edit_profile, change_password |
| bbs_thread.php | 帖子功能 | create_thread, reply, digest, top |
| bbs_forum.php | 版块功能 | forum, category, sub_forum |
| bbs_search.php | 搜索功能 | search, search_result, no_result |
| bbs_theme.php | 主题功能 | theme_settings, light_mode, dark_mode |
| bbs_social.php | 社交功能 | follow, followers, my_feed, notification |
| bbs_friendlink.php | 友情链接 | friend_link, link_name, link_url |
| bbs_misc.php | 其他杂项 | no_data, loading, confirm_action |
/**
* 获取翻译文本
* @param string $key 语言 key
* @param array $arr 可选,替换变量
* @return string 翻译后的文本
*/
function lang($key, $arr = array()) {
global $_SERVER;
$text = isset($_SERVER['lang'][$key]) ? $_SERVER['lang'][$key] : $key;
if (!empty($arr)) {
$search = $replace = array();
foreach ($arr as $k => $v) {
$search[] = '{' . $k . '}';
$replace[] = $v;
}
$text = str_replace($search, $replace, $text);
}
return $text;
}
基本用法
echo lang('login'); // 输出:登录 / Login / 登入
变量替换
// 语言文件中的定义
'welcome' => '欢迎 {username},您有 {count} 条新消息',
// 调用
echo lang('welcome', array('username' => '张三', 'count' => 5));
// 输出:欢迎 张三,您有 5 条新消息
HTML 内容翻译
// 语言文件中
'terms' => '我已阅读并同意<a href="/terms">服务条款</a>',
// 调用
echo lang('terms');
// 输出:我已阅读并同意<a href="/terms">服务条款</a>
// 推荐:下划线分隔,小写
'user_register_success' => '注册成功'
'thread_create_success' => '发帖成功'
'confirm_delete' => '确定要删除吗?'
// 不推荐:驼峰命名、混合大小写
'userRegisterSuccess' // ❌
'THREAD_CREATE_SUCCESS' // ❌
插件在 hook/ 目录下放置语言文件:
plugin/my_plugin/
├── hook/
│ ├── lang_zh_cn_bbs.php ← 中文翻译
│ ├── lang_en_us_bbs.php ← 英文翻译
│ ├── lang_zh_tw_bbs.php ← 繁体翻译
│ ├── lang_ru_ru_bbs.php ← 俄语翻译
│ └── lang_th_th_bbs.php ← 泰语翻译
└── ...
<?php
// hook/lang_zh_cn_bbs.php
return array(
// 建议使用插件名前缀避免冲突
'my_plugin_title' => '我的插件',
'my_plugin_enable' => '启用插件',
'my_plugin_disable' => '禁用插件',
'my_plugin_config' => '插件设置',
'my_plugin_settings_saved' => '设置已保存',
);
<?php echo lang('my_plugin_title'); ?>
如果插件有后台设置页面,需要创建后台语言文件:
plugin/my_plugin/
├── hook/
│ ├── lang_zh_cn_bbs.php
│ ├── lang_en_us_bbs.php
│ └── ...
└── hook/admin/
├── lang_zh_cn_bbs_admin.php ← 后台中文
└── lang_en_us_bbs_admin.php ← 后台英文
<?php
// hook/admin/lang_zh_cn_bbs_admin.php
return array(
'my_plugin_admin_title' => '我的插件管理',
'my_plugin_admin_settings' => '插件设置',
);
后台语言会在加载 bbs_admin.php 时通过 hook 注入。
为避免与核心或其他插件冲突,建议:
// 推荐:插件名_功能
'haya_favorite_add' => '收藏'
'haya_favorite_remove' => '取消收藏'
// 推荐:插件名_模块_功能
'sitemap_admin_generate' => '生成站点地图'
'sitemap_admin_settings' => '地图设置'
HTML 模板中
<h1><?php echo lang('user_center'); ?></h1>
<button class="btn btn-primary"><?php echo lang('submit'); ?></button>
JavaScript 中(通过 data 属性)
<button class="btn btn-danger" onclick="confirmDelete('<?php echo lang('confirm_delete'); ?>')">
<?php echo lang('delete'); ?>
</button>
JavaScript 中(通过 DOM 注入)
// 在 JS 文件中
var deleteConfirmText = document.getElementById('delete-btn').dataset.confirm;
<button id="delete-btn" class="btn btn-danger" data-confirm="<?php echo lang('confirm_delete'); ?>">
<?php echo lang('delete'); ?>
</button>
❌ 错误示例
<span>帖子</span>
<button>删除</button>
<a href="/user">个人中心</a>
✅ 正确示例
<span><?php echo lang('thread'); ?></span>
<button><?php echo lang('delete'); ?></button>
<a href="<?php echo url('user'); ?>"><?php echo lang('user_center'); ?></a>
对于运行时生成的文本,需要在语言包中添加对应的 key:
// 语言文件
'upload_success' => '上传成功'
'upload_failed' => '上传失败,错误码:{error_code}'
// PHP 代码
if ($uploadSuccess) {
message(0, lang('upload_success'));
} else {
message(-1, lang('upload_failed', array('error_code' => $errorCode)));
}
用户选择语言 → 设置 Cookie → 刷新页面 → 检测 Cookie → 加载对应语言包
语言检测优先级
Accept-Language 头lang 配置)相关代码位置
index.inc.php 中的 detect_user_lang()route/lang.phpview/htm/header_nav.inc.htm 中的语言下拉菜单// route/lang.php
$lang_code = param(1) . '-' . param(2); // 如 'en-us'
setcookie('lang', $lang_code, time() + 86400 * 365, '/');
前台语言切换通过 URL 路由实现:
?lang-zh-cn.htm → 切换到简体中文
?lang-en-us.htm → 切换到 English
注意:URL 中使用 - 分隔语言代码,如 en-us,不要使用 en_us。
后台使用独立的语言包 bbs_admin.php,不受前台语言切换影响。
后台管理员可以在后台导航栏单独切换后台显示语言,设置同样保存在 Cookie 中。
// lang/zh-cn/bbs_admin.php
return array(
// 后台特有的翻译
'admin_dashboard' => '仪表盘',
'admin_settings' => '站点设置',
'admin_user_manage' => '用户管理',
// ...
);
<?php echo lang('admin_dashboard'); ?>
| 方面 | 后台语言 | 前台语言 |
|---|---|---|
| 文件 | bbs_admin.php |
bbs.php 及子模块 |
| 语言 key 前缀 | admin_ |
无特定前缀 |
| 切换影响 | 仅后台 | 仅前台 |
| 插件 hook | hook/lang_*_bbs_admin.php |
hook/lang_*_bbs.php |
// lang/zh-cn/bbs_install.php
return array(
'install_welcome' => '欢迎使用 Xiuno BBS 安装向导',
'install_database' => '数据库配置',
'install_admin_account' => '创始人账号',
'install_complete' => '安装完成',
// ...
);
// install/index.php
$_lang = include APP_PATH . "lang/{$conf['lang']}/bbs_install.php";
安装程序通常需要先让用户选择语言,然后再加载对应语言包。
tools/lang_sync_check.php
php tools/lang_sync_check.php
=== 语言包同步检测 ===
基准语言:zh-cn (410 keys)
en-us: 367 keys, 缺失 43 个 key
- missing_key_1
- missing_key_2
...
zh-tw: 310 keys, 缺失 100 个 key
- missing_key_1
...
API 返回的数据通常不需要翻译,但错误消息需要支持多语言。
方式一:API 返回错误码,客户端翻译
// API 返回
return json(['code' => 1001, 'message' => lang('user_not_login')]);
客户端根据错误码和当前语言显示对应的消息。
方式二:API 接受语言参数,返回翻译后的消息
// API 入口
$apiLang = param('lang', $conf['lang']);
// 加载对应语言包
$_lang = include APP_PATH . "lang/{$apiLang}/bbs.php";
如果 API 需要独立的语言处理,可以创建 bbs_api.php:
// lang/zh-cn/bbs_api.php
return array(
'api_success' => '操作成功',
'api_failed' => '操作失败',
'api_invalid_params' => '参数错误',
'api unauthorized' => '未授权',
// ...
);
在 zh-cn/bbs.php 及子模块中添加新 key
// bbs_thread.php
'thread_pin' => '置顶',
在所有其他语言包中添加对应翻译
// en-us/bbs_thread.php
'thread_pin' => 'Pin Topic',
运行同步检测工具确认无遗漏
{placeholder} 保持一致变量占位符
// ❌ 错误:占位符顺序不一致
'zh' => '{name} 赞了 {user} 的帖子'
'en' => '{user} liked {name}\'s post'
// ✅ 正确:占位符顺序一致
'zh' => '{name} 赞了 {user} 的帖子'
'en' => '{user} liked {name}\'s post'
HTML 内容
// ❌ 错误:HTML 标签不匹配
'zh' => '<strong>重要</strong> 请阅读'
'en' => '<strong>Important</strong> Please read'
// HTML 属性可能需要翻译
'search_placeholder' => '搜索...'
'en' => 'Search...'
复数形式
// PHP 原生不支持复数,需要手动处理
$msg = $count == 1
? lang('x_posts_single', ['count' => $count])
: lang('x_posts_plural', ['count' => $count]);
tools/lang_sync_check.php 检测遗漏| 常量 | 说明 |
|---|---|
$conf['lang'] |
当前站点默认语言 |
$_SERVER['lang'] |
当前会话语言数组 |
$_COOKIE['lang'] |
用户语言偏好 Cookie |
| 文件 | 位置 | 说明 |
|---|---|---|
| 语言入口 | lang/{locale}/bbs.php |
前台语言主文件 |
| 后台语言 | lang/{locale}/bbs_admin.php |
后台语言 |
| 安装语言 | lang/{locale}/bbs_install.php |
安装程序语言 |
| 切换路由 | route/lang.php |
语言切换处理 |
| 前台入口 | index.inc.php |
语言检测逻辑 |
| 检测工具 | tools/lang_sync_check.php |
同步检测脚本 |
| 模块 | key 前缀 | 示例 |
|---|---|---|
| 用户 | user_ |
user_register, user_login, user_profile |
| 帖子 | thread_ / post_ |
thread_create, thread_delete, post_edit |
| 版块 | forum_ |
forum_create, forum_update |
| 消息 | message_ / notify_ |
message_send, notify_new |
| 设置 | setting_ |
setting_save, setting_reset |
| 错误 | error_ |
error_not_found, error_permission |
| 成功 | success_ |
success_create, success_update |
文档版本:1.0 最后更新:2026-06-01
XIUNOX版本发布地址:https://xiuno.xcxgy.cn
Xiuno BBS开源程序交流论坛