国际化
Infernus 的国际化核心在于字符集编码转换,而非多语言翻译。虽然 $t 可以用于翻译需求,但核心功能是确保服务端(UTF-8)与玩家客户端(旧式字符集如 ISO-8859-1 或 GBK)之间的数据交换正确。大多数服务器仅服务于单一区域,因此您可能完全不需要多语言支持——但至少应了解玩家国际化部分,以避免乱码问题。
VSCode 插件
infernus-starter 中的 .vscode/extensions.json 提供了插件安装建议。强烈建议您在 VSCode 右下角弹出提示时点击安装,以便在开发时直观地查看国际化数据。
i18n-ally-custom-framework.yml 和 settings.json 已为您配置好相关插件设置。
示例
定义语言包
语言包由 .json 文件组成,以树形结构作为语言包数据的 key。
字符串中可以包含 %s 作为占位符,用于动态填充数据。
中文语言包
{
"server": {
"running": "成功运行由 node.js 强力驱动的 omp 服务器",
"connection": "连接信息:%s - %s : %s"
}
}英文语言包
{
"server": {
"running": "Successfully running an omp server powered by node.js",
"connection": "connection information: %s - %s : %s"
}
}实例化
通过 new I18n("默认区域 key", 语言包对象) 创建国际化实例。
通常我们只需使用内部的 $t 函数。
$t("语言包数据 key", [占位数组], 区域 key) 可获取对应区域的语言包文本。
当字符串没有占位符时,可传入 null、undefined 或空数组。
不传入第三个参数则从默认区域获取数据。
import { I18n } from "@infernus/core";
// 国际化的 JSON 语言包
import zh_CN from "./locales/zh_CN.json";
import en_US from "./locales/en_US.json";
const locales = {
zh_CN,
en_US,
};
export const { $t } = new I18n("en_US", locales);
console.log($t("server.running"));
console.log($t("server.connection", ["127.0.0.1", "8080", "123456"]));
console.log($t("server.connection", ["127.0.0.1", "8080", "123456"], "zh_CN"));实用函数
I18n 类还提供了几个实用的静态方法,用于字符集之间的转换:
encodeToBuf- 将字符串转换为指定字符集的字节数组。
decodeFromBuf- 将字节数组转换为指定字符集的字符串。
getValidStr- 截取字节数组中的有效字符串,以第一个
0字节作为字符串结尾标记。
- 截取字节数组中的有效字符串,以第一个
玩家国际化
每个玩家实例上有两个属性控制国际化:charset(字符集)和 locale(区域)。默认值如下:
class Player {
charset = "ISO-8859-1";
locale = "en_US";
}通常 $t 会结合玩家的区域来获取对应的语言包数据。
// 假设您有一个 player 实例
console.log($t("server.incoming", ["127.0.0.1", "8080", "123456"], player.locale));如需修改玩家的语言或字符集,请修改 charset 和 locale 属性,并始终确保 charset 正确。您可以根据 IP 地址推测玩家区域,或让玩家输入特定字符串后比对字节来推断字符集。
允许国际化用户名
TIP
默认情况下,游戏服务器只允许英文字母、数字和下划线组成的用户名连接。
OMP 提供了新的 API,可启用或禁用用户名中的特定字节值(0–255)。
GameMode.supportAllNickname() 方法利用这些 API,允许所有国际化的用户名(包括中文等非 ASCII 字符)连接游戏。
import { GameMode } from "@infernus/core";
GameMode.onInit(({ next }) => {
GameMode.supportAllNickname();
return next();
});原理
WARNING
双向字符集数据交换正常的前提是玩家的字符集设置正确。
如果设置了错误的字符集,服务端和客户端双方都将得到乱码。
Infernus 底层使用 iconv-lite 进行字符集转换,并通过 polyfill.amx 拦截 gamemode 中的部分回调,以十进制字节数组形式返回。
服务端向客户端的函数(如 SendClientMessage、SendClientMessageToAll、ShowPlayerDialog、CreateDynamic3DTextLabel)进行了字符集转换,将 UTF-8 数据转为玩家字符集数据,确保玩家能正常显示。
客户端到服务端的函数(如 OnText、OnPlayerCommandText、OnDialogResponse)同样经过了字符集转换,确保数据交换正确。
TIP
虽然字符集已转换,但玩家字符集中不包含的 UTF-8 字符仍会以乱码(如 ?)形式显示,这是早期 SA 客户端的底层限制。例如,使用 ISO-8859-1 字符集的客户端收到 emoji 或中文字符时就会显示为乱码。
对于 GameText/TextDraw,Infernus 底层始终以 UTF-8 格式交换数据,因为这两个功能基于贴图映射实现(类似于前端中的精灵图),而非真正的文本渲染。部分客户端模组(如汉化补丁)底层使用了 UTF-8 渲染,但将所有 UTF-8 字库放入一张贴图中是不现实的,效果也无法与文本数据相比。
SA 重制版内部使用 UTF-8 实现,如果未来 OMP 推出重制版的联机功能,应无需额外处理。
终端乱码
如果使用 pino.js 等日志库时终端出现乱码,可尝试以下方法解决。
PowerShell 用户请执行以下命令(仅对当前会话有效)。
如需永久生效,请将该命令添加到 $PROFILE 中。
$OutputEncoding = [Console]::InputEncoding = [Console]::OutputEncoding = New-Object System.Text.UTF8Encodingcmd 用户可使用以下命令启动 OMP 服务器:
cmd /c "chcp 65001 > nul & omp-server"上述命令会将终端的字符集切换为 UTF-8。
其他环境请自行搜索解决方案。