插件配置经常同时包含功能参数和展示文本。ConfigText 与 ConfigList 允许一个配置字段保存普通文本,也允许管理员把它改为语言文件引用。
它们保存语言在命名空间下的位置,当前语言变化后,再次读取同一字段即可得到新的内容,这个过程是实时的。
先定义语言对象,并在绑定时为语言包声明别名:
@LangPack(filePath = "lang")
public class MainLanguage {
public Notice notice = new Notice();
public static class Notice {
public LangText title = LangText.of("操作结果");
public LangList details = LangList.of("数据已保存");
}
}
MainLanguage lang = lin.linFile()
.language()
.bind("main", MainLanguage.class);
main 是当前插件内的语言包别名。资源目录仍由 @LangPack 决定。
配置对象把需要翻译的字段声明为 ConfigText 或 ConfigList:
@ConfigFile(name = "notice")
public class NoticeConfig {
public ConfigText heading = ConfigText.of("操作结果");
public ConfigList description = ConfigList.of("数据已保存");
}
配置文件既可以保留普通文本:
heading: "操作结果"
description:
- "数据已保存"
也可以引用前面绑定的语言包:
heading: "@lang(main:notice.title)"
description: "@lang(main:notice.details)"
还可以用多行语法显示指定默认值:
heading:
lang: "main:notice.title"
fallback: "操作结果"
最后绑定配置并读取当前值:
NoticeConfig config = lin.linFile()
.config()
.bind(NoticeConfig.class);
String title = config.heading.get();
List<String> lines = config.description.get();
必须先绑定带别名的语言包,再绑定使用该别名的配置。单行引用使用 @lang(别名:路径);对象形式使用 lang 保存相同的“别名:路径”,并可通过 fallback 声明回退文本。路径不存在或类型不匹配时,配置校验会报告对应字段。
ConfigText 对应单个字符串,ConfigList 对应整个字符串列表。普通 String 和 List<String> 不会解释语言引用。
两种类型可以出现在嵌套对象中,也可以作为 Map 的值或 List 的元素,例如:
public Map<String, ConfigText> titles = new LinkedHashMap<>();
public List<ConfigText> notices = new ArrayList<>();
ConfigText 实现了 TextSource,可以直接交给消息服务。resolve() 与 get() 都读取当前全局语言;ConfigList.get() 返回不可修改的列表快照。
LangText 与 ConfigText 不应混用:前者声明语言对象中的固定字段,后者表示配置文件选择的文本来源。
保存配置时,文件服务写回普通文本或引用定义,不会把当前翻译覆盖到配置中。
语言重载或切换后,已有 ConfigText 和 ConfigList 会在下次读取时解析新文本。配置重载可能替换这些字段以及集合元素,因此应从活动配置对象重新取得字段。
已经发送的消息或由插件自行渲染的界面不会自动变化,插件仍需在重载流程中重新读取并更新显示。LinView 会刷新由它管理的已打开界面。
插件自行读取文档时,也可以复用配置服务的解析器:
ConfigText heading = lin.linFile().config().text(rawHeading);
ConfigList description = lin.linFile().config().textList(rawDescription);
独立解析没有关联的文件位置。格式错误会抛出 IllegalArgumentException,但不会向原文件添加诊断注释。
讨论