消息外部化 (i18n)
ArcartXSuite 1.1.0 起提供 消息外部化框架,让模块的所有用户可见文本从硬编码迁移到可编辑的 messages.yml。服主可自定义措辞、翻译为其他语言,无需改动代码。
核心组件
| 组件 | 位置 | 职责 |
|---|---|---|
MessageProvider | api.message | 加载 messages.yml,提供 get(key, args...) 取值 |
AbstractAXSModule#messagesFileName() | api | 声明消息文件名,基类自动导出+加载 |
AbstractAXSModule#messages() | api | 获取已加载的 MessageProvider |
工作原理
模块 jar 内 messages.yml
│ (构建期 ProtectYamlResourcesTask 加密)
▼
arcartx/internal/protected/<base64>.axb
│ (onEnable 时 context.exportConfigResource 解密导出)
▼
data/<moduleId>/messages.yml ← 用户可编辑
│ (MessageProvider.load 读取)
▼
messages().get("key", args) ← 代码中使用消息文件与 config.yml 走同一套加密/导出管线。
接入步骤
1. 创建默认消息文件
在模块 src/main/resources/messages.yml:
yaml
# 支持 & 颜色码和 {0} {1} 占位符
prefix: "&3◆ &6ArcartXSuite &7| &r"
no-permission: "&c你没有权限执行这个命令。"
toggle:
enabled: "&a功能已开启。"
disabled: "&e功能已关闭。"
status:
mode: "&7当前模式: &f{0}"嵌套键用点号路径访问:
status.mode→"当前模式: {0}"。
2. 模块声明消息文件
java
@Override
protected String messagesFileName() {
return "messages.yml";
}3. 注入到命令/服务
messages() 在 startService() 之前已就绪,可直接传给命令:
java
@Override
protected Map<String, TabExecutor> commandBindings() {
return Map.of("mycommand", new MyCommand(messages()));
}4. 替换硬编码文本
java
// 改造前
player.sendMessage(PREFIX + ChatColor.RED + "你没有权限执行这个命令。");
// 改造后
player.sendMessage(messages.get("prefix") + messages.get("no-permission"));带占位符:
java
// messages.yml: status.mode: "&7当前模式: &f{0}"
player.sendMessage(messages.get("status.mode", modeName));API 速查
| 方法 | 说明 |
|---|---|
get(key) | 取消息;键不存在时返回键名本身(便于发现遗漏) |
get(key, args...) | 取消息并替换 {0} {1} ... 占位符;null 参数替换为空串 |
has(key) | 判断键是否存在 |
size() | 已加载消息条数 |
get 自动翻译 & 颜色码为 §。
迁移现状
消息外部化采用渐进式迁移:基础设施已就绪,各模块逐步接入。
| 模块 | 状态 |
|---|---|
pickup | ✅ 已迁移(玩家命令范例) |
onlinerewards | ✅ 已迁移(管理+玩家命令范例) |
loginview | ✅ 已迁移(管理命令,service 消息已在 config 定制) |
combateffect | ✅ 已迁移(非基类模块手动集成范例) |
announcer | ✅ 已迁移(广播+字幕管理命令) |
eventpacket | ✅ 已迁移(信号触发+清理管理命令) |
title | ✅ 已迁移 |
prop | ✅ 已迁移(基类模块管理命令范例) |
questgps | ✅ 已迁移(基类模块双命令范例,包含玩家/管理命令) |
map | ✅ 已迁移(基类模块双命令范例,包含玩家/管理命令) |
chat | ✅ 已迁移(基类模块,三模式多指令集成范例) |
market | ✅ 已迁移(基类模块双命令范例,包含玩家/管理命令) |
rgb | ⚪ 无需迁移(纯 PlaceholderAPI 渲染,无命令消息) |
qqbot | ✅ 已迁移(基类模块双命令范例,包含玩家/管理命令) |
conversation | ✅ 已迁移(基类模块,NPC/动画交互命令范例) |
warehouse | ✅ 已迁移(基类模块双命令,支持二级密码与银行接口外部化) |
tab | ✅ 已迁移(基类模块,支持复杂虚拟快照管理与翻页命令外部化) |
regions | ✅ 已迁移(基类模块,支持选区、世界规则及标志指令外部化) |
essentials | ✅ 已迁移(基类模块自承载 ModuleCommandHandler 巨型指令集全部外部化) |
| 其余模块 | 🎉 100% 迁移完毕 |
非基类模块:少数模块(如
combateffect)直接implements AXSModule而非继承AbstractAXSModule,无法用messages()。它们需在onEnable手动context.exportResource("messages.yml", file, false)+new MessageProvider(...).load(),自行实现msg()辅助方法。
分层原则:命令层的框架性文本(权限/用法/状态标签/help)外部化到
messages.yml;业务结果消息(如OperationResult.message())和已在config.yml定制的文本(如签到完成语、loginview的messages.locked()锁定提示)保持原状。迁移前先检查该模块是否已有config.yml内的messages节——若有则无需重复外部化。
注意事项
- 键命名:用
kebab-case+ 点号分层(如toggle.enabled) - 前缀复用:把
prefix也放进messages.yml,连品牌前缀都可定制 - reload 生效:用户编辑
data/<moduleId>/messages.yml后/axs reload <module>即可 - 新增字段无需迁移声明:
messages.yml不是配置,不走ConfigDiagnosticEngine,新增键直接在 jar 默认文件补充即可