<<<<<<< HEAD # 1.LangUtil 是什么? LangUtil 是一个 Minecraft 1.12.2 Bukkit / Spigot 多语言管理插件。 它的作用不是替代业务插件,而是给其他插件提供统一的语言 API: - 每个插件维护自己的语言文件 - 玩家可以切换自己的语言 - 不同玩家可以看到不同语言 - 修改语言文件后可以不重启服务器直接重载 - 支持物品名称、物品 lore、普通消息、占位符和颜色代码 简单理解: ```yml LangUtil = 公共语言管理器 其他插件 = 自己提供 lang 文件 玩家 = 自己选择 zh_CN / en_US 等语言 ``` ------ # 2.目录结构 ## LangUtil 自己的数据 玩家语言选择会保存到: ```yml plugins/LangUtil/player-language.yml ``` 格式示例: ```yml player-language: 550e8400-e29b-41d4-a716-446655440000: zh_CN ``` ## 其他插件的语言文件 其他插件必须把语言文件放在自己的插件目录下: ```yml plugins/OtherPlugin/lang/zh_CN.yml plugins/OtherPlugin/lang/en_US.yml ``` 注意: ```yml 语言文件不是放在 LangUtil 的 lang 目录 语言文件是放在调用 register 的插件自己的 lang 目录 ``` ------ # 3.其他插件如何注册? 其他插件需要依赖 LangUtil。 ## plugin.yml ```yml depend: - LangUtil ``` ## 插件入口 ```java 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); } } ``` 当执行: ```java LangUtil.register(this); ``` LangUtil 会读取: ```yml plugins/OtherPlugin/lang/*.yml ``` ------ # 4.语言文件怎么写? ## zh_CN.yml ```yml message: reload: "&a语言文件已重载" no-permission: "&c你没有权限使用该命令。" item: flame-sword: name: "&c烈焰长剑" lore: - "&7伤害: &c{damage}" - "&7品质: &6{quality}" - "" - "&e右键释放火焰" ``` ## en_US.yml ```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: ```yml zh_CN.yml → zh_CN en_US.yml → en_US ``` ------ # 5.玩家命令 ## 查看可用语言 ```yml /lang ``` 玩家会看到当前已经加载的语言 ID。 ## 切换语言 ```yml /lang zh_CN /lang en_US ``` 切换后会按玩家 UUID 保存。 玩家退出服务器再进入,仍然保持上次选择。 ## 重载语言文件 ```yml /lang reload ``` 修改语言文件后,不需要重启服务器,执行该命令即可重新读取所有已注册插件的语言文件。 控制台也可以执行: ```yml lang reload ``` ------ # 6.权限节点 ```yml langutil.use # 允许玩家使用 /lang 查看和切换语言 langutil.reload # 允许使用 /lang reload ``` 推荐配置: ```yml 普通玩家: langutil.use 管理员: langutil.use + langutil.reload ``` ------ # 7.API 调用 ## 获取普通消息 ```java String message = LangUtil.get(player, this, "message.reload"); ``` ## 发送普通消息 ```java LangUtil.send(player, this, "message.reload"); ``` ## 发送消息并播放音效 ```java LangUtil.send(player, this, "message.reload", Sound.LEVEL_UP); ``` ## 使用占位符 ```java Map placeholders = new HashMap(); placeholders.put("damage", "12"); placeholders.put("quality", "史诗"); String name = LangUtil.get(player, this, "item.flame-sword.name", placeholders); ``` 语言文件: ```yml item: flame-sword: name: "&c烈焰长剑" ``` 结果: ```yml 烈焰长剑 ``` ------ # 8.物品 name 和 lore 怎么做? 物品 name 是字符串,可以用: ```java LangUtil.get(player, this, "item.flame-sword.name", placeholders); ``` 物品 lore 是 List,可以用: ```java LangUtil.getList(player, this, "item.flame-sword.lore", placeholders); ``` 完整示例: ```java Map placeholders = new HashMap(); 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` 工具类。 ```java 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 getList(CommandSender sender, String path) { return LangUtil.getList(sender, plugin, path); } } ``` 插件启动时: ```java Lang.init(this); ``` 业务代码: ```java Lang.send(player, "message.reload"); ``` ------ # 10.重载机制说明 LangUtil 不会每次发送消息都读取本地 YAML。 语言文件读取时机: ```yml 插件启动 register 时 /lang reload 时 再次调用 register 时 ``` 平时调用: ```java LangUtil.get(...) LangUtil.getList(...) LangUtil.send(...) ``` 都是从内存缓存读取。 这样可以避免每次发消息都读磁盘,降低主线程压力。 ------ # 11.异常与回退规则 ## 玩家没有选择语言 默认使用: ```yml zh_CN ``` ## 玩家选择的语言文件不存在 回退: ```yml zh_CN ``` ## zh_CN 也不存在 返回 path 原文: ```java LangUtil.get(player, this, "message.not-found"); ``` 返回: ```yml message.not-found ``` ## lore 不存在 返回单行 List: ```yml - item.xxx.lore ``` ## YAML 格式错误 控制台会输出: ```yml 插件名 语言文件名 错误原因 ``` 不会因为单个语言文件错误导致服务器关闭。 ------ # 12.实战使用流程 ## 第一步:安装 LangUtil 把插件放入服务器: ```yml plugins/LangUtil-1.2.0.jar ``` 启动服务器。 ## 第二步:业务插件依赖 LangUtil ```yml depend: - LangUtil ``` ## 第三步:业务插件注册语言文件 ```java LangUtil.register(this); ``` ## 第四步:创建语言文件 ```yml plugins/OtherPlugin/lang/zh_CN.yml plugins/OtherPlugin/lang/en_US.yml ``` ## 第五步:玩家切换语言 ```yml /lang zh_CN /lang en_US ``` ## 第六步:业务插件发送消息 ```java LangUtil.send(player, this, "message.reload"); ``` ## 第七步:修改语言后重载 ```yml /lang reload ``` ------ # 13.注意事项 - 推荐始终使用带 `JavaPlugin plugin` 参数的 API。 - 不推荐使用 `LangUtil.get(String path)`,因为它无法稳定判断读取哪个插件的语言。 - 其他插件必须先调用 `LangUtil.register(this)`,否则读取不到自己的语言文件。 - 语言文件必须放在调用注册方法的插件自己的 `lang` 目录。 - 物品 lore 必须用 YAML List 格式编写。 - 修改语言文件后必须执行 `/lang reload` 才会进入缓存。 ======= # LangUtil >>>>>>> 12c7b3f43c6113b170b9e83dedf75650d51b9040