Files
LangUtil/README.md
2026-06-01 07:06:35 +08:00

7.3 KiB
Raw Blame History

<<<<<<< HEAD

1.LangUtil 是什么?

LangUtil 是一个 Minecraft 1.12.2 Bukkit / Spigot 多语言管理插件。

它的作用不是替代业务插件,而是给其他插件提供统一的语言 API

  • 每个插件维护自己的语言文件
  • 玩家可以切换自己的语言
  • 不同玩家可以看到不同语言
  • 修改语言文件后可以不重启服务器直接重载
  • 支持物品名称、物品 lore、普通消息、占位符和颜色代码

简单理解:

LangUtil = 公共语言管理器
其他插件 = 自己提供 lang 文件
玩家 = 自己选择 zh_CN / en_US 等语言

2.目录结构

LangUtil 自己的数据

玩家语言选择会保存到:

plugins/LangUtil/player-language.yml

格式示例:

player-language:
  550e8400-e29b-41d4-a716-446655440000: zh_CN

其他插件的语言文件

其他插件必须把语言文件放在自己的插件目录下:

plugins/OtherPlugin/lang/zh_CN.yml
plugins/OtherPlugin/lang/en_US.yml

注意:

语言文件不是放在 LangUtil 的 lang 目录
语言文件是放在调用 register 的插件自己的 lang 目录

3.其他插件如何注册?

其他插件需要依赖 LangUtil。

plugin.yml

depend:
  - LangUtil

插件入口

import com.io.yaohun.langutil.LangUtil;
import org.bukkit.plugin.java.JavaPlugin;

public final class OtherPlugin extends JavaPlugin {
    @Override
    public void onEnable() {
        LangUtil.register(this);
    }
}

当执行:

LangUtil.register(this);

LangUtil 会读取:

plugins/OtherPlugin/lang/*.yml

4.语言文件怎么写?

zh_CN.yml

message:
  reload: "&a语言文件已重载"
  no-permission: "&c你没有权限使用该命令。"

item:
  flame-sword:
    name: "&c烈焰长剑"
    lore:
      - "&7伤害: &c{damage}"
      - "&7品质: &6{quality}"
      - ""
      - "&e右键释放火焰"

en_US.yml

message:
  reload: "&aLanguage files reloaded"
  no-permission: "&cYou do not have permission."

item:
  flame-sword:
    name: "&cFlame Sword"
    lore:
      - "&7Damage: &c{damage}"
      - "&7Quality: &6{quality}"
      - ""
      - "&eRight-click to release fire"

文件名就是语言 ID

zh_CN.yml  →  zh_CN
en_US.yml  →  en_US

5.玩家命令

查看可用语言

/lang

玩家会看到当前已经加载的语言 ID。

切换语言

/lang zh_CN
/lang en_US

切换后会按玩家 UUID 保存。

玩家退出服务器再进入,仍然保持上次选择。

重载语言文件

/lang reload

修改语言文件后,不需要重启服务器,执行该命令即可重新读取所有已注册插件的语言文件。

控制台也可以执行:

lang reload

6.权限节点

langutil.use      # 允许玩家使用 /lang 查看和切换语言
langutil.reload   # 允许使用 /lang reload

推荐配置:

普通玩家: langutil.use
管理员: langutil.use + langutil.reload

7.API 调用

获取普通消息

String message = LangUtil.get(player, this, "message.reload");

发送普通消息

LangUtil.send(player, this, "message.reload");

发送消息并播放音效

LangUtil.send(player, this, "message.reload", Sound.LEVEL_UP);

使用占位符

Map<String, String> placeholders = new HashMap<String, String>();
placeholders.put("damage", "12");
placeholders.put("quality", "史诗");

String name = LangUtil.get(player, this, "item.flame-sword.name", placeholders);

语言文件:

item:
  flame-sword:
    name: "&c烈焰长剑"

结果:

烈焰长剑

8.物品 name 和 lore 怎么做?

物品 name 是字符串,可以用:

LangUtil.get(player, this, "item.flame-sword.name", placeholders);

物品 lore 是 List可以用

LangUtil.getList(player, this, "item.flame-sword.lore", placeholders);

完整示例:

Map<String, String> placeholders = new HashMap<String, String>();
placeholders.put("damage", "12");
placeholders.put("quality", "史诗");

ItemMeta meta = item.getItemMeta();
meta.setDisplayName(LangUtil.get(player, this, "item.flame-sword.name", placeholders));
meta.setLore(LangUtil.getList(player, this, "item.flame-sword.lore", placeholders));
item.setItemMeta(meta);

9.推荐封装方式

为了让业务代码更短,其他插件可以自己封装一个 Lang 工具类。

public final class Lang {
    private static JavaPlugin plugin;

    private Lang() {
    }

    public static void init(JavaPlugin javaPlugin) {
        plugin = javaPlugin;
        LangUtil.register(javaPlugin);
    }

    public static void send(CommandSender sender, String path) {
        LangUtil.send(sender, plugin, path);
    }

    public static String get(CommandSender sender, String path) {
        return LangUtil.get(sender, plugin, path);
    }

    public static List<String> getList(CommandSender sender, String path) {
        return LangUtil.getList(sender, plugin, path);
    }
}

插件启动时:

Lang.init(this);

业务代码:

Lang.send(player, "message.reload");

10.重载机制说明

LangUtil 不会每次发送消息都读取本地 YAML。

语言文件读取时机:

插件启动 register 时
/lang reload 时
再次调用 register 时

平时调用:

LangUtil.get(...)
LangUtil.getList(...)
LangUtil.send(...)

都是从内存缓存读取。

这样可以避免每次发消息都读磁盘,降低主线程压力。


11.异常与回退规则

玩家没有选择语言

默认使用:

zh_CN

玩家选择的语言文件不存在

回退:

zh_CN

zh_CN 也不存在

返回 path 原文:

LangUtil.get(player, this, "message.not-found");

返回:

message.not-found

lore 不存在

返回单行 List

- item.xxx.lore

YAML 格式错误

控制台会输出:

插件名
语言文件名
错误原因

不会因为单个语言文件错误导致服务器关闭。


12.实战使用流程

第一步:安装 LangUtil

把插件放入服务器:

plugins/LangUtil-1.2.0.jar

启动服务器。

第二步:业务插件依赖 LangUtil

depend:
  - LangUtil

第三步:业务插件注册语言文件

LangUtil.register(this);

第四步:创建语言文件

plugins/OtherPlugin/lang/zh_CN.yml
plugins/OtherPlugin/lang/en_US.yml

第五步:玩家切换语言

/lang zh_CN
/lang en_US

第六步:业务插件发送消息

LangUtil.send(player, this, "message.reload");

第七步:修改语言后重载

/lang reload

13.注意事项

  • 推荐始终使用带 JavaPlugin plugin 参数的 API。
  • 不推荐使用 LangUtil.get(String path),因为它无法稳定判断读取哪个插件的语言。
  • 其他插件必须先调用 LangUtil.register(this),否则读取不到自己的语言文件。
  • 语言文件必须放在调用注册方法的插件自己的 lang 目录。
  • 物品 lore 必须用 YAML List 格式编写。
  • 修改语言文件后必须执行 /lang reload 才会进入缓存。 =======

LangUtil

12c7b3f43c6113b170b9e83dedf75650d51b9040