Skip to content

I18n 多语言 ​

UltiTools 提供了一个易用的多语言 API,让你可以轻松的为你的插件添加多语言支持。

创建语言文件 ​

在 resources 文件夹中创建一个 lang 文件夹。按照你的需求放入你的插件语言文件。

json
{
  "test": "测试",
  "test2": "测试2"
}

将文件名命名为 zh.json,其中 zh 为语言代码。

语言代码可参照此表。

YAML 语言文件 ​

也支持 .yml/.yaml 字典

v6.3.0 起,模块的 lang 目录也可以使用 .yml/.yaml 而不是 .json——Language.fromYaml 会把嵌套键用点号展开,且分区节点本身不会变成字符串条目。

只提供 .yml 的模块仍可能加载不到自己的字典

每个内部模块与核心 UltiTools 插件共用同一个类加载器,所以对 jar 内 lang/<语言码>.json 的查找可能先解析到核心自己的 .json 文件,.yml 永远不会被尝试,i18n(...) 因此只会返回原始 key(issue #412)——在这个问题解决之前,请在 .yml 旁再放一份 lang/<语言码>.json(哪怕内容近似)作为临时办法。

基于来源记录的文件刷新 ​

v6.3.0 起,未改动过的语言文件会自动刷新

saveResources() 会记录每个提取出的 lang/<语言码><扩展名> 文件的 SHA-256。下次启动时,若某个 文件记录的哈希值仍与磁盘上的字节匹配,就会被替换成当前 jar 中的版本,并输出一行 INFO 日志说明该文件。

已经改动过的文件不会被这样覆盖:如果其字节已不再匹配记录的哈希,或者从未记录过哈希且字节与 jar 不同, 框架会保留你的文件不动。只有确实丢失了占位符的具体键才会改用 jar 的值,并各输出一次 WARN 日志,注明模 块、文件与键名;其余键仍保留你的措辞。由于模块字典可能使用两种占位符风格中的任意一种,两者都会被检查:

  • String.format 占位符(%s、%d,或显式的 %1$s 索引)——只要你的键与 jar 中键的占位符数 量不同(无论增多还是减少),你的键就会被覆盖。
  • {0}/{PLAYER} 风格的花括号占位符(v6.3.0 起)——通过普通的 String#replace 替换,而非 Formatter。只有当 jar 的值包含一个你的值完全没有的占位符时,你的键才会被覆盖;你自己额外添加的花 括号占位符,或对已有占位符周围文字的任何改写,都不会被触碰。这个检查刻意设计为单向的:它只标记消失 的占位符,绝不会标记你自己做的定制 (issue #524)。

要强制刷新一个已自定义的文件,删除它并重启该模块:框架会重新从 jar 中提取该文件,并记录新的基准哈希。

字面 % 必须写成 %%

语言字典的值会经过 java.util.Formatter。 裸 % 后面紧跟 s、d 或数字会被当作真正的转换符——String.format("Save 90%discount", 5) 返回 "Save 905iscount",参数缺失时则抛出 MissingFormatArgumentException。 如需输出字面上的百分号,请写成 %%。

你自己添加的花括号占位符永远不会被标记

{0}/{PLAYER} 检查只沿着"从 jar 的值到你的值"这一个方向比较——你在自己译文里加的类似 {备注} 这样的花括号,无论怎么写,都不会被误认成丢失的占位符。

注册语言代码 ​

实际使用的语言由 UltiTools 主插件配置决定

实际使用的语言取自 UltiTools 主插件配置中的 language 键,由 getLanguageCode() 读取。v6.3.0 起,构造该语言之前会先查询 supported():配置的语言码不受支持时会输出警告,并退回一个确实存在的语言,而不再静默加载空字典。

supported() 的默认实现取自模块自身的 lang/*.json 文件,因此只要把语言文件命名为 lang/<语言码>.json 就无需重写它。重写它依然有效并优先生效,适用于模块想声明支持某个语言码、却没有对应文件的少数情形。

UltiTools 需要知道你的插件支持哪些语言,因此你需要在你的插件继承了 UltiToolsPlugin 的类进行注册

一种很简便的方法就是在继承了 UltiToolsPlugin 的类添加 @I18n 并添加语言代码:

java
@I18n({"zh", "en"})

当然你也可以重写 supported() 方法,返回一个含有语言代码的 List<String> 即可:

java
@Override
public List<String> supported() {
    return Arrays.asList("zh", "en");
}

使用多语言 ​

在你的插件继承了 UltiToolsPlugin 的类中,有一个 i18n 方法,用于获取多语言字符串。

java
String test = i18n("test");

// 输出:测试

如果语言文件中不存在该字符串,将会返回该字符串本身。

java
String test3 = i18n("test3");

// 输出:test3

TIP

在仅有两种语言的情况下,你可以仅创建一个语言文件,其中的键值对的键为原文,值为译文。

贡献者

The avatar of contributor named as Ling Bao Ling Bao
The avatar of contributor named as Claude Opus 5.5 (1M context) Claude Opus 5.5 (1M context)

基于 MIT 许可发布