正在载入

等待时间过长时请刷新页面

编写于

最近更新

语言文件

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
formatFileType.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 差异记录的规则见配置文件的“修复缺失键”一节 ⇱。配置与语言服务共用同一项运行时授权。

讨论

请登录账号