LangService 把 YAML 或 JSON 中的翻译绑定为 Java 语言对象。字段结构由代码声明,翻译内容来自 Jar 资源和插件数据目录。
语言服务使用当前 Facade 的全局语言。全局语言的设置见多语言 ⇱。
@LangPack(filePath = "lang", format = FileType.YAML)
public class MainLanguage {
public Message message = new Message();
public static class Message {
public String prefix = "";
public String reloaded = "";
public LangText commandDescription = LangText.of("执行重载命令");
public LangList tips = LangList.of("默认提示");
public LangMap buttons = LangMap.of();
}
}
语言对象遵循文件服务概览 ⇱中的对象约束。字段初始化值既是代码回退值,也是补齐缺失键的依据。稳定引用类型的详细规则见语言字段引用 ⇱。
@LangPack 的主要参数为:
| 参数 | 作用 | ||
|---|---|---|---|
filePath | 语言包子目录,默认为 lang | ||
format | FileType.YAML 或 FileType.JSON | ||
emit | 是否允许生成文件、差异记录和执行显式写回 | ||
defaultLocale | 首选语言不可用时使用的回退语言 | ||
normalizeLocale | 是否把 en-GB、enGB 等名称归一化为 en_GB |
同一个 filePath 对应以下位置:
src/main/resources/langservice/<filePath>/<locale>.yml
plugins/<YourPlugin>/<filePath>/<locale>.yml
例如 filePath = "lang" 时,中文内建资源位于 src/main/resources/langservice/lang/zh_CN.yml,运行后对应 plugins/<YourPlugin>/lang/zh_CN.yml。
语言资源结构必须与语言对象字段一致:
message:
prefix: "§7[§dMyPlugin§7] "
reloaded: "配置文件重新加载成功"
command-description: "执行重载命令"
tips:
- "第一条提示"
buttons:
confirm: "确认"
cancel: "取消"
文件名就是 locale。关闭 normalizeLocale 后,扫描、读取和保存都会保留开发者传入的名称。
语言注释应直接写在 resources 中的 YAML 文件里。首次复制和后续保存会尽量保留这些注释,不需要多语言注释注解。
LangService languages = lin.linFile().language();
MainLanguage lang = languages.bind(MainLanguage.class);
需要让配置通过 @lang(...) 引用此语言包时,在绑定时提供当前插件内唯一的别名:
MainLanguage lang = languages.bind("main", MainLanguage.class);
服务优先读取当前全局语言,找不到时使用语言包的 defaultLocale,然后在内存中以代码默认值补足缺失字段。允许输出时,内建资源会被复制到插件数据目录;没有资源时则按默认值生成文件。已有语言文件不会仅因绑定或重载而自动写入缺失键。
同一 LangService 重复绑定相同语言类会返回同一个活动对象,并按当前语言刷新内容。
普通字段直接保存当前语言的值:
sender.sendMessage(lang.message.reloaded);
需要被命令或消息服务长期持有的字段使用 LangText、LangList 或 LangMap,并在读取时解析:
String description = lang.message.commandDescription.resolve();
List<String> tips = lang.message.tips.resolve();
按路径临时查询可以使用 tr(...):
String named = languages.tr(
"message.welcome",
"player", player.getName()
);
tr 会依次查询当前 locale、语言包默认 locale 和代码默认值,最终仍不存在时回显键名。语言服务不解析 PlaceholderAPI、颜色或高级字符串描述符;取得文本后应交给相应展示服务。
languages.reload();
重载按语言包分别准备新快照。成功的包提交新值,失败的包保留旧值并暂停保存,其他包仍继续处理。ReloadException.failures() 汇总失败项。
全局语言通过 Facade 设置切换:
lin.settings()
.totalLocale("en_GB")
.apply();
切换前会检查全部已绑定语言包;任一包加载失败时,不提交全局语言变化。成功后,原来的 languages、语言对象和语言字段引用继续有效。
saveAll() 保存当前活动语言对应的所有已绑定对象:
lang.message.reloaded = "新的提示文本";
languages.saveAll();
LangText 等字段是只读引用。修改引用对应的翻译时,应编辑语言文件并重载,不应给引用字段重新赋值。
save(Class<T>, locale) 会把当前活动对象写入指定 locale。由于活动对象表示当前全局语言,除非明确知道内容与目标语言一致,否则不应使用它覆盖其他 locale。
服务器数据目录中新增符合约定的文件后,可以扫描并检查社区语言:
Set<String> locales = languages.availableLocales();
languages.ensure(MainLanguage.class);
languages.ensureAllLocales();
availableLocales() 只返回磁盘中已经存在的文件。ensure(...) 检查指定语言类,ensureAllLocales() 检查所有已绑定语言类并生成差异记录,不会把缺失键写回原文件。
确认需要修复时使用运行时命令 /linlang files repair <插件名称>,也可以使用 /linlang files repair-all 修复全部已注册插件。运行时自身不属于这两个命令的修复目标。开发者也可以在明确的管理流程中调用:
int repaired = languages.repairMissingKeys();
运行时自动修复开关、YAML 注释和 JSON 差异记录的规则见配置文件的“修复缺失键”一节 ⇱。配置与语言服务共用同一项运行时授权。
讨论