From f188fd7d8899e67b02315e8888eaef5119a347f7 Mon Sep 17 00:00:00 2001
From: YufiriaMazenta <2199098065@qq.com>
Date: Sat, 16 Dec 2023 16:22:01 +0800
Subject: [PATCH] =?UTF-8?q?[1.6.3-dev2]=E6=B6=88=E6=81=AF=E6=96=87?=
 =?UTF-8?q?=E6=9C=AC=E6=94=AF=E6=8C=81=E5=A4=9A=E8=AF=AD=E8=A8=80,?=
 =?UTF-8?q?=E6=96=B0=E5=A2=9E=E7=B9=81=E4=BD=93=E4=B8=AD=E6=96=87,?=
 =?UTF-8?q?=E8=8B=B1=E6=96=87?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 build.gradle.kts                              |   4 +-
 .../craftorithm/Craftorithm.java              |   2 +-
 .../arcenciel/ArcencielDispatcher.java        |   8 +-
 .../arcenciel/block/StringArcencielBlock.java |   3 +-
 .../arcenciel/token/TokenConsole.java         |   4 +-
 .../arcenciel/token/TokenHasPerm.java         |   2 +-
 .../arcenciel/token/TokenPapi.java            |   8 +-
 .../arcenciel/token/TokenRunCmd.java          |   4 +-
 .../craftorithm/cmd/PluginCommand.java        |   6 +-
 .../cmd/sub/AbstractSubCommand.java           |   8 +-
 .../cmd/sub/CreateRecipeCommand.java          |   8 +-
 .../cmd/sub/DisableRecipeCommand.java         |   6 +-
 .../cmd/sub/RecipeListCommand.java            |   2 +-
 .../craftorithm/cmd/sub/ReloadCommand.java    |   4 +-
 .../cmd/sub/RemoveRecipeCommand.java          |   4 +-
 .../craftorithm/cmd/sub/RunArcencielCmd.java  |   2 +-
 .../craftorithm/cmd/sub/VersionCommand.java   |   2 +-
 .../cmd/sub/item/ItemGiveCommand.java         |   6 +-
 .../cmd/sub/item/ItemSaveCommand.java         |   4 +-
 .../craftorithm/config/Languages.java         | 168 +++++++++---------
 .../craftorithm/config/PluginConfigs.java     |   8 +-
 .../item/impl/CraftorithmItemProvider.java    |  16 +-
 .../menu/creator/AnvilRecipeCreator.java      |  21 +--
 .../menu/creator/CookingRecipeCreator.java    |  29 +--
 .../menu/creator/CraftingRecipeCreator.java   |   6 +-
 .../menu/creator/PotionMixCreator.java        |   8 +-
 .../menu/creator/RecipeCreator.java           |   8 +-
 .../menu/creator/SmithingRecipeCreator.java   |  10 +-
 .../creator/StoneCuttingRecipeCreator.java    |   8 +-
 .../menu/creator/UnlockableRecipeCreator.java |   4 +-
 .../menu/display/RecipeDisplayMenuHolder.java |   4 +-
 .../display/RecipeGroupListMenuHolder.java    |  10 +-
 .../menu/display/RecipeListMenuHolder.java    |  10 +-
 .../craftorithm/recipe/RecipeManager.java     |  16 +-
 .../craftorithm/util/ItemUtils.java           |   6 +-
 .../craftorithm/util/LangUtil.java            |  23 ++-
 .../craftorithm/util/PluginHookUtil.java      |  30 ++--
 .../craftorithm/util/UpdateUtil.java          |   2 +-
 src/main/resources/lang/en_us.yml             | 115 ++++++++++++
 .../resources/{lang.yml => lang/zh_cn.yml}    |   0
 src/main/resources/lang/zh_tw.yml             | 115 ++++++++++++
 41 files changed, 467 insertions(+), 237 deletions(-)
 create mode 100644 src/main/resources/lang/en_us.yml
 rename src/main/resources/{lang.yml => lang/zh_cn.yml} (100%)
 create mode 100644 src/main/resources/lang/zh_tw.yml

diff --git a/build.gradle.kts b/build.gradle.kts
index 88fdc6c6..5fb7a96b 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -1,5 +1,5 @@
 import java.text.SimpleDateFormat
-version = "1.6.3-dev1"
+version = "1.6.3-dev2"
 
 plugins {
     `java-library`
@@ -40,7 +40,7 @@ dependencies {
     compileOnly("io.lumine:Mythic-Dist:5.3.5")
     compileOnly("io.lumine:MythicLib-dist:1.6.2-SNAPSHOT")
     compileOnly("net.Indyuce:MMOItems-API:6.9.5-SNAPSHOT")
-    implementation("com.crypticlib:CrypticLib:0.7.2")
+    implementation("com.crypticlib:CrypticLib:0.8.8")
 }
 
 group = "com.github.yufiriamazenta"
diff --git a/src/main/java/com/github/yufiriamazenta/craftorithm/Craftorithm.java b/src/main/java/com/github/yufiriamazenta/craftorithm/Craftorithm.java
index 6ce36956..89355789 100644
--- a/src/main/java/com/github/yufiriamazenta/craftorithm/Craftorithm.java
+++ b/src/main/java/com/github/yufiriamazenta/craftorithm/Craftorithm.java
@@ -35,7 +35,7 @@ public void enable() {
         initArcenciel();
         loadBStat();
         
-        LangUtil.info(Languages.LOAD_FINISH.value());
+        LangUtil.info(Languages.LOAD_FINISH);
         UpdateUtil.pullUpdateCheckRequest(Bukkit.getConsoleSender());
     }
 
diff --git a/src/main/java/com/github/yufiriamazenta/craftorithm/arcenciel/ArcencielDispatcher.java b/src/main/java/com/github/yufiriamazenta/craftorithm/arcenciel/ArcencielDispatcher.java
index 6b922daf..13abea91 100644
--- a/src/main/java/com/github/yufiriamazenta/craftorithm/arcenciel/ArcencielDispatcher.java
+++ b/src/main/java/com/github/yufiriamazenta/craftorithm/arcenciel/ArcencielDispatcher.java
@@ -7,7 +7,7 @@
 import com.github.yufiriamazenta.craftorithm.arcenciel.obj.ReturnObj;
 import com.github.yufiriamazenta.craftorithm.arcenciel.token.*;
 import com.github.yufiriamazenta.craftorithm.util.PluginHookUtil;
-import crypticlib.config.yaml.YamlConfigWrapper;
+import crypticlib.config.ConfigWrapper;
 import org.bukkit.entity.Player;
 
 import java.util.List;
@@ -15,7 +15,7 @@
 public enum ArcencielDispatcher implements IArcencielDispatcher {
 
     INSTANCE;
-    private YamlConfigWrapper functionFile;
+    private ConfigWrapper functionFile;
 
     ArcencielDispatcher() {
         regDefScriptKeyword();
@@ -65,7 +65,7 @@ private void regDefScriptKeyword() {
         }
     }
 
-    public YamlConfigWrapper functionFile() {
+    public ConfigWrapper functionFile() {
         return functionFile;
     }
 
@@ -75,7 +75,7 @@ public List<String> getFunc(String funcName) {
 
     public void loadFuncFile() {
         if (functionFile == null)
-            functionFile = new YamlConfigWrapper(Craftorithm.instance(), "function.yml");
+            functionFile = new ConfigWrapper(Craftorithm.instance(), "function.yml");
     }
 
 }
diff --git a/src/main/java/com/github/yufiriamazenta/craftorithm/arcenciel/block/StringArcencielBlock.java b/src/main/java/com/github/yufiriamazenta/craftorithm/arcenciel/block/StringArcencielBlock.java
index c59e4bf8..260cb424 100644
--- a/src/main/java/com/github/yufiriamazenta/craftorithm/arcenciel/block/StringArcencielBlock.java
+++ b/src/main/java/com/github/yufiriamazenta/craftorithm/arcenciel/block/StringArcencielBlock.java
@@ -7,6 +7,7 @@
 import com.github.yufiriamazenta.craftorithm.config.Languages;
 import com.github.yufiriamazenta.craftorithm.util.CollectionsUtil;
 import com.github.yufiriamazenta.craftorithm.util.LangUtil;
+import crypticlib.chat.MessageSender;
 import org.bukkit.entity.Player;
 
 import java.util.ArrayList;
@@ -39,7 +40,7 @@ public ReturnObj<Object> exec(Player player) {
         if (keyword == null) {
             List<String> func = ArcencielDispatcher.INSTANCE.getFunc(keywordStr);
             if (func.isEmpty()) {
-                LangUtil.sendLang(player, Languages.ARCENCIEL_UNKNOWN_TOKEN.value(), CollectionsUtil.newStringHashMap("<token>", keywordStr));
+                LangUtil.sendLang(player, Languages.ARCENCIEL_UNKNOWN_TOKEN, CollectionsUtil.newStringHashMap("<token>", keywordStr));
                 return new ReturnObj<>(ArcencielSignal.CONTINUE);
             } else {
                 return ArcencielDispatcher.INSTANCE.dispatchArcencielFunc(player, func);
diff --git a/src/main/java/com/github/yufiriamazenta/craftorithm/arcenciel/token/TokenConsole.java b/src/main/java/com/github/yufiriamazenta/craftorithm/arcenciel/token/TokenConsole.java
index 3bf832e5..3fbee399 100644
--- a/src/main/java/com/github/yufiriamazenta/craftorithm/arcenciel/token/TokenConsole.java
+++ b/src/main/java/com/github/yufiriamazenta/craftorithm/arcenciel/token/TokenConsole.java
@@ -2,7 +2,7 @@
 
 import com.github.yufiriamazenta.craftorithm.arcenciel.obj.ReturnObj;
 import com.github.yufiriamazenta.craftorithm.util.CollectionsUtil;
-import crypticlib.util.TextUtil;
+import crypticlib.chat.TextProcessor;
 import org.bukkit.Bukkit;
 import org.bukkit.entity.Player;
 
@@ -18,7 +18,7 @@ protected TokenConsole() {
 
     @Override
     public ReturnObj<Boolean> exec(Player player, List<String> args) {
-        String command = TextUtil.placeholder(player, CollectionsUtil.list2ArcencielBlock(args));
+        String command = TextProcessor.placeholder(player, CollectionsUtil.list2ArcencielBlock(args));
         return new ReturnObj<>(Bukkit.dispatchCommand(Bukkit.getConsoleSender(), command));
     }
 
diff --git a/src/main/java/com/github/yufiriamazenta/craftorithm/arcenciel/token/TokenHasPerm.java b/src/main/java/com/github/yufiriamazenta/craftorithm/arcenciel/token/TokenHasPerm.java
index dd6cdb61..b32a1ac8 100644
--- a/src/main/java/com/github/yufiriamazenta/craftorithm/arcenciel/token/TokenHasPerm.java
+++ b/src/main/java/com/github/yufiriamazenta/craftorithm/arcenciel/token/TokenHasPerm.java
@@ -19,7 +19,7 @@ protected TokenHasPerm() {
     @Override
     public ReturnObj<Boolean> exec(Player player, List<String> args) {
         if (args.isEmpty()) {
-            LangUtil.sendLang(player, Languages.ARCENCIEL_NOT_ENOUGH_PARAM.value(), CollectionsUtil.newStringHashMap("<statement>", "if"));
+            LangUtil.sendLang(player, Languages.ARCENCIEL_NOT_ENOUGH_PARAM, CollectionsUtil.newStringHashMap("<statement>", "if"));
             return new ReturnObj<>(false);
         }
         return new ReturnObj<>(player.hasPermission(args.get(0)));
diff --git a/src/main/java/com/github/yufiriamazenta/craftorithm/arcenciel/token/TokenPapi.java b/src/main/java/com/github/yufiriamazenta/craftorithm/arcenciel/token/TokenPapi.java
index a5031044..ef0d1b5f 100644
--- a/src/main/java/com/github/yufiriamazenta/craftorithm/arcenciel/token/TokenPapi.java
+++ b/src/main/java/com/github/yufiriamazenta/craftorithm/arcenciel/token/TokenPapi.java
@@ -3,7 +3,7 @@
 import com.github.yufiriamazenta.craftorithm.arcenciel.obj.ReturnObj;
 import com.github.yufiriamazenta.craftorithm.util.CollectionsUtil;
 import com.github.yufiriamazenta.craftorithm.util.ScriptValueUtil;
-import crypticlib.util.TextUtil;
+import crypticlib.chat.TextProcessor;
 import org.bukkit.entity.Player;
 
 import java.util.List;
@@ -21,14 +21,14 @@ public ReturnObj<Boolean> exec(Player player, List<String> args) {
         String papiStr;
         if (args.size() > 2) {
             papiStr = args.get(0);
-            papiStr = TextUtil.placeholder(player, papiStr);
+            papiStr = TextProcessor.placeholder(player, papiStr);
             String operator = args.get(1);
             String valueStr = CollectionsUtil.list2ArcencielBlock(args.subList(2, args.size()));
             return new ReturnObj<>(ScriptValueUtil.compare(papiStr, valueStr, operator));
         } else {
             papiStr = CollectionsUtil.list2ArcencielBlock(args);
-            papiStr = TextUtil.placeholder(player, papiStr);
-            return new ReturnObj<>(Boolean.parseBoolean(TextUtil.placeholder(player, papiStr)));
+            papiStr = TextProcessor.placeholder(player, papiStr);
+            return new ReturnObj<>(Boolean.parseBoolean(TextProcessor.placeholder(player, papiStr)));
         }
     }
 
diff --git a/src/main/java/com/github/yufiriamazenta/craftorithm/arcenciel/token/TokenRunCmd.java b/src/main/java/com/github/yufiriamazenta/craftorithm/arcenciel/token/TokenRunCmd.java
index b545555e..1ca400ff 100644
--- a/src/main/java/com/github/yufiriamazenta/craftorithm/arcenciel/token/TokenRunCmd.java
+++ b/src/main/java/com/github/yufiriamazenta/craftorithm/arcenciel/token/TokenRunCmd.java
@@ -2,7 +2,7 @@
 
 import com.github.yufiriamazenta.craftorithm.arcenciel.obj.ReturnObj;
 import com.github.yufiriamazenta.craftorithm.util.CollectionsUtil;
-import crypticlib.util.TextUtil;
+import crypticlib.chat.TextProcessor;
 import org.bukkit.Bukkit;
 import org.bukkit.entity.Player;
 
@@ -18,7 +18,7 @@ protected TokenRunCmd() {
 
     @Override
     public ReturnObj<Boolean> exec(Player player, List<String> args) {
-        String command = TextUtil.placeholder(player, CollectionsUtil.list2ArcencielBlock(args));
+        String command = TextProcessor.placeholder(player, CollectionsUtil.list2ArcencielBlock(args));
         return new ReturnObj<>(Bukkit.dispatchCommand(player, command));
     }
 }
diff --git a/src/main/java/com/github/yufiriamazenta/craftorithm/cmd/PluginCommand.java b/src/main/java/com/github/yufiriamazenta/craftorithm/cmd/PluginCommand.java
index 1f21a0a3..cca02a26 100644
--- a/src/main/java/com/github/yufiriamazenta/craftorithm/cmd/PluginCommand.java
+++ b/src/main/java/com/github/yufiriamazenta/craftorithm/cmd/PluginCommand.java
@@ -29,7 +29,7 @@ public class PluginCommand extends RootCmdExecutor {
     public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, String[] args) {
         List<String> argList = Arrays.asList(args);
         if (argList.isEmpty()) {
-            LangUtil.sendLang(sender, Languages.COMMAND_NOT_ENOUGH_PARAM.value(), CollectionsUtil.newStringHashMap("<number>", String.valueOf(1)));
+            LangUtil.sendLang(sender, Languages.COMMAND_NOT_ENOUGH_PARAM, CollectionsUtil.newStringHashMap("<number>", String.valueOf(1)));
             return true;
         }
         ISubcmdExecutor subCommand = subcommands().get(argList.get(0));
@@ -37,14 +37,14 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command
             String perm = subCommand.permission();
             if (perm != null) {
                 if (!sender.hasPermission(perm)) {
-                    LangUtil.sendLang(sender, Languages.COMMAND_NO_PERM.value());
+                    LangUtil.sendLang(sender, Languages.COMMAND_NO_PERM);
                     return true;
                 }
             }
             return subCommand.onCommand(sender, argList.subList(1, argList.size()));
         }
         else {
-            LangUtil.sendLang(sender, Languages.COMMAND_UNDEFINED_SUBCMD.value());
+            LangUtil.sendLang(sender, Languages.COMMAND_UNDEFINED_SUBCMD);
             return true;
         }
     }
diff --git a/src/main/java/com/github/yufiriamazenta/craftorithm/cmd/sub/AbstractSubCommand.java b/src/main/java/com/github/yufiriamazenta/craftorithm/cmd/sub/AbstractSubCommand.java
index ae3cdbb8..5c1197c1 100644
--- a/src/main/java/com/github/yufiriamazenta/craftorithm/cmd/sub/AbstractSubCommand.java
+++ b/src/main/java/com/github/yufiriamazenta/craftorithm/cmd/sub/AbstractSubCommand.java
@@ -24,12 +24,12 @@ protected AbstractSubCommand(String command) {
     public boolean onCommand(CommandSender sender, List<String> args) {
         ISubcmdExecutor subCommand = subcommands().get(args.get(0));
         if (subCommand == null) {
-            LangUtil.sendLang(sender, Languages.COMMAND_UNDEFINED_SUBCMD.value());
+            LangUtil.sendLang(sender, Languages.COMMAND_UNDEFINED_SUBCMD);
         } else {
             String perm = subCommand.permission();
             if (perm != null) {
                 if (!sender.hasPermission(perm)) {
-                    LangUtil.sendLang(sender, Languages.COMMAND_NO_PERM.value());
+                    LangUtil.sendLang(sender, Languages.COMMAND_NO_PERM);
                     return true;
                 }
             }
@@ -43,14 +43,14 @@ public void sendNotEnoughCmdParamMsg(CommandSender sender, int paramNum) {
     }
 
     public void sendNotEnoughCmdParamMsg(CommandSender sender, String paramStr) {
-        LangUtil.sendLang(sender, Languages.COMMAND_NOT_ENOUGH_PARAM.value(), CollectionsUtil.newStringHashMap("<number>", paramStr));
+        LangUtil.sendLang(sender, Languages.COMMAND_NOT_ENOUGH_PARAM, CollectionsUtil.newStringHashMap("<number>", paramStr));
     }
 
     public boolean checkSenderIsPlayer(CommandSender sender) {
         if (sender instanceof Player) {
             return true;
         } else {
-            LangUtil.sendLang(sender, Languages.COMMAND_PLAYER_ONLY.value());
+            LangUtil.sendLang(sender, Languages.COMMAND_PLAYER_ONLY);
             return false;
         }
     }
diff --git a/src/main/java/com/github/yufiriamazenta/craftorithm/cmd/sub/CreateRecipeCommand.java b/src/main/java/com/github/yufiriamazenta/craftorithm/cmd/sub/CreateRecipeCommand.java
index 326ebb59..2a952d6d 100644
--- a/src/main/java/com/github/yufiriamazenta/craftorithm/cmd/sub/CreateRecipeCommand.java
+++ b/src/main/java/com/github/yufiriamazenta/craftorithm/cmd/sub/CreateRecipeCommand.java
@@ -50,17 +50,17 @@ public boolean onCommand(CommandSender sender, List<String> args) {
         }
         String recipeTypeStr = args.get(0).toLowerCase(Locale.ROOT);
         if (!recipeTypeList.contains(recipeTypeStr)) {
-            LangUtil.sendLang(sender, Languages.COMMAND_CREATE_UNSUPPORTED_RECIPE_TYPE.value());
+            LangUtil.sendLang(sender, Languages.COMMAND_CREATE_UNSUPPORTED_RECIPE_TYPE);
             return true;
         }
         String recipeName = args.get(1);
         Matcher matcher = recipeNamePattern.matcher(recipeName);
         if (!matcher.matches()) {
-            LangUtil.sendLang(sender, Languages.COMMAND_CREATE_UNSUPPORTED_RECIPE_NAME.value());
+            LangUtil.sendLang(sender, Languages.COMMAND_CREATE_UNSUPPORTED_RECIPE_NAME);
             return true;
         }
         if (RecipeManager.INSTANCE.hasCraftorithmRecipe(recipeName)) {
-            LangUtil.sendLang(sender, Languages.COMMAND_CREATE_NAME_USED.value());
+            LangUtil.sendLang(sender, Languages.COMMAND_CREATE_NAME_USED);
             return true;
         }
         RecipeType recipeType = RecipeType.valueOf(recipeTypeStr.toUpperCase(Locale.ROOT));
@@ -86,7 +86,7 @@ public boolean onCommand(CommandSender sender, List<String> args) {
                 new AnvilRecipeCreator(player, recipeName).openMenu();
                 break;
             default:
-                LangUtil.sendLang(sender, Languages.COMMAND_CREATE_UNSUPPORTED_RECIPE_TYPE.value());
+                LangUtil.sendLang(sender, Languages.COMMAND_CREATE_UNSUPPORTED_RECIPE_TYPE);
                 break;
         }
         return true;
diff --git a/src/main/java/com/github/yufiriamazenta/craftorithm/cmd/sub/DisableRecipeCommand.java b/src/main/java/com/github/yufiriamazenta/craftorithm/cmd/sub/DisableRecipeCommand.java
index b636646e..8aa04322 100644
--- a/src/main/java/com/github/yufiriamazenta/craftorithm/cmd/sub/DisableRecipeCommand.java
+++ b/src/main/java/com/github/yufiriamazenta/craftorithm/cmd/sub/DisableRecipeCommand.java
@@ -26,15 +26,15 @@ public boolean onCommand(CommandSender sender, List<String> args) {
         }
         NamespacedKey removeRecipeKey = NamespacedKey.fromString(args.get(0));
         if (!RecipeManager.INSTANCE.serverRecipesCache().containsKey(removeRecipeKey)) {
-            LangUtil.sendLang(sender, Languages.COMMAND_DISABLE_NOT_EXIST.value());
+            LangUtil.sendLang(sender, Languages.COMMAND_DISABLE_NOT_EXIST);
             return true;
         }
         List<NamespacedKey> removeRecipeKeys = Collections.singletonList(removeRecipeKey);
         if (RecipeManager.INSTANCE.disableOtherPluginsRecipe(removeRecipeKeys, true)) {
-            LangUtil.sendLang(sender, Languages.COMMAND_DISABLE_SUCCESS.value());
+            LangUtil.sendLang(sender, Languages.COMMAND_DISABLE_SUCCESS);
         }
         else
-            LangUtil.sendLang(sender, Languages.COMMAND_DISABLE_FAILED.value());
+            LangUtil.sendLang(sender, Languages.COMMAND_DISABLE_FAILED);
         return true;
     }
 
diff --git a/src/main/java/com/github/yufiriamazenta/craftorithm/cmd/sub/RecipeListCommand.java b/src/main/java/com/github/yufiriamazenta/craftorithm/cmd/sub/RecipeListCommand.java
index ee9e5417..68784d62 100644
--- a/src/main/java/com/github/yufiriamazenta/craftorithm/cmd/sub/RecipeListCommand.java
+++ b/src/main/java/com/github/yufiriamazenta/craftorithm/cmd/sub/RecipeListCommand.java
@@ -26,7 +26,7 @@ private RecipeListCommand() {
     @Override
     public boolean onCommand(CommandSender sender, List<String> args) {
         if (CrypticLib.minecraftVersion() < 11600) {
-            LangUtil.sendLang(sender, Languages.COMMAND_LIST_UNSUPPORTED_VERSION.value());
+            LangUtil.sendLang(sender, Languages.COMMAND_LIST_UNSUPPORTED_VERSION);
             return true;
         }
         if (!checkSenderIsPlayer(sender)) {
diff --git a/src/main/java/com/github/yufiriamazenta/craftorithm/cmd/sub/ReloadCommand.java b/src/main/java/com/github/yufiriamazenta/craftorithm/cmd/sub/ReloadCommand.java
index ed36be2e..b08162d2 100644
--- a/src/main/java/com/github/yufiriamazenta/craftorithm/cmd/sub/ReloadCommand.java
+++ b/src/main/java/com/github/yufiriamazenta/craftorithm/cmd/sub/ReloadCommand.java
@@ -24,10 +24,10 @@ private ReloadCommand() {
     public boolean onCommand(CommandSender sender, List<String> args) {
         try {
             reloadPlugin();
-            LangUtil.sendLang(sender, Languages.COMMAND_RELOAD_SUCCESS.value());
+            LangUtil.sendLang(sender, Languages.COMMAND_RELOAD_SUCCESS);
         } catch (Exception e) {
             e.printStackTrace();
-            LangUtil.sendLang(sender, Languages.COMMAND_RELOAD_EXCEPTION.value());
+            LangUtil.sendLang(sender, Languages.COMMAND_RELOAD_EXCEPTION);
         }
         return true;
     }
diff --git a/src/main/java/com/github/yufiriamazenta/craftorithm/cmd/sub/RemoveRecipeCommand.java b/src/main/java/com/github/yufiriamazenta/craftorithm/cmd/sub/RemoveRecipeCommand.java
index 211cfa39..360b53f7 100644
--- a/src/main/java/com/github/yufiriamazenta/craftorithm/cmd/sub/RemoveRecipeCommand.java
+++ b/src/main/java/com/github/yufiriamazenta/craftorithm/cmd/sub/RemoveRecipeCommand.java
@@ -30,10 +30,10 @@ public boolean onCommand(CommandSender sender, List<String> args) {
         }
 
         if (RecipeManager.INSTANCE.removeCraftorithmRecipe(args.get(0), true)) {
-            LangUtil.sendLang(sender, Languages.COMMAND_REMOVE_SUCCESS.value());
+            LangUtil.sendLang(sender, Languages.COMMAND_REMOVE_SUCCESS);
         }
         else
-            LangUtil.sendLang(sender, Languages.COMMAND_REMOVE_NOT_EXIST.value());
+            LangUtil.sendLang(sender, Languages.COMMAND_REMOVE_NOT_EXIST);
         return true;
     }
 
diff --git a/src/main/java/com/github/yufiriamazenta/craftorithm/cmd/sub/RunArcencielCmd.java b/src/main/java/com/github/yufiriamazenta/craftorithm/cmd/sub/RunArcencielCmd.java
index 62d1530b..f6cde4a5 100644
--- a/src/main/java/com/github/yufiriamazenta/craftorithm/cmd/sub/RunArcencielCmd.java
+++ b/src/main/java/com/github/yufiriamazenta/craftorithm/cmd/sub/RunArcencielCmd.java
@@ -33,7 +33,7 @@ public boolean onCommand(CommandSender sender, List<String> args) {
         }
         ArcencielDispatcher.INSTANCE.dispatchArcencielBlock((Player) sender, arcencielBlock.toString());
         long execTime = System.currentTimeMillis() - startTime;
-        LangUtil.sendLang(sender, Languages.COMMAND_RUN_ARCENCIEL_SUCCESS.value(), CollectionsUtil.newStringHashMap("<time>", String.valueOf(execTime)));
+        LangUtil.sendLang(sender, Languages.COMMAND_RUN_ARCENCIEL_SUCCESS, CollectionsUtil.newStringHashMap("<time>", String.valueOf(execTime)));
         return true;
     }
 }
diff --git a/src/main/java/com/github/yufiriamazenta/craftorithm/cmd/sub/VersionCommand.java b/src/main/java/com/github/yufiriamazenta/craftorithm/cmd/sub/VersionCommand.java
index b3287b3b..d0dc36d8 100644
--- a/src/main/java/com/github/yufiriamazenta/craftorithm/cmd/sub/VersionCommand.java
+++ b/src/main/java/com/github/yufiriamazenta/craftorithm/cmd/sub/VersionCommand.java
@@ -17,7 +17,7 @@ private VersionCommand() {
 
     @Override
     public boolean onCommand(CommandSender sender, List<String> args) {
-        LangUtil.sendLang(sender, Languages.COMMAND_VERSION.value());
+        LangUtil.sendLang(sender, Languages.COMMAND_VERSION);
         return true;
     }
 }
diff --git a/src/main/java/com/github/yufiriamazenta/craftorithm/cmd/sub/item/ItemGiveCommand.java b/src/main/java/com/github/yufiriamazenta/craftorithm/cmd/sub/item/ItemGiveCommand.java
index 3a5e24da..992b099b 100644
--- a/src/main/java/com/github/yufiriamazenta/craftorithm/cmd/sub/item/ItemGiveCommand.java
+++ b/src/main/java/com/github/yufiriamazenta/craftorithm/cmd/sub/item/ItemGiveCommand.java
@@ -33,7 +33,7 @@ public boolean onCommand(CommandSender sender, List<String> args) {
         if (args.size() >= 2) {
             player = Bukkit.getPlayer(args.get(1));
             if (player == null) {
-                LangUtil.sendLang(sender, Languages.COMMAND_ITEM_GIVE_PLAYER_OFFLINE.value());
+                LangUtil.sendLang(sender, Languages.COMMAND_ITEM_GIVE_PLAYER_OFFLINE);
                 return true;
             }
         } else {
@@ -46,12 +46,12 @@ public boolean onCommand(CommandSender sender, List<String> args) {
 
         ItemStack itemStack = CraftorithmItemProvider.INSTANCE.getItem(args.get(0));
         if (itemStack == null) {
-            LangUtil.sendLang(sender, Languages.COMMAND_ITEM_GIVE_NOT_EXIST_ITEM.value(), CollectionsUtil.newStringHashMap("<item_name>", args.get(0)));
+            LangUtil.sendLang(sender, Languages.COMMAND_ITEM_GIVE_NOT_EXIST_ITEM, CollectionsUtil.newStringHashMap("<item_name>", args.get(0)));
             return true;
         }
 
         player.getInventory().addItem(itemStack);
-        LangUtil.sendLang(sender, Languages.COMMAND_ITEM_GIVE_SUCCESS.value());
+        LangUtil.sendLang(sender, Languages.COMMAND_ITEM_GIVE_SUCCESS);
         return true;
     }
 
diff --git a/src/main/java/com/github/yufiriamazenta/craftorithm/cmd/sub/item/ItemSaveCommand.java b/src/main/java/com/github/yufiriamazenta/craftorithm/cmd/sub/item/ItemSaveCommand.java
index ee22e6e0..19dd6293 100644
--- a/src/main/java/com/github/yufiriamazenta/craftorithm/cmd/sub/item/ItemSaveCommand.java
+++ b/src/main/java/com/github/yufiriamazenta/craftorithm/cmd/sub/item/ItemSaveCommand.java
@@ -33,12 +33,12 @@ public boolean onCommand(CommandSender sender, List<String> args) {
 
         ItemStack item = ((Player) sender).getInventory().getItemInMainHand();
         if (item.getType().equals(Material.AIR)) {
-            LangUtil.sendLang(sender, Languages.COMMAND_ITEM_SAVE_FAILED_SAVE_AIR.value());
+            LangUtil.sendLang(sender, Languages.COMMAND_ITEM_SAVE_FAILED_SAVE_AIR);
             return true;
         }
 
         CraftorithmItemProvider.INSTANCE.regCraftorithmItem(args.get(0), args.get(1), item.clone());
-        LangUtil.sendLang(sender, Languages.COMMAND_ITEM_SAVE_SUCCESS.value());
+        LangUtil.sendLang(sender, Languages.COMMAND_ITEM_SAVE_SUCCESS);
         return true;
     }
 
diff --git a/src/main/java/com/github/yufiriamazenta/craftorithm/config/Languages.java b/src/main/java/com/github/yufiriamazenta/craftorithm/config/Languages.java
index db3f17be..0667eec0 100644
--- a/src/main/java/com/github/yufiriamazenta/craftorithm/config/Languages.java
+++ b/src/main/java/com/github/yufiriamazenta/craftorithm/config/Languages.java
@@ -1,96 +1,96 @@
 package com.github.yufiriamazenta.craftorithm.config;
 
-import crypticlib.config.yaml.YamlConfigHandler;
-import crypticlib.config.yaml.entry.StringConfigEntry;
-import crypticlib.config.yaml.entry.StringListConfigEntry;
+import crypticlib.chat.LangConfigHandler;
+import crypticlib.chat.entry.StringLangConfigEntry;
+import crypticlib.config.entry.StringListConfigEntry;
 
 import java.util.Collections;
 
-@YamlConfigHandler(path = "lang.yml")
+@LangConfigHandler(langFileFolder = "lang")
 public class Languages {
 
-    public static final StringConfigEntry PREFIX = new StringConfigEntry("prefix", "&8[&3Craftorithm&8]");
-    public static final StringConfigEntry UNSUPPORTED_VERSION = new StringConfigEntry("unsupported_version", "<prefix> 不支持的版本");
-    public static final StringConfigEntry NEW_VERSION = new StringConfigEntry("new_version", "<prefix> &a检测到有新版本<new_version>, 请及时更新到新版本");
-    public static final StringConfigEntry COMMAND_NO_PERM = new StringConfigEntry("command.no_perm", "<prefix> &c你没有使用此命令的权限");
-    public static final StringConfigEntry COMMAND_PLAYER_ONLY = new StringConfigEntry("command.player_only", "<prefix> &c只有玩家才能执行此命令");
-    public static final StringConfigEntry COMMAND_NOT_ENOUGH_PARAM = new StringConfigEntry("command.not_enough_param", "<prefix> &c命令缺少参数,缺少<number>个参数");
-    public static final StringConfigEntry COMMAND_UNDEFINED_SUBCMD = new StringConfigEntry("command.undefined_subcmd", "<prefix> &c未定义的子命令");
-    public static final StringConfigEntry COMMAND_ITEM_SAVE_SUCCESS = new StringConfigEntry("command.item.save.success", "<prefix> &a物品保存成功");
-    public static final StringConfigEntry COMMAND_ITEM_SAVE_FAILED_SAVE_AIR = new StringConfigEntry("command.item.save.failed_save_air", "<prefix> &c物品保存失败,原因:不能保存不存在的物品");
-    public static final StringConfigEntry COMMAND_ITEM_GIVE_SUCCESS = new StringConfigEntry("command.item.give.success", "<prefix> &a物品获取成功");
-    public static final StringConfigEntry COMMAND_ITEM_GIVE_NOT_EXIST_ITEM = new StringConfigEntry("command.item.give.not_exist_item", "<prefix> &c不存在物品 <item_name>");
-    public static final StringConfigEntry COMMAND_ITEM_GIVE_PLAYER_OFFLINE = new StringConfigEntry("command.item.give.player_offline", "<prefix> &c该玩家不在线或不存在");
-    public static final StringConfigEntry COMMAND_RELOAD_SUCCESS = new StringConfigEntry("command.reload.success", "<prefix> &a插件重载成功");
-    public static final StringConfigEntry COMMAND_RELOAD_EXCEPTION = new StringConfigEntry("command.reload.exception", "<prefix> &c插件重载过程中发生错误,请查看控制台");
-    public static final StringConfigEntry COMMAND_REMOVE_SUCCESS = new StringConfigEntry("command.remove.success", "<prefix> &a配方删除成功");
-    public static final StringConfigEntry COMMAND_REMOVE_NOT_EXIST = new StringConfigEntry("command.remove.not_exist", "<prefix> &c配方不存在");
-    public static final StringConfigEntry COMMAND_DISABLE_SUCCESS = new StringConfigEntry("command.disable.success", "<prefix> &c禁用配方成功");
-    public static final StringConfigEntry COMMAND_DISABLE_NOT_EXIST = new StringConfigEntry("command.disable.not_exist", "<prefix> &c配方不存在或已经被禁用");
-    public static final StringConfigEntry COMMAND_DISABLE_FAILED = new StringConfigEntry("command.disable.failed", "<prefix> &c配方禁用失败,可能已被禁用或不存在");
-    public static final StringConfigEntry COMMAND_VERSION = new StringConfigEntry("command.version", "<prefix> &a插件版本:<version>");
-    public static final StringConfigEntry COMMAND_CREATE_UNSUPPORTED_RECIPE_TYPE = new StringConfigEntry("command.create.unsupported_recipe_type", "<prefix> &c不支持的配方类型");
-    public static final StringConfigEntry COMMAND_CREATE_UNSUPPORTED_RECIPE_NAME = new StringConfigEntry("command.create.unsupported_recipe_name", "<prefix> &c不支持的配方名字,只能使用[a-z0-9/._-]+允许的内容");
-    public static final StringConfigEntry COMMAND_CREATE_NAME_USED = new StringConfigEntry("command.create.name_used", "<prefix> &c配方ID已经被使用");
-    public static final StringConfigEntry COMMAND_CREATE_NULL_RESULT = new StringConfigEntry("command.create.null_result", "<prefix> &c配方结果不允许为空!");
-    public static final StringConfigEntry COMMAND_CREATE_NULL_SOURCE = new StringConfigEntry("command.create.null_source", "<prefix> &c配方原料不允许为空!");
-    public static final StringConfigEntry COMMAND_CREATE_SUCCESS = new StringConfigEntry("command.create.success", "<prefix> &a<recipe_type>类型配方<recipe_name>创建成功");
-    public static final StringConfigEntry COMMAND_RUN_ARCENCIEL_SUCCESS = new StringConfigEntry("command.run_arcenciel.success", "<prefix> &a运行成功,耗时<time>ms");
-    public static final StringConfigEntry COMMAND_LIST_UNSUPPORTED_VERSION = new StringConfigEntry("list.unsupported_version", "<prefix> &c此功能只在1.16及以上版本可用");
-    public static final StringConfigEntry MENU_RECIPE_LIST_TITLE = new StringConfigEntry("menu.recipe_list.title", "&3&l配方列表");
-    public static final StringConfigEntry MENU_RECIPE_LIST_ICON_FRAME = new StringConfigEntry("menu.recipe_list.icon.frame", "&3&l配方列表");
-    public static final StringConfigEntry MENU_RECIPE_LIST_ICON_PREVIOUS = new StringConfigEntry("menu.recipe_list.icon.previous", "&a上一页");
-    public static final StringConfigEntry MENU_RECIPE_LIST_ICON_NEXT = new StringConfigEntry("menu.recipe_list.icon.next", "&a下一页");
-    public static final StringConfigEntry MENU_NEW_RECIPE_LIST_TITLE = new StringConfigEntry("menu.new_recipe_list.title", "&3&lCraftorithm新增配方列表");
-    public static final StringConfigEntry MENU_NEW_RECIPE_LIST_ICON_FRAME = new StringConfigEntry("menu.new_recipe_list.icon.frame", "&3&l新增配方列表");
-    public static final StringConfigEntry MENU_NEW_RECIPE_LIST_ICON_PREVIOUS = new StringConfigEntry("menu.new_recipe_list.icon.previous", "&a上一页");
-    public static final StringConfigEntry MENU_NEW_RECIPE_LIST_ICON_NEXT = new StringConfigEntry("menu.new_recipe_list.icon.next", "&a下一页");
-    public static final StringConfigEntry MENU_RECIPE_DISPLAY_TITLE_SHAPED = new StringConfigEntry("menu.recipe_display.title.shaped", "有序配方");
-    public static final StringConfigEntry MENU_RECIPE_DISPLAY_TITLE_SHAPELESS = new StringConfigEntry("menu.recipe_display.title.shapeless", "无序配方");
-    public static final StringConfigEntry MENU_RECIPE_DISPLAY_TITLE_FURNACE = new StringConfigEntry("menu.recipe_display.title.furnace", "熔炉配方");
-    public static final StringConfigEntry MENU_RECIPE_DISPLAY_TITLE_BLASTING = new StringConfigEntry("menu.recipe_display.title.blasting", "高炉配方");
-    public static final StringConfigEntry MENU_RECIPE_DISPLAY_TITLE_SMOKING = new StringConfigEntry("menu.recipe_display.title.smoking", "烟熏炉配方");
-    public static final StringConfigEntry MENU_RECIPE_DISPLAY_TITLE_CAMPFIRE = new StringConfigEntry("menu.recipe_display.title.campfire", "营火配方");
-    public static final StringConfigEntry MENU_RECIPE_DISPLAY_TITLE_SMITHING = new StringConfigEntry("menu.recipe_display.title.smithing", "锻造配方");
-    public static final StringConfigEntry MENU_RECIPE_DISPLAY_TITLE_STONE_CUTTING = new StringConfigEntry("menu.recipe_display.title.stone_cutting", "切石配方");
-    public static final StringConfigEntry MENU_RECIPE_DISPLAY_TITLE_POTION = new StringConfigEntry("menu.recipe_display.title.potion", "酿造配方");
-    public static final StringConfigEntry MENU_RECIPE_DISPLAY_TITLE_ANVIL = new StringConfigEntry("menu.recipe_display.title.anvil", "铁砧配方");
-    public static final StringConfigEntry MENU_RECIPE_CREATOR_TITLE = new StringConfigEntry("menu.recipe_creator.title", "&3创建<recipe_type>配方: <recipe_name>");
-    public static final StringConfigEntry MENU_RECIPE_CREATOR_ICON_FRAME = new StringConfigEntry("menu.recipe_creator.icon.frame", "&a创建配方");
-    public static final StringConfigEntry MENU_RECIPE_CREATOR_ICON_RESULT_FRAME = new StringConfigEntry("menu.recipe_creator.icon.result_frame", "&a配方结果");
-    public static final StringConfigEntry MENU_RECIPE_CREATOR_ICON_CONFIRM = new StringConfigEntry("menu.recipe_creator.icon.confirm", "&3&l确认创建");
-    public static final StringConfigEntry MENU_RECIPE_CREATOR_ICON_UNLOCK = new StringConfigEntry("menu.recipe_creator.icon.unlock", "&a是否为玩家解锁配方:<unlock>");
-    public static final StringConfigEntry MENU_RECIPE_CREATOR_ICON_COOKING_FRAME = new StringConfigEntry("menu.recipe_creator.icon.cooking_frame", "&a烧炼原料");
-    public static final StringConfigEntry MENU_RECIPE_CREATOR_ICON_SMITHING_FRAME = new StringConfigEntry("menu.recipe_creator.icon.smithing_frame", "&a锻造原料");
-    public static final StringConfigEntry MENU_RECIPE_CREATOR_ICON_POTION_FRAME = new StringConfigEntry("menu.recipe_creator.icon.potion_frame", "&a酿造原料");
-    public static final StringConfigEntry MENU_RECIPE_CREATOR_ICON_ANVIL_FRAME = new StringConfigEntry("menu.recipe_creator.icon.anvil_frame", "&a打造原料");
-    public static final StringConfigEntry MENU_RECIPE_CREATOR_ICON_ANVIL_COPY_NBT_TOGGLE = new StringConfigEntry("menu.recipe_creator.icon.anvil_copy_nbt_toggle", "&a保留物品NBT: <enable>");
-    public static final StringConfigEntry MENU_RECIPE_CREATOR_ICON_ANVIL_COST_LEVEL_NAME = new StringConfigEntry("menu.recipe_creator.icon.anvil_cost_level.name", "&a所需等级: <level>");
+    public static final StringLangConfigEntry PREFIX = new StringLangConfigEntry("prefix", "&8[&3Craftorithm&8]");
+    public static final StringLangConfigEntry UNSUPPORTED_VERSION = new StringLangConfigEntry("unsupported_version", "<prefix> 不支持的版本");
+    public static final StringLangConfigEntry NEW_VERSION = new StringLangConfigEntry("new_version", "<prefix> &a检测到有新版本<new_version>, 请及时更新到新版本");
+    public static final StringLangConfigEntry COMMAND_NO_PERM = new StringLangConfigEntry("command.no_perm", "<prefix> &c你没有使用此命令的权限");
+    public static final StringLangConfigEntry COMMAND_PLAYER_ONLY = new StringLangConfigEntry("command.player_only", "<prefix> &c只有玩家才能执行此命令");
+    public static final StringLangConfigEntry COMMAND_NOT_ENOUGH_PARAM = new StringLangConfigEntry("command.not_enough_param", "<prefix> &c命令缺少参数,缺少<number>个参数");
+    public static final StringLangConfigEntry COMMAND_UNDEFINED_SUBCMD = new StringLangConfigEntry("command.undefined_subcmd", "<prefix> &c未定义的子命令");
+    public static final StringLangConfigEntry COMMAND_ITEM_SAVE_SUCCESS = new StringLangConfigEntry("command.item.save.success", "<prefix> &a物品保存成功");
+    public static final StringLangConfigEntry COMMAND_ITEM_SAVE_FAILED_SAVE_AIR = new StringLangConfigEntry("command.item.save.failed_save_air", "<prefix> &c物品保存失败,原因:不能保存不存在的物品");
+    public static final StringLangConfigEntry COMMAND_ITEM_GIVE_SUCCESS = new StringLangConfigEntry("command.item.give.success", "<prefix> &a物品获取成功");
+    public static final StringLangConfigEntry COMMAND_ITEM_GIVE_NOT_EXIST_ITEM = new StringLangConfigEntry("command.item.give.not_exist_item", "<prefix> &c不存在物品 <item_name>");
+    public static final StringLangConfigEntry COMMAND_ITEM_GIVE_PLAYER_OFFLINE = new StringLangConfigEntry("command.item.give.player_offline", "<prefix> &c该玩家不在线或不存在");
+    public static final StringLangConfigEntry COMMAND_RELOAD_SUCCESS = new StringLangConfigEntry("command.reload.success", "<prefix> &a插件重载成功");
+    public static final StringLangConfigEntry COMMAND_RELOAD_EXCEPTION = new StringLangConfigEntry("command.reload.exception", "<prefix> &c插件重载过程中发生错误,请查看控制台");
+    public static final StringLangConfigEntry COMMAND_REMOVE_SUCCESS = new StringLangConfigEntry("command.remove.success", "<prefix> &a配方删除成功");
+    public static final StringLangConfigEntry COMMAND_REMOVE_NOT_EXIST = new StringLangConfigEntry("command.remove.not_exist", "<prefix> &c配方不存在");
+    public static final StringLangConfigEntry COMMAND_DISABLE_SUCCESS = new StringLangConfigEntry("command.disable.success", "<prefix> &c禁用配方成功");
+    public static final StringLangConfigEntry COMMAND_DISABLE_NOT_EXIST = new StringLangConfigEntry("command.disable.not_exist", "<prefix> &c配方不存在或已经被禁用");
+    public static final StringLangConfigEntry COMMAND_DISABLE_FAILED = new StringLangConfigEntry("command.disable.failed", "<prefix> &c配方禁用失败,可能已被禁用或不存在");
+    public static final StringLangConfigEntry COMMAND_VERSION = new StringLangConfigEntry("command.version", "<prefix> &a插件版本:<version>");
+    public static final StringLangConfigEntry COMMAND_CREATE_UNSUPPORTED_RECIPE_TYPE = new StringLangConfigEntry("command.create.unsupported_recipe_type", "<prefix> &c不支持的配方类型");
+    public static final StringLangConfigEntry COMMAND_CREATE_UNSUPPORTED_RECIPE_NAME = new StringLangConfigEntry("command.create.unsupported_recipe_name", "<prefix> &c不支持的配方名字,只能使用[a-z0-9/._-]+允许的内容");
+    public static final StringLangConfigEntry COMMAND_CREATE_NAME_USED = new StringLangConfigEntry("command.create.name_used", "<prefix> &c配方ID已经被使用");
+    public static final StringLangConfigEntry COMMAND_CREATE_NULL_RESULT = new StringLangConfigEntry("command.create.null_result", "<prefix> &c配方结果不允许为空!");
+    public static final StringLangConfigEntry COMMAND_CREATE_NULL_SOURCE = new StringLangConfigEntry("command.create.null_source", "<prefix> &c配方原料不允许为空!");
+    public static final StringLangConfigEntry COMMAND_CREATE_SUCCESS = new StringLangConfigEntry("command.create.success", "<prefix> &a<recipe_type>类型配方<recipe_name>创建成功");
+    public static final StringLangConfigEntry COMMAND_RUN_ARCENCIEL_SUCCESS = new StringLangConfigEntry("command.run_arcenciel.success", "<prefix> &a运行成功,耗时<time>ms");
+    public static final StringLangConfigEntry COMMAND_LIST_UNSUPPORTED_VERSION = new StringLangConfigEntry("command.list.unsupported_version", "<prefix> &c此功能只在1.16及以上版本可用");
+    public static final StringLangConfigEntry MENU_RECIPE_LIST_TITLE = new StringLangConfigEntry("menu.recipe_list.title", "&3&l配方列表");
+    public static final StringLangConfigEntry MENU_RECIPE_LIST_ICON_FRAME = new StringLangConfigEntry("menu.recipe_list.icon.frame", "&3&l配方列表");
+    public static final StringLangConfigEntry MENU_RECIPE_LIST_ICON_PREVIOUS = new StringLangConfigEntry("menu.recipe_list.icon.previous", "&a上一页");
+    public static final StringLangConfigEntry MENU_RECIPE_LIST_ICON_NEXT = new StringLangConfigEntry("menu.recipe_list.icon.next", "&a下一页");
+    public static final StringLangConfigEntry MENU_NEW_RECIPE_LIST_TITLE = new StringLangConfigEntry("menu.new_recipe_list.title", "&3&lCraftorithm新增配方列表");
+    public static final StringLangConfigEntry MENU_NEW_RECIPE_LIST_ICON_FRAME = new StringLangConfigEntry("menu.new_recipe_list.icon.frame", "&3&l新增配方列表");
+    public static final StringLangConfigEntry MENU_NEW_RECIPE_LIST_ICON_PREVIOUS = new StringLangConfigEntry("menu.new_recipe_list.icon.previous", "&a上一页");
+    public static final StringLangConfigEntry MENU_NEW_RECIPE_LIST_ICON_NEXT = new StringLangConfigEntry("menu.new_recipe_list.icon.next", "&a下一页");
+    public static final StringLangConfigEntry MENU_RECIPE_DISPLAY_TITLE_SHAPED = new StringLangConfigEntry("menu.recipe_display.title.shaped", "有序配方");
+    public static final StringLangConfigEntry MENU_RECIPE_DISPLAY_TITLE_SHAPELESS = new StringLangConfigEntry("menu.recipe_display.title.shapeless", "无序配方");
+    public static final StringLangConfigEntry MENU_RECIPE_DISPLAY_TITLE_FURNACE = new StringLangConfigEntry("menu.recipe_display.title.furnace", "熔炉配方");
+    public static final StringLangConfigEntry MENU_RECIPE_DISPLAY_TITLE_BLASTING = new StringLangConfigEntry("menu.recipe_display.title.blasting", "高炉配方");
+    public static final StringLangConfigEntry MENU_RECIPE_DISPLAY_TITLE_SMOKING = new StringLangConfigEntry("menu.recipe_display.title.smoking", "烟熏炉配方");
+    public static final StringLangConfigEntry MENU_RECIPE_DISPLAY_TITLE_CAMPFIRE = new StringLangConfigEntry("menu.recipe_display.title.campfire", "营火配方");
+    public static final StringLangConfigEntry MENU_RECIPE_DISPLAY_TITLE_SMITHING = new StringLangConfigEntry("menu.recipe_display.title.smithing", "锻造配方");
+    public static final StringLangConfigEntry MENU_RECIPE_DISPLAY_TITLE_STONE_CUTTING = new StringLangConfigEntry("menu.recipe_display.title.stone_cutting", "切石配方");
+    public static final StringLangConfigEntry MENU_RECIPE_DISPLAY_TITLE_POTION = new StringLangConfigEntry("menu.recipe_display.title.potion", "酿造配方");
+    public static final StringLangConfigEntry MENU_RECIPE_DISPLAY_TITLE_ANVIL = new StringLangConfigEntry("menu.recipe_display.title.anvil", "铁砧配方");
+    public static final StringLangConfigEntry MENU_RECIPE_CREATOR_TITLE = new StringLangConfigEntry("menu.recipe_creator.title", "&3创建<recipe_type>配方: <recipe_name>");
+    public static final StringLangConfigEntry MENU_RECIPE_CREATOR_ICON_FRAME = new StringLangConfigEntry("menu.recipe_creator.icon.frame", "&a创建配方");
+    public static final StringLangConfigEntry MENU_RECIPE_CREATOR_ICON_RESULT_FRAME = new StringLangConfigEntry("menu.recipe_creator.icon.result_frame", "&a配方结果");
+    public static final StringLangConfigEntry MENU_RECIPE_CREATOR_ICON_CONFIRM = new StringLangConfigEntry("menu.recipe_creator.icon.confirm", "&3&l确认创建");
+    public static final StringLangConfigEntry MENU_RECIPE_CREATOR_ICON_UNLOCK = new StringLangConfigEntry("menu.recipe_creator.icon.unlock", "&a是否为玩家解锁配方:<unlock>");
+    public static final StringLangConfigEntry MENU_RECIPE_CREATOR_ICON_COOKING_FRAME = new StringLangConfigEntry("menu.recipe_creator.icon.cooking_frame", "&a烧炼原料");
+    public static final StringLangConfigEntry MENU_RECIPE_CREATOR_ICON_SMITHING_FRAME = new StringLangConfigEntry("menu.recipe_creator.icon.smithing_frame", "&a锻造原料");
+    public static final StringLangConfigEntry MENU_RECIPE_CREATOR_ICON_POTION_FRAME = new StringLangConfigEntry("menu.recipe_creator.icon.potion_frame", "&a酿造原料");
+    public static final StringLangConfigEntry MENU_RECIPE_CREATOR_ICON_ANVIL_FRAME = new StringLangConfigEntry("menu.recipe_creator.icon.anvil_frame", "&a打造原料");
+    public static final StringLangConfigEntry MENU_RECIPE_CREATOR_ICON_ANVIL_COPY_NBT_TOGGLE = new StringLangConfigEntry("menu.recipe_creator.icon.anvil_copy_nbt_toggle", "&a保留物品NBT: <enable>");
+    public static final StringLangConfigEntry MENU_RECIPE_CREATOR_ICON_ANVIL_COST_LEVEL_NAME = new StringLangConfigEntry("menu.recipe_creator.icon.anvil_cost_level.name", "&a所需等级: <level>");
     public static final StringListConfigEntry MENU_RECIPE_CREATOR_ICON_ANVIL_COST_LEVEL_LORE = new StringListConfigEntry("menu.recipe_creator.icon.anvil_cost_level.lore", Collections.singletonList("&3点击修改所需等级"));
-    public static final StringConfigEntry MENU_RECIPE_CREATOR_ICON_ANVIL_COST_LEVEL_INPUT_HINT = new StringConfigEntry("menu.recipe_creator.icon.anvil_cost_level.input_hint", "&a请输入所需等级, 输入cancel取消");
-    public static final StringConfigEntry MENU_RECIPE_CREATOR_ICON_COOKING_TIME_NAME = new StringConfigEntry("menu.recipe_creator.icon.cooking_time.name", "&a烧炼时间: <time> tick");
+    public static final StringLangConfigEntry MENU_RECIPE_CREATOR_ICON_ANVIL_COST_LEVEL_INPUT_HINT = new StringLangConfigEntry("menu.recipe_creator.icon.anvil_cost_level.input_hint", "&a请输入所需等级, 输入cancel取消");
+    public static final StringLangConfigEntry MENU_RECIPE_CREATOR_ICON_COOKING_TIME_NAME = new StringLangConfigEntry("menu.recipe_creator.icon.cooking_time.name", "&a烧炼时间: <time> tick");
     public static final StringListConfigEntry MENU_RECIPE_CREATOR_ICON_COOKING_TIME_LORE = new StringListConfigEntry("menu.recipe_creator.icon.cooking_time.lore", Collections.singletonList("&3点击修改烧炼时间"));
-    public static final StringConfigEntry MENU_RECIPE_CREATOR_ICON_COOKING_TIME_INPUT_HINT = new StringConfigEntry("menu.recipe_creator.icon.cooking_time.input_hint", "&a请输入烧炼时间, 单位为tick, 输入cancel取消");
-    public static final StringConfigEntry MENU_RECIPE_CREATOR_ICON_COOKING_EXP_NAME = new StringConfigEntry("menu.recipe_creator.icon.cooking_exp.name", "&a奖励经验: <exp>");
+    public static final StringLangConfigEntry MENU_RECIPE_CREATOR_ICON_COOKING_TIME_INPUT_HINT = new StringLangConfigEntry("menu.recipe_creator.icon.cooking_time.input_hint", "&a请输入烧炼时间, 单位为tick, 输入cancel取消");
+    public static final StringLangConfigEntry MENU_RECIPE_CREATOR_ICON_COOKING_EXP_NAME = new StringLangConfigEntry("menu.recipe_creator.icon.cooking_exp.name", "&a奖励经验: <exp>");
     public static final StringListConfigEntry MENU_RECIPE_CREATOR_ICON_COOKING_EXP_LORE = new StringListConfigEntry("menu.recipe_creator.icon.cooking_exp.lore", Collections.singletonList("&3点击修改奖励经验"));
-    public static final StringConfigEntry MENU_RECIPE_CREATOR_ICON_COOKING_EXP_INPUT_HINT = new StringConfigEntry("menu.recipe_creator.icon.cooking_exp.input_hint", "&a请输入奖励经验, 输入cancel取消");
-    public static final StringConfigEntry MENU_RECIPE_CREATOR_ICON_FURNACE_TOGGLE = new StringConfigEntry("menu.recipe_creator.icon.furnace_toggle", "&a启用熔炉配方:<enable>");
-    public static final StringConfigEntry MENU_RECIPE_CREATOR_ICON_BLAST_FURNACE_TOGGLE = new StringConfigEntry("menu.recipe_creator.icon.blast_furnace_toggle", "&a启用高炉配方:<enable>");
-    public static final StringConfigEntry MENU_RECIPE_CREATOR_ICON_SMOKER_TOGGLE = new StringConfigEntry("menu.recipe_creator.icon.smoker_toggle", "&a启用烟熏炉配方:<enable>");
-    public static final StringConfigEntry MENU_RECIPE_CREATOR_ICON_CAMPFIRE_TOGGLE = new StringConfigEntry("menu.recipe_creator.icon.campfire_toggle", "&a启用营火配方:<enable>");
-    public static final StringConfigEntry ARCENCIEL_NOT_ENOUGH_PARAM = new StringConfigEntry("arcenciel.not_enough_param", "<prefix> &c语句\"<statement>\"不完整");
-    public static final StringConfigEntry ARCENCIEL_UNKNOWN_TOKEN = new StringConfigEntry("arcenciel.unknown_token", "<prefix> &c未定义的关键词或函数<token>");
-    public static final StringConfigEntry LOAD_FINISH = new StringConfigEntry("load.finish", "<prefix> &a插件加载完毕");
-    public static final StringConfigEntry LOAD_RECIPE_LOAD_EXCEPTION = new StringConfigEntry("load.recipe_load_exception", "<prefix> &c加载配方<recipe_name>时出现错误");
-    public static final StringConfigEntry LOAD_ITEM_LOAD_EXCEPTION = new StringConfigEntry("load.item_load_exception", "<prefix> &c加载物品<item_name>时出现错误");
-    public static final StringConfigEntry LOAD_HOOK_PLUGIN_SUCCESS = new StringConfigEntry("load.hook_plugin.success", "<prefix> &a发现<plugin>,已挂钩");
-    public static final StringConfigEntry LOAD_HOOK_PLUGIN_NOT_EXIST = new StringConfigEntry("load.hook_plugin.not_exist", "<prefix> &c未发现<plugin>");
-    public static final StringConfigEntry RECIPE_TYPE_NAME_SHAPED = new StringConfigEntry("recipe_type_name.shaped", "有序");
-    public static final StringConfigEntry RECIPE_TYPE_NAME_SHAPELESS = new StringConfigEntry("recipe_type_name.shapeless", "无序");
-    public static final StringConfigEntry RECIPE_TYPE_NAME_COOKING = new StringConfigEntry("recipe_type_name.cooking", "烧炼");
-    public static final StringConfigEntry RECIPE_TYPE_NAME_SMITHING = new StringConfigEntry("recipe_type_name.smithing", "锻造");
-    public static final StringConfigEntry RECIPE_TYPE_NAME_STONE_CUTTING = new StringConfigEntry("recipe_type_name.stone_cutting", "切石");
-    public static final StringConfigEntry RECIPE_TYPE_NAME_POTION = new StringConfigEntry("recipe_type_name.potion", "酿造");
-    public static final StringConfigEntry RECIPE_TYPE_NAME_ANVIL = new StringConfigEntry("recipe_type_name.anvil", "铁砧");
+    public static final StringLangConfigEntry MENU_RECIPE_CREATOR_ICON_COOKING_EXP_INPUT_HINT = new StringLangConfigEntry("menu.recipe_creator.icon.cooking_exp.input_hint", "&a请输入奖励经验, 输入cancel取消");
+    public static final StringLangConfigEntry MENU_RECIPE_CREATOR_ICON_FURNACE_TOGGLE = new StringLangConfigEntry("menu.recipe_creator.icon.furnace_toggle", "&a启用熔炉配方:<enable>");
+    public static final StringLangConfigEntry MENU_RECIPE_CREATOR_ICON_BLAST_FURNACE_TOGGLE = new StringLangConfigEntry("menu.recipe_creator.icon.blast_furnace_toggle", "&a启用高炉配方:<enable>");
+    public static final StringLangConfigEntry MENU_RECIPE_CREATOR_ICON_SMOKER_TOGGLE = new StringLangConfigEntry("menu.recipe_creator.icon.smoker_toggle", "&a启用烟熏炉配方:<enable>");
+    public static final StringLangConfigEntry MENU_RECIPE_CREATOR_ICON_CAMPFIRE_TOGGLE = new StringLangConfigEntry("menu.recipe_creator.icon.campfire_toggle", "&a启用营火配方:<enable>");
+    public static final StringLangConfigEntry ARCENCIEL_NOT_ENOUGH_PARAM = new StringLangConfigEntry("arcenciel.not_enough_param", "<prefix> &c语句\"<statement>\"不完整");
+    public static final StringLangConfigEntry ARCENCIEL_UNKNOWN_TOKEN = new StringLangConfigEntry("arcenciel.unknown_token", "<prefix> &c未定义的关键词或函数<token>");
+    public static final StringLangConfigEntry LOAD_FINISH = new StringLangConfigEntry("load.finish", "<prefix> &a插件加载完毕");
+    public static final StringLangConfigEntry LOAD_RECIPE_LOAD_EXCEPTION = new StringLangConfigEntry("load.recipe_load_exception", "<prefix> &c加载配方<recipe_name>时出现错误");
+    public static final StringLangConfigEntry LOAD_ITEM_LOAD_EXCEPTION = new StringLangConfigEntry("load.item_load_exception", "<prefix> &c加载物品<item_name>时出现错误");
+    public static final StringLangConfigEntry LOAD_HOOK_PLUGIN_SUCCESS = new StringLangConfigEntry("load.hook_plugin.success", "<prefix> &a发现<plugin>,已挂钩");
+    public static final StringLangConfigEntry LOAD_HOOK_PLUGIN_NOT_EXIST = new StringLangConfigEntry("load.hook_plugin.not_exist", "<prefix> &c未发现<plugin>");
+    public static final StringLangConfigEntry RECIPE_TYPE_NAME_SHAPED = new StringLangConfigEntry("recipe_type_name.shaped", "有序");
+    public static final StringLangConfigEntry RECIPE_TYPE_NAME_SHAPELESS = new StringLangConfigEntry("recipe_type_name.shapeless", "无序");
+    public static final StringLangConfigEntry RECIPE_TYPE_NAME_COOKING = new StringLangConfigEntry("recipe_type_name.cooking", "烧炼");
+    public static final StringLangConfigEntry RECIPE_TYPE_NAME_SMITHING = new StringLangConfigEntry("recipe_type_name.smithing", "锻造");
+    public static final StringLangConfigEntry RECIPE_TYPE_NAME_STONE_CUTTING = new StringLangConfigEntry("recipe_type_name.stone_cutting", "切石");
+    public static final StringLangConfigEntry RECIPE_TYPE_NAME_POTION = new StringLangConfigEntry("recipe_type_name.potion", "酿造");
+    public static final StringLangConfigEntry RECIPE_TYPE_NAME_ANVIL = new StringLangConfigEntry("recipe_type_name.anvil", "铁砧");
 
 }
diff --git a/src/main/java/com/github/yufiriamazenta/craftorithm/config/PluginConfigs.java b/src/main/java/com/github/yufiriamazenta/craftorithm/config/PluginConfigs.java
index 421762da..7911361b 100644
--- a/src/main/java/com/github/yufiriamazenta/craftorithm/config/PluginConfigs.java
+++ b/src/main/java/com/github/yufiriamazenta/craftorithm/config/PluginConfigs.java
@@ -1,10 +1,10 @@
 package com.github.yufiriamazenta.craftorithm.config;
 
-import crypticlib.config.yaml.YamlConfigHandler;
-import crypticlib.config.yaml.entry.BooleanConfigEntry;
-import crypticlib.config.yaml.entry.StringConfigEntry;
+import crypticlib.config.ConfigHandler;
+import crypticlib.config.entry.BooleanConfigEntry;
+import crypticlib.config.entry.StringConfigEntry;
 
-@YamlConfigHandler(path = "config.yml")
+@ConfigHandler(path = "config.yml")
 public class PluginConfigs {
 
     public final static BooleanConfigEntry CHECK_UPDATE = new BooleanConfigEntry("check_update", true);
diff --git a/src/main/java/com/github/yufiriamazenta/craftorithm/item/impl/CraftorithmItemProvider.java b/src/main/java/com/github/yufiriamazenta/craftorithm/item/impl/CraftorithmItemProvider.java
index cbbe325e..6672e553 100644
--- a/src/main/java/com/github/yufiriamazenta/craftorithm/item/impl/CraftorithmItemProvider.java
+++ b/src/main/java/com/github/yufiriamazenta/craftorithm/item/impl/CraftorithmItemProvider.java
@@ -5,7 +5,7 @@
 import com.github.yufiriamazenta.craftorithm.item.ItemProvider;
 import com.github.yufiriamazenta.craftorithm.util.CollectionsUtil;
 import com.github.yufiriamazenta.craftorithm.util.LangUtil;
-import crypticlib.config.yaml.YamlConfigWrapper;
+import crypticlib.config.ConfigWrapper;
 import crypticlib.nms.item.ItemFactory;
 import crypticlib.nms.item.NbtItem;
 import crypticlib.util.FileUtil;
@@ -26,7 +26,7 @@ public enum CraftorithmItemProvider implements ItemProvider {
     INSTANCE;
     public final File ITEM_FILE_FOLDER = new File(Craftorithm.instance().getDataFolder(), "items");
     private final Map<String, ItemStack> itemMap;
-    private final Map<String, YamlConfigWrapper> itemConfigFileMap;
+    private final Map<String, ConfigWrapper> itemConfigFileMap;
 
     CraftorithmItemProvider() {
         itemConfigFileMap = new HashMap<>();
@@ -87,14 +87,14 @@ private void loadItemFiles() {
             key = key.replace("\\", "/");
             int lastDotIndex = key.lastIndexOf(".");
             key = key.substring(0, lastDotIndex);
-            itemConfigFileMap.put(key, new YamlConfigWrapper(file));
+            itemConfigFileMap.put(key, new ConfigWrapper(file));
         }
     }
 
     private void loadItems() {
         itemMap.clear();
         for (String namespace : itemConfigFileMap.keySet()) {
-            YamlConfigWrapper itemFile = itemConfigFileMap.get(namespace);
+            ConfigWrapper itemFile = itemConfigFileMap.get(namespace);
             Set<String> itemKeySet = itemFile.config().getKeys(false);
             for (String itemKey : itemKeySet) {
                 ConfigurationSection config = itemFile.config().getConfigurationSection(itemKey);
@@ -109,19 +109,19 @@ private void loadItem(String itemKey, ConfigurationSection config) {
             ItemStack bukkitItem = item.saveNbtToBukkit();
             itemMap.put(itemKey, bukkitItem);
         } catch (Exception e) {
-            LangUtil.info(Languages.LOAD_ITEM_LOAD_EXCEPTION.value(), CollectionsUtil.newStringHashMap("<item_name>", itemKey));
+            LangUtil.info(Languages.LOAD_ITEM_LOAD_EXCEPTION, CollectionsUtil.newStringHashMap("<item_name>", itemKey));
             e.printStackTrace();
         }
     }
 
     public String regCraftorithmItem(String namespace, String itemName, ItemStack item) {
-        YamlConfigWrapper itemConfigFile;
+        ConfigWrapper itemConfigFile;
         if (!itemConfigFileMap.containsKey(namespace)) {
             File itemFile = new File(ITEM_FILE_FOLDER, namespace + ".yml");
             if (!itemFile.exists()) {
                 FileUtil.createNewFile(itemFile);
             }
-            itemConfigFile = new YamlConfigWrapper(itemFile);
+            itemConfigFile = new ConfigWrapper(itemFile);
             itemConfigFileMap.put(namespace, itemConfigFile);
         } else {
             itemConfigFile = itemConfigFileMap.get(namespace);
@@ -138,7 +138,7 @@ public Map<String, ItemStack> itemMap() {
         return new HashMap<>(itemMap);
     }
 
-    public Map<String, YamlConfigWrapper> itemConfigFileMap() {
+    public Map<String, ConfigWrapper> itemConfigFileMap() {
         return new HashMap<>(itemConfigFileMap);
     }
 
diff --git a/src/main/java/com/github/yufiriamazenta/craftorithm/menu/creator/AnvilRecipeCreator.java b/src/main/java/com/github/yufiriamazenta/craftorithm/menu/creator/AnvilRecipeCreator.java
index ad503d0d..e2f710fe 100644
--- a/src/main/java/com/github/yufiriamazenta/craftorithm/menu/creator/AnvilRecipeCreator.java
+++ b/src/main/java/com/github/yufiriamazenta/craftorithm/menu/creator/AnvilRecipeCreator.java
@@ -8,7 +8,9 @@
 import com.github.yufiriamazenta.craftorithm.recipe.registry.RecipeRegistry;
 import com.github.yufiriamazenta.craftorithm.util.ItemUtils;
 import com.github.yufiriamazenta.craftorithm.util.LangUtil;
-import crypticlib.config.yaml.YamlConfigWrapper;
+import crypticlib.chat.TextProcessor;
+import crypticlib.chat.entry.StringLangConfigEntry;
+import crypticlib.config.ConfigWrapper;
 import crypticlib.conversation.Conversation;
 import crypticlib.conversation.NumberPrompt;
 import crypticlib.conversation.Prompt;
@@ -17,7 +19,6 @@
 import crypticlib.ui.display.MenuLayout;
 import crypticlib.ui.menu.StoredMenu;
 import crypticlib.util.ItemUtil;
-import crypticlib.util.TextUtil;
 import org.bukkit.Material;
 import org.bukkit.entity.Player;
 import org.bukkit.event.inventory.InventoryClickEvent;
@@ -66,17 +67,17 @@ public AnvilRecipeCreator(@NotNull Player player, @NotNull String recipeName) {
                             ItemStack base = creator.storedItems().get(19);
                             ItemStack addition = creator.storedItems().get(21);
                             if (ItemUtil.isAir(result)) {
-                                LangUtil.sendLang(event.getWhoClicked(), Languages.COMMAND_CREATE_NULL_RESULT.value());
+                                LangUtil.sendLang(event.getWhoClicked(), Languages.COMMAND_CREATE_NULL_RESULT);
                                 return;
                             }
                             if (ItemUtil.isAir(addition) || ItemUtil.isAir(base)) {
-                                LangUtil.sendLang(event.getWhoClicked(), Languages.COMMAND_CREATE_NULL_SOURCE.value());
+                                LangUtil.sendLang(event.getWhoClicked(), Languages.COMMAND_CREATE_NULL_SOURCE);
                                 return;
                             }
                             String resultName = ItemUtils.matchItemNameOrCreate(result, false);
                             String inputName = ItemUtils.matchItemNameOrCreate(base, false);
                             String ingredientName = ItemUtils.matchItemNameOrCreate(addition, false);
-                            YamlConfigWrapper recipeConfig = createRecipeConfig(recipeName);
+                            ConfigWrapper recipeConfig = createRecipeConfig(recipeName);
                             recipeConfig.set("source.copy_nbt", event.getInventory().getItem(40).getItemMeta().hasEnchants());
                             recipeConfig.set("type", "anvil");
                             recipeConfig.set("source.base", inputName);
@@ -127,7 +128,7 @@ protected void toggleCopyNbt(int slot, InventoryClickEvent event) {
         ItemStack display = event.getCurrentItem();
         ItemMeta itemMeta = display.getItemMeta();
         itemMeta.setDisplayName(
-            TextUtil.color(
+            TextProcessor.color(
                 Languages.MENU_RECIPE_CREATOR_ICON_ANVIL_COPY_NBT_TOGGLE
                     .value()
                     .replace("<enable>", String.valueOf(copyNbt))
@@ -139,7 +140,7 @@ protected void toggleCopyNbt(int slot, InventoryClickEvent event) {
     protected Icon getCostLevelIcon() {
         Icon icon = new Icon(
             Material.EXPERIENCE_BOTTLE,
-            TextUtil.color(Languages.MENU_RECIPE_CREATOR_ICON_ANVIL_COST_LEVEL_NAME.value())
+            TextProcessor.color(Languages.MENU_RECIPE_CREATOR_ICON_ANVIL_COST_LEVEL_NAME.value())
                 .replace("<level>", String.valueOf(costLevel)),
             event -> {
                 Player player = (Player) event.getWhoClicked();
@@ -163,7 +164,7 @@ public void updateCostLevelIcon() {
         if (costLevelIcon == null)
             return;
         ItemMeta itemMeta = costLevelIcon.getItemMeta();
-        itemMeta.setDisplayName(TextUtil.color(Languages.MENU_RECIPE_CREATOR_ICON_ANVIL_COST_LEVEL_NAME.value())
+        itemMeta.setDisplayName(TextProcessor.color(Languages.MENU_RECIPE_CREATOR_ICON_ANVIL_COST_LEVEL_NAME.value())
             .replace("<level>", String.valueOf(costLevel)));
         costLevelIcon.setItemMeta(itemMeta);
     }
@@ -180,8 +181,8 @@ public Prompt acceptValidatedInput(@NotNull Map<Object, Object> data, @NotNull N
         }
 
         @Override
-        public @NotNull String promptText(@NotNull Map<Object, Object> data) {
-            return TextUtil.color(Languages.MENU_RECIPE_CREATOR_ICON_ANVIL_COST_LEVEL_INPUT_HINT.value());
+        public @NotNull StringLangConfigEntry promptText(@NotNull Map<Object, Object> data) {
+            return Languages.MENU_RECIPE_CREATOR_ICON_ANVIL_COST_LEVEL_INPUT_HINT;
         }
     }
 
diff --git a/src/main/java/com/github/yufiriamazenta/craftorithm/menu/creator/CookingRecipeCreator.java b/src/main/java/com/github/yufiriamazenta/craftorithm/menu/creator/CookingRecipeCreator.java
index c24dc4a7..8face251 100644
--- a/src/main/java/com/github/yufiriamazenta/craftorithm/menu/creator/CookingRecipeCreator.java
+++ b/src/main/java/com/github/yufiriamazenta/craftorithm/menu/creator/CookingRecipeCreator.java
@@ -8,7 +8,9 @@
 import com.github.yufiriamazenta.craftorithm.recipe.registry.RecipeRegistry;
 import com.github.yufiriamazenta.craftorithm.util.ItemUtils;
 import com.github.yufiriamazenta.craftorithm.util.LangUtil;
-import crypticlib.config.yaml.YamlConfigWrapper;
+import crypticlib.chat.TextProcessor;
+import crypticlib.chat.entry.StringLangConfigEntry;
+import crypticlib.config.ConfigWrapper;
 import crypticlib.conversation.Conversation;
 import crypticlib.conversation.NumberPrompt;
 import crypticlib.conversation.Prompt;
@@ -17,7 +19,6 @@
 import crypticlib.ui.display.MenuLayout;
 import crypticlib.ui.menu.StoredMenu;
 import crypticlib.util.ItemUtil;
-import crypticlib.util.TextUtil;
 import org.bukkit.Material;
 import org.bukkit.entity.Player;
 import org.bukkit.event.inventory.InventoryClickEvent;
@@ -74,16 +75,16 @@ public CookingRecipeCreator(@NotNull Player player, @NotNull String recipeName)
                             ItemStack source = Objects.requireNonNull(creator).storedItems().get(20);
                             ItemStack result = creator.storedItems().get(24);
                             if (ItemUtil.isAir(source)) {
-                                LangUtil.sendLang(event.getWhoClicked(), Languages.COMMAND_CREATE_NULL_SOURCE.value());
+                                LangUtil.sendLang(event.getWhoClicked(), Languages.COMMAND_CREATE_NULL_SOURCE);
                                 return;
                             }
                             if (ItemUtil.isAir(result)) {
-                                LangUtil.sendLang(event.getWhoClicked(), Languages.COMMAND_CREATE_NULL_RESULT.value());
+                                LangUtil.sendLang(event.getWhoClicked(), Languages.COMMAND_CREATE_NULL_RESULT);
                                 return;
                             }
                             String sourceName = ItemUtils.matchItemNameOrCreate(source, true);
                             String resultName = ItemUtils.matchItemNameOrCreate(result, false);
-                            YamlConfigWrapper recipeConfig = createRecipeConfig(recipeName);
+                            ConfigWrapper recipeConfig = createRecipeConfig(recipeName);
                             recipeConfig.set("type", "cooking");
                             recipeConfig.set("result", resultName);
                             recipeConfig.set("multiple", true);
@@ -181,7 +182,7 @@ protected void toggleCookingIcon(int slot, InventoryClickEvent event) {
 
         ItemMeta itemMeta = display.getItemMeta();
         itemMeta.setDisplayName(
-            TextUtil.color(
+            TextProcessor.color(
                 displayName.replace("<enable>", String.valueOf(enable))
             )
         );
@@ -191,7 +192,7 @@ protected void toggleCookingIcon(int slot, InventoryClickEvent event) {
     protected Icon getCookingTimeIcon() {
         Icon icon = new Icon(
             Material.CLOCK,
-            TextUtil.color(Languages.MENU_RECIPE_CREATOR_ICON_COOKING_TIME_NAME.value())
+            TextProcessor.color(Languages.MENU_RECIPE_CREATOR_ICON_COOKING_TIME_NAME.value())
                 .replace("<time>", String.valueOf(cookingTime)),
             event -> {
                 Player player = (Player) event.getWhoClicked();
@@ -213,7 +214,7 @@ protected Icon getCookingTimeIcon() {
     protected Icon getExpIcon() {
         Icon icon = new Icon(
             Material.EXPERIENCE_BOTTLE,
-            TextUtil.color(Languages.MENU_RECIPE_CREATOR_ICON_COOKING_EXP_NAME.value())
+            TextProcessor.color(Languages.MENU_RECIPE_CREATOR_ICON_COOKING_EXP_NAME.value())
                 .replace("<exp>", String.valueOf(exp)),
             event -> {
                 Player player = (Player) event.getWhoClicked();
@@ -237,7 +238,7 @@ protected void updateCookingTimeIcon() {
         if (cookingTimeIcon == null)
             return;
         ItemMeta itemMeta = cookingTimeIcon.getItemMeta();
-        itemMeta.setDisplayName(TextUtil.color(Languages.MENU_RECIPE_CREATOR_ICON_COOKING_TIME_NAME.value())
+        itemMeta.setDisplayName(TextProcessor.color(Languages.MENU_RECIPE_CREATOR_ICON_COOKING_TIME_NAME.value())
             .replace("<time>", String.valueOf(cookingTime)));
         cookingTimeIcon.setItemMeta(itemMeta);
     }
@@ -247,7 +248,7 @@ protected void updateExpIcon() {
         if (expIcon == null)
             return;
         ItemMeta itemMeta = expIcon.getItemMeta();
-        itemMeta.setDisplayName(TextUtil.color(Languages.MENU_RECIPE_CREATOR_ICON_COOKING_EXP_NAME.value())
+        itemMeta.setDisplayName(TextProcessor.color(Languages.MENU_RECIPE_CREATOR_ICON_COOKING_EXP_NAME.value())
             .replace("<exp>", String.valueOf(exp)));
         expIcon.setItemMeta(itemMeta);
     }
@@ -264,8 +265,8 @@ class CookingTimePrompt implements NumberPrompt {
         }
 
         @Override
-        public @NotNull String promptText(@NotNull Map<Object, Object> data) {
-            return TextUtil.color(Languages.MENU_RECIPE_CREATOR_ICON_COOKING_TIME_INPUT_HINT.value());
+        public @NotNull StringLangConfigEntry promptText(@NotNull Map<Object, Object> data) {
+            return Languages.MENU_RECIPE_CREATOR_ICON_COOKING_TIME_INPUT_HINT;
         }
     }
 
@@ -280,8 +281,8 @@ class ExpPrompt implements NumberPrompt {
         }
 
         @Override
-        public @NotNull String promptText(@NotNull Map<Object, Object> data) {
-            return TextUtil.color(Languages.MENU_RECIPE_CREATOR_ICON_COOKING_EXP_INPUT_HINT.value());
+        public @NotNull StringLangConfigEntry promptText(@NotNull Map<Object, Object> data) {
+            return Languages.MENU_RECIPE_CREATOR_ICON_COOKING_EXP_INPUT_HINT;
         }
     }
 
diff --git a/src/main/java/com/github/yufiriamazenta/craftorithm/menu/creator/CraftingRecipeCreator.java b/src/main/java/com/github/yufiriamazenta/craftorithm/menu/creator/CraftingRecipeCreator.java
index cc7bdfbd..51776eca 100644
--- a/src/main/java/com/github/yufiriamazenta/craftorithm/menu/creator/CraftingRecipeCreator.java
+++ b/src/main/java/com/github/yufiriamazenta/craftorithm/menu/creator/CraftingRecipeCreator.java
@@ -8,7 +8,7 @@
 import com.github.yufiriamazenta.craftorithm.util.ItemUtils;
 import com.github.yufiriamazenta.craftorithm.util.LangUtil;
 import com.google.common.base.Preconditions;
-import crypticlib.config.yaml.YamlConfigWrapper;
+import crypticlib.config.ConfigWrapper;
 import crypticlib.ui.display.Icon;
 import crypticlib.ui.display.MenuDisplay;
 import crypticlib.ui.display.MenuLayout;
@@ -50,7 +50,7 @@ public CraftingRecipeCreator(@NotNull Player player, RecipeType recipeType, @Not
                         Map<Integer, ItemStack> storedItems = Objects.requireNonNull(creator).storedItems();
                         ItemStack result = storedItems.get(24);
                         if (ItemUtil.isAir(result)) {
-                            LangUtil.sendLang(event.getWhoClicked(), Languages.COMMAND_CREATE_NULL_RESULT.value());
+                            LangUtil.sendLang(event.getWhoClicked(), Languages.COMMAND_CREATE_NULL_RESULT);
                             return;
                         }
                         String resultName = ItemUtils.matchItemNameOrCreate(result, false);
@@ -65,7 +65,7 @@ public CraftingRecipeCreator(@NotNull Player player, RecipeType recipeType, @Not
                             String sourceName = ItemUtils.matchItemNameOrCreate(source, true);
                             sourceList.add(sourceName);
                         }
-                        YamlConfigWrapper recipeConfig = createRecipeConfig(recipeName);
+                        ConfigWrapper recipeConfig = createRecipeConfig(recipeName);
                         switch (recipeType()) {
                             case SHAPED:
                                 List<String> shape = new ArrayList<>(Arrays.asList("abc", "def", "ghi"));
diff --git a/src/main/java/com/github/yufiriamazenta/craftorithm/menu/creator/PotionMixCreator.java b/src/main/java/com/github/yufiriamazenta/craftorithm/menu/creator/PotionMixCreator.java
index 48beb3a7..06a94241 100644
--- a/src/main/java/com/github/yufiriamazenta/craftorithm/menu/creator/PotionMixCreator.java
+++ b/src/main/java/com/github/yufiriamazenta/craftorithm/menu/creator/PotionMixCreator.java
@@ -7,7 +7,7 @@
 import com.github.yufiriamazenta.craftorithm.recipe.registry.RecipeRegistry;
 import com.github.yufiriamazenta.craftorithm.util.ItemUtils;
 import com.github.yufiriamazenta.craftorithm.util.LangUtil;
-import crypticlib.config.yaml.YamlConfigWrapper;
+import crypticlib.config.ConfigWrapper;
 import crypticlib.ui.display.Icon;
 import crypticlib.ui.display.MenuDisplay;
 import crypticlib.ui.display.MenuLayout;
@@ -48,17 +48,17 @@ public PotionMixCreator(@NotNull Player player, @NotNull String recipeName) {
                             ItemStack input = creator.storedItems().get(19);
                             ItemStack ingredient = creator.storedItems().get(21);
                             if (ItemUtil.isAir(result)) {
-                                LangUtil.sendLang(event.getWhoClicked(), Languages.COMMAND_CREATE_NULL_RESULT.value());
+                                LangUtil.sendLang(event.getWhoClicked(), Languages.COMMAND_CREATE_NULL_RESULT);
                                 return;
                             }
                             if (ItemUtil.isAir(ingredient) || ItemUtil.isAir(input)) {
-                                LangUtil.sendLang(event.getWhoClicked(), Languages.COMMAND_CREATE_NULL_SOURCE.value());
+                                LangUtil.sendLang(event.getWhoClicked(), Languages.COMMAND_CREATE_NULL_SOURCE);
                                 return;
                             }
                             String resultName = ItemUtils.matchItemNameOrCreate(result, false);
                             String inputName = ItemUtils.matchItemNameOrCreate(input, true);
                             String ingredientName = ItemUtils.matchItemNameOrCreate(ingredient, true);
-                            YamlConfigWrapper recipeConfig = createRecipeConfig(recipeName);
+                            ConfigWrapper recipeConfig = createRecipeConfig(recipeName);
                             recipeConfig.set("type", "potion");
                             recipeConfig.set("source.input", inputName);
                             recipeConfig.set("source.ingredient", ingredientName);
diff --git a/src/main/java/com/github/yufiriamazenta/craftorithm/menu/creator/RecipeCreator.java b/src/main/java/com/github/yufiriamazenta/craftorithm/menu/creator/RecipeCreator.java
index 920ff1cb..1419a3eb 100644
--- a/src/main/java/com/github/yufiriamazenta/craftorithm/menu/creator/RecipeCreator.java
+++ b/src/main/java/com/github/yufiriamazenta/craftorithm/menu/creator/RecipeCreator.java
@@ -5,7 +5,7 @@
 import com.github.yufiriamazenta.craftorithm.recipe.RecipeType;
 import com.github.yufiriamazenta.craftorithm.util.CollectionsUtil;
 import com.github.yufiriamazenta.craftorithm.util.LangUtil;
-import crypticlib.config.yaml.YamlConfigWrapper;
+import crypticlib.config.ConfigWrapper;
 import crypticlib.ui.display.Icon;
 import crypticlib.ui.menu.StoredMenu;
 import crypticlib.util.FileUtil;
@@ -70,17 +70,17 @@ protected Icon getFrameIcon() {
     protected void sendSuccessMsg(HumanEntity receiver, String recipeName) {
         LangUtil.sendLang(
             receiver,
-            Languages.COMMAND_CREATE_SUCCESS.value(),
+            Languages.COMMAND_CREATE_SUCCESS,
             CollectionsUtil.newStringHashMap("<recipe_type>", RecipeManager.INSTANCE.getRecipeTypeName(recipeType), "<recipe_name>", recipeName)
         );
     }
 
-    protected YamlConfigWrapper createRecipeConfig(String recipeName) {
+    protected ConfigWrapper createRecipeConfig(String recipeName) {
         File recipeFile = new File(RecipeManager.INSTANCE.RECIPE_FILE_FOLDER, recipeName + ".yml");
         if (!recipeFile.exists()) {
             FileUtil.createNewFile(recipeFile);
         }
-        return new YamlConfigWrapper(recipeFile);
+        return new ConfigWrapper(recipeFile);
     }
 
     protected Icon getResultFrameIcon() {
diff --git a/src/main/java/com/github/yufiriamazenta/craftorithm/menu/creator/SmithingRecipeCreator.java b/src/main/java/com/github/yufiriamazenta/craftorithm/menu/creator/SmithingRecipeCreator.java
index 4c0ac0cf..3120ef56 100644
--- a/src/main/java/com/github/yufiriamazenta/craftorithm/menu/creator/SmithingRecipeCreator.java
+++ b/src/main/java/com/github/yufiriamazenta/craftorithm/menu/creator/SmithingRecipeCreator.java
@@ -8,7 +8,7 @@
 import com.github.yufiriamazenta.craftorithm.util.ItemUtils;
 import com.github.yufiriamazenta.craftorithm.util.LangUtil;
 import crypticlib.CrypticLib;
-import crypticlib.config.yaml.YamlConfigWrapper;
+import crypticlib.config.ConfigWrapper;
 import crypticlib.ui.display.Icon;
 import crypticlib.ui.display.MenuDisplay;
 import crypticlib.ui.display.MenuLayout;
@@ -63,7 +63,7 @@ public SmithingRecipeCreator(@NotNull Player player, @NotNull String recipeName)
                                 StoredMenu creator = (StoredMenu) Objects.requireNonNull(event.getClickedInventory()).getHolder();
                                 ItemStack result = Objects.requireNonNull(creator).storedItems().get(24);
                                 if (ItemUtil.isAir(result)) {
-                                    LangUtil.sendLang(event.getWhoClicked(), Languages.COMMAND_CREATE_NULL_RESULT.value());
+                                    LangUtil.sendLang(event.getWhoClicked(), Languages.COMMAND_CREATE_NULL_RESULT);
                                     return;
                                 }
                                 String resultName = ItemUtils.matchItemNameOrCreate(result, false);
@@ -78,17 +78,17 @@ public SmithingRecipeCreator(@NotNull Player player, @NotNull String recipeName)
                                     addition = creator.storedItems().get(21);
                                     templateName = ItemUtils.matchItemNameOrCreate(template, true);
                                     if (ItemUtil.isAir(template)) {
-                                        LangUtil.sendLang(event.getWhoClicked(), Languages.COMMAND_CREATE_NULL_SOURCE.value());
+                                        LangUtil.sendLang(event.getWhoClicked(), Languages.COMMAND_CREATE_NULL_SOURCE);
                                         return;
                                     }
                                 }
                                 if (ItemUtil.isAir(base) || ItemUtil.isAir(addition)) {
-                                    LangUtil.sendLang(event.getWhoClicked(), Languages.COMMAND_CREATE_NULL_SOURCE.value());
+                                    LangUtil.sendLang(event.getWhoClicked(), Languages.COMMAND_CREATE_NULL_SOURCE);
                                     return;
                                 }
                                 baseName = ItemUtils.matchItemNameOrCreate(base, true);
                                 additionName = ItemUtils.matchItemNameOrCreate(addition, true);
-                                YamlConfigWrapper recipeConfig = createRecipeConfig(recipeName);
+                                ConfigWrapper recipeConfig = createRecipeConfig(recipeName);
                                 recipeConfig.set("result", resultName);
                                 recipeConfig.set("source.base", baseName);
                                 recipeConfig.set("source.addition", additionName);
diff --git a/src/main/java/com/github/yufiriamazenta/craftorithm/menu/creator/StoneCuttingRecipeCreator.java b/src/main/java/com/github/yufiriamazenta/craftorithm/menu/creator/StoneCuttingRecipeCreator.java
index a7d8cd15..ec7aa6ad 100644
--- a/src/main/java/com/github/yufiriamazenta/craftorithm/menu/creator/StoneCuttingRecipeCreator.java
+++ b/src/main/java/com/github/yufiriamazenta/craftorithm/menu/creator/StoneCuttingRecipeCreator.java
@@ -7,7 +7,7 @@
 import com.github.yufiriamazenta.craftorithm.recipe.registry.RecipeRegistry;
 import com.github.yufiriamazenta.craftorithm.util.ItemUtils;
 import com.github.yufiriamazenta.craftorithm.util.LangUtil;
-import crypticlib.config.yaml.YamlConfigWrapper;
+import crypticlib.config.ConfigWrapper;
 import crypticlib.ui.display.Icon;
 import crypticlib.ui.display.MenuDisplay;
 import crypticlib.ui.display.MenuLayout;
@@ -55,14 +55,14 @@ public StoneCuttingRecipeCreator(@NotNull Player player, @NotNull String recipeN
                                 resultList.add(ItemUtils.matchItemNameOrCreate(result, false));
                             }
                             if (sourceList.isEmpty()) {
-                                LangUtil.sendLang(event.getWhoClicked(), Languages.COMMAND_CREATE_NULL_SOURCE.value());
+                                LangUtil.sendLang(event.getWhoClicked(), Languages.COMMAND_CREATE_NULL_SOURCE);
                                 return;
                             }
                             if (resultList.isEmpty()) {
-                                LangUtil.sendLang(event.getWhoClicked(), Languages.COMMAND_CREATE_NULL_RESULT.value());
+                                LangUtil.sendLang(event.getWhoClicked(), Languages.COMMAND_CREATE_NULL_RESULT);
                                 return;
                             }
-                            YamlConfigWrapper recipeConfig = createRecipeConfig(recipeName);
+                            ConfigWrapper recipeConfig = createRecipeConfig(recipeName);
                             recipeConfig.set("multiple", true);
                             recipeConfig.set("result", resultList);
                             recipeConfig.set("type", "stone_cutting");
diff --git a/src/main/java/com/github/yufiriamazenta/craftorithm/menu/creator/UnlockableRecipeCreator.java b/src/main/java/com/github/yufiriamazenta/craftorithm/menu/creator/UnlockableRecipeCreator.java
index e92b4d3e..33d86ca2 100644
--- a/src/main/java/com/github/yufiriamazenta/craftorithm/menu/creator/UnlockableRecipeCreator.java
+++ b/src/main/java/com/github/yufiriamazenta/craftorithm/menu/creator/UnlockableRecipeCreator.java
@@ -3,8 +3,8 @@
 import com.github.yufiriamazenta.craftorithm.config.Languages;
 import com.github.yufiriamazenta.craftorithm.config.PluginConfigs;
 import com.github.yufiriamazenta.craftorithm.recipe.RecipeType;
+import crypticlib.chat.TextProcessor;
 import crypticlib.ui.display.Icon;
-import crypticlib.util.TextUtil;
 import org.bukkit.Material;
 import org.bukkit.entity.Player;
 import org.bukkit.event.inventory.InventoryClickEvent;
@@ -48,7 +48,7 @@ protected void toggleUnlockIcon(int slot, InventoryClickEvent event) {
         ItemStack display = event.getCurrentItem();
         ItemMeta itemMeta = display.getItemMeta();
         itemMeta.setDisplayName(
-            TextUtil.color(
+            TextProcessor.color(
                 Languages.MENU_RECIPE_CREATOR_ICON_UNLOCK
                     .value()
                     .replace("<unlock>", String.valueOf(unlock))
diff --git a/src/main/java/com/github/yufiriamazenta/craftorithm/menu/display/RecipeDisplayMenuHolder.java b/src/main/java/com/github/yufiriamazenta/craftorithm/menu/display/RecipeDisplayMenuHolder.java
index 011ba6e7..53d5781b 100644
--- a/src/main/java/com/github/yufiriamazenta/craftorithm/menu/display/RecipeDisplayMenuHolder.java
+++ b/src/main/java/com/github/yufiriamazenta/craftorithm/menu/display/RecipeDisplayMenuHolder.java
@@ -7,9 +7,9 @@
 import com.github.yufiriamazenta.craftorithm.recipe.custom.AnvilRecipe;
 import com.github.yufiriamazenta.craftorithm.recipe.custom.PotionMixRecipe;
 import crypticlib.CrypticLib;
+import crypticlib.chat.TextProcessor;
 import crypticlib.ui.display.Icon;
 import crypticlib.ui.menu.Menu;
-import crypticlib.util.TextUtil;
 import org.bukkit.Bukkit;
 import org.bukkit.Material;
 import org.bukkit.entity.Player;
@@ -97,7 +97,7 @@ else if (recipe instanceof SmokingRecipe) {
     @NotNull
     @Override
     public Inventory getInventory() {
-        Inventory inventory = Bukkit.createInventory(this, inventoryType, TextUtil.color(invTitle));
+        Inventory inventory = Bukkit.createInventory(this, inventoryType, TextProcessor.color(invTitle));
         for (Integer slot : slotMap().keySet()) {
             inventory.setItem(slot, slotMap().get(slot).display());
         }
diff --git a/src/main/java/com/github/yufiriamazenta/craftorithm/menu/display/RecipeGroupListMenuHolder.java b/src/main/java/com/github/yufiriamazenta/craftorithm/menu/display/RecipeGroupListMenuHolder.java
index f71b45af..2e9158df 100644
--- a/src/main/java/com/github/yufiriamazenta/craftorithm/menu/display/RecipeGroupListMenuHolder.java
+++ b/src/main/java/com/github/yufiriamazenta/craftorithm/menu/display/RecipeGroupListMenuHolder.java
@@ -2,9 +2,9 @@
 
 import com.github.yufiriamazenta.craftorithm.config.Languages;
 import com.github.yufiriamazenta.craftorithm.recipe.RecipeManager;
+import crypticlib.chat.TextProcessor;
 import crypticlib.ui.display.Icon;
 import crypticlib.ui.menu.Menu;
-import crypticlib.util.TextUtil;
 import org.bukkit.Bukkit;
 import org.bukkit.Material;
 import org.bukkit.entity.Player;
@@ -56,7 +56,7 @@ public RecipeGroupListMenuHolder(Player player) {
     @Override
     public Inventory getInventory() {
         resetIcons();
-        Inventory inventory = Bukkit.createInventory(this, 54, TextUtil.color(Languages.MENU_NEW_RECIPE_LIST_TITLE.value()));
+        Inventory inventory = Bukkit.createInventory(this, 54, TextProcessor.color(Languages.MENU_NEW_RECIPE_LIST_TITLE.value()));
         for (Integer slot : super.slotMap().keySet()) {
             inventory.setItem(slot, slotMap().get(slot).display());
         }
@@ -82,15 +82,15 @@ public void previousPage() {
     private void resetIcons() {
         slotMap().clear();
         int []frameSlots = {45, 47, 48, 49, 50, 51, 53};
-        Icon frameIcon = new Icon(Material.BLACK_STAINED_GLASS_PANE, TextUtil.color(Languages.MENU_NEW_RECIPE_LIST_ICON_FRAME.value()));
+        Icon frameIcon = new Icon(Material.BLACK_STAINED_GLASS_PANE, TextProcessor.color(Languages.MENU_NEW_RECIPE_LIST_ICON_FRAME.value()));
         for (int frameSlot : frameSlots) {
             slotMap().put(frameSlot, frameIcon);
         }
-        slotMap().put(46, new Icon(Material.PAPER, TextUtil.color(Languages.MENU_NEW_RECIPE_LIST_ICON_PREVIOUS.value()), (event -> {
+        slotMap().put(46, new Icon(Material.PAPER, TextProcessor.color(Languages.MENU_NEW_RECIPE_LIST_ICON_PREVIOUS.value()), (event -> {
             event.setCancelled(true);
             previousPage();
         })));
-        slotMap().put(52, new Icon(Material.PAPER, TextUtil.color(Languages.MENU_NEW_RECIPE_LIST_ICON_NEXT.value()), (event -> {
+        slotMap().put(52, new Icon(Material.PAPER, TextProcessor.color(Languages.MENU_NEW_RECIPE_LIST_ICON_NEXT.value()), (event -> {
             event.setCancelled(true);
             nextPage();
         })));
diff --git a/src/main/java/com/github/yufiriamazenta/craftorithm/menu/display/RecipeListMenuHolder.java b/src/main/java/com/github/yufiriamazenta/craftorithm/menu/display/RecipeListMenuHolder.java
index 0fd4368a..53f9e7c6 100644
--- a/src/main/java/com/github/yufiriamazenta/craftorithm/menu/display/RecipeListMenuHolder.java
+++ b/src/main/java/com/github/yufiriamazenta/craftorithm/menu/display/RecipeListMenuHolder.java
@@ -4,9 +4,9 @@
 import com.github.yufiriamazenta.craftorithm.config.Languages;
 import com.github.yufiriamazenta.craftorithm.recipe.RecipeManager;
 import crypticlib.CrypticLib;
+import crypticlib.chat.TextProcessor;
 import crypticlib.ui.display.Icon;
 import crypticlib.ui.menu.Menu;
-import crypticlib.util.TextUtil;
 import org.bukkit.Bukkit;
 import org.bukkit.Material;
 import org.bukkit.NamespacedKey;
@@ -85,15 +85,15 @@ public void previousPage() {
     private void resetIcons() {
         slotMap().clear();
         int []frame = {45, 47, 48, 49, 50, 51, 53};
-        Icon frameIcon = new Icon(Material.BLACK_STAINED_GLASS_PANE, TextUtil.color(Languages.MENU_RECIPE_LIST_ICON_FRAME.value()));
+        Icon frameIcon = new Icon(Material.BLACK_STAINED_GLASS_PANE, TextProcessor.color(Languages.MENU_RECIPE_LIST_ICON_FRAME.value()));
         for (int i : frame) {
             slotMap().put(i, frameIcon);
         }
-        slotMap().put(46, new Icon(Material.PAPER, TextUtil.color(Languages.MENU_RECIPE_LIST_ICON_PREVIOUS.value()), (event -> {
+        slotMap().put(46, new Icon(Material.PAPER, TextProcessor.color(Languages.MENU_RECIPE_LIST_ICON_PREVIOUS.value()), (event -> {
             event.setCancelled(true);
             previousPage();
         })));
-        slotMap().put(52, new Icon(Material.PAPER, TextUtil.color(Languages.MENU_RECIPE_LIST_ICON_NEXT.value()), (event -> {
+        slotMap().put(52, new Icon(Material.PAPER, TextProcessor.color(Languages.MENU_RECIPE_LIST_ICON_NEXT.value()), (event -> {
             event.setCancelled(true);
             nextPage();
         })));
@@ -135,7 +135,7 @@ public void onClose(InventoryCloseEvent event) {
     @Override
     public Inventory getInventory() {
         resetIcons();
-        Inventory inventory = Bukkit.createInventory(this, 54, TextUtil.color(Languages.MENU_RECIPE_LIST_TITLE.value()));
+        Inventory inventory = Bukkit.createInventory(this, 54, TextProcessor.color(Languages.MENU_RECIPE_LIST_TITLE.value()));
         for (Integer slot : slotMap().keySet()) {
             inventory.setItem(slot, slotMap().get(slot).display());
         }
diff --git a/src/main/java/com/github/yufiriamazenta/craftorithm/recipe/RecipeManager.java b/src/main/java/com/github/yufiriamazenta/craftorithm/recipe/RecipeManager.java
index caf3da2d..7d1431d5 100644
--- a/src/main/java/com/github/yufiriamazenta/craftorithm/recipe/RecipeManager.java
+++ b/src/main/java/com/github/yufiriamazenta/craftorithm/recipe/RecipeManager.java
@@ -11,7 +11,7 @@
 import com.github.yufiriamazenta.craftorithm.util.CollectionsUtil;
 import com.github.yufiriamazenta.craftorithm.util.LangUtil;
 import crypticlib.CrypticLib;
-import crypticlib.config.yaml.YamlConfigWrapper;
+import crypticlib.config.ConfigWrapper;
 import crypticlib.util.FileUtil;
 import org.bukkit.Bukkit;
 import org.bukkit.Keyed;
@@ -34,7 +34,7 @@ public enum RecipeManager {
 
     INSTANCE;
     public final File RECIPE_FILE_FOLDER = new File(Craftorithm.instance().getDataFolder().getPath(), "recipes");
-    private final YamlConfigWrapper removedRecipesConfigWrapper = new YamlConfigWrapper(Craftorithm.instance(), "removed_recipes.yml");
+    private final ConfigWrapper removedRecipesConfigWrapper = new ConfigWrapper(Craftorithm.instance(), "removed_recipes.yml");
     public final String PLUGIN_RECIPE_NAMESPACE = "craftorithm";
     private final Map<RecipeType, Map<String, RecipeGroup>> pluginRecipeMap;
     private final Map<RecipeType, Consumer<Recipe>> recipeRegisterMap;
@@ -45,7 +45,7 @@ public enum RecipeManager {
     private final Map<NamespacedKey, Recipe> serverRecipesCache;
     private final Map<NamespacedKey, PotionMixRecipe> potionMixRecipeMap;
     private final Map<NamespacedKey, AnvilRecipe> anvilRecipeMap;
-    private final Map<String, YamlConfigWrapper> recipeConfigWrapperMap;
+    private final Map<String, ConfigWrapper> recipeConfigWrapperMap;
     private boolean supportPotionMix;
 
     RecipeManager() {
@@ -118,7 +118,7 @@ public void reloadRecipeManager() {
     private void loadRecipes() {
         for (String fileName : recipeConfigWrapperMap.keySet()) {
             try {
-                YamlConfigWrapper configWrapper = recipeConfigWrapperMap.get(fileName);
+                ConfigWrapper configWrapper = recipeConfigWrapperMap.get(fileName);
                 YamlConfiguration config = configWrapper.config();
                 boolean unlock =  config.getBoolean("unlock", PluginConfigs.DEFAULT_RECIPE_UNLOCK.value());
                 for (RecipeRegistry recipeRegistry : RecipeFactory.newRecipeRegistry(config, fileName)) {
@@ -127,7 +127,7 @@ private void loadRecipes() {
                 }
                 recipeSortMap.put(fileName, config.getInt("sort_id", 0));
             } catch (Throwable e) {
-                LangUtil.info(Languages.LOAD_RECIPE_LOAD_EXCEPTION.value(), CollectionsUtil.newStringHashMap("<recipe_name>", fileName));
+                LangUtil.info(Languages.LOAD_RECIPE_LOAD_EXCEPTION, CollectionsUtil.newStringHashMap("<recipe_name>", fileName));
                 e.printStackTrace();
             }
         }
@@ -149,7 +149,7 @@ private void loadRecipeFiles() {
             key = key.replace("\\", "/");
             int lastDotIndex = key.lastIndexOf(".");
             key = key.substring(0, lastDotIndex);
-            recipeConfigWrapperMap.put(key, new YamlConfigWrapper(file));
+            recipeConfigWrapperMap.put(key, new ConfigWrapper(file));
         }
     }
 
@@ -228,7 +228,7 @@ public boolean removeCraftorithmRecipe(String recipeGroupName, boolean deleteFil
                 if (recipeGroup == null)
                     return false;
                 recipeRemoverMap.get(recipeType).accept(recipeGroup.groupRecipeKeys());
-                YamlConfigWrapper recipeConfig = recipeConfigWrapperMap.get(recipeGroupName);
+                ConfigWrapper recipeConfig = recipeConfigWrapperMap.get(recipeGroupName);
                 if (recipeConfig != null && deleteFile) {
                     recipeConfig.configFile().delete();
                 }
@@ -434,7 +434,7 @@ public Map<NamespacedKey, PotionMixRecipe> potionMixRecipeMap() {
         return potionMixRecipeMap;
     }
 
-    public Map<String, YamlConfigWrapper> recipeConfigWrapperMap() {
+    public Map<String, ConfigWrapper> recipeConfigWrapperMap() {
         return recipeConfigWrapperMap;
     }
 
diff --git a/src/main/java/com/github/yufiriamazenta/craftorithm/util/ItemUtils.java b/src/main/java/com/github/yufiriamazenta/craftorithm/util/ItemUtils.java
index 0c5b032d..493449d8 100644
--- a/src/main/java/com/github/yufiriamazenta/craftorithm/util/ItemUtils.java
+++ b/src/main/java/com/github/yufiriamazenta/craftorithm/util/ItemUtils.java
@@ -4,8 +4,8 @@
 import com.github.yufiriamazenta.craftorithm.item.ItemManager;
 import com.github.yufiriamazenta.craftorithm.item.impl.CraftorithmItemProvider;
 import com.google.common.base.Preconditions;
+import crypticlib.chat.TextProcessor;
 import crypticlib.util.ItemUtil;
-import crypticlib.util.TextUtil;
 import org.bukkit.inventory.ItemStack;
 import org.bukkit.inventory.meta.ItemMeta;
 
@@ -26,7 +26,7 @@ public class ItemUtils {
     }
 
     public static void reloadCannotCraftLore() {
-        cannotCraftLore = TextUtil.color(PluginConfigs.LORE_CANNOT_CRAFT.value());
+        cannotCraftLore = TextProcessor.color(PluginConfigs.LORE_CANNOT_CRAFT.value());
         try {
             cannotCraftLorePattern = Pattern.compile(cannotCraftLore);
             cannotCraftLoreIsRegex = true;
@@ -101,7 +101,7 @@ public static void setLore(ItemStack item, List<String> lore, boolean format) {
         ItemMeta itemMeta = item.getItemMeta();
         itemMeta.setLore(lore);
         if (format)
-            itemMeta.getLore().replaceAll(TextUtil::color);
+            itemMeta.getLore().replaceAll(TextProcessor::color);
     }
 
 }
diff --git a/src/main/java/com/github/yufiriamazenta/craftorithm/util/LangUtil.java b/src/main/java/com/github/yufiriamazenta/craftorithm/util/LangUtil.java
index 994fbbaa..34f8be4a 100644
--- a/src/main/java/com/github/yufiriamazenta/craftorithm/util/LangUtil.java
+++ b/src/main/java/com/github/yufiriamazenta/craftorithm/util/LangUtil.java
@@ -2,7 +2,10 @@
 
 import com.github.yufiriamazenta.craftorithm.Craftorithm;
 import com.github.yufiriamazenta.craftorithm.config.Languages;
-import crypticlib.util.TextUtil;
+import crypticlib.chat.MessageSender;
+import crypticlib.chat.TextProcessor;
+import crypticlib.chat.entry.LangConfigEntry;
+import crypticlib.chat.entry.StringLangConfigEntry;
 import org.bukkit.Bukkit;
 import org.bukkit.command.CommandSender;
 import org.bukkit.entity.Player;
@@ -12,30 +15,24 @@
 
 public class LangUtil {
 
-    public static void sendLang(CommandSender receiver, String msgKey) {
-        sendLang(receiver, msgKey, new HashMap<>());
+    public static void sendLang(CommandSender receiver, StringLangConfigEntry message) {
+        sendLang(receiver, message, new HashMap<>());
     }
 
-    public static void sendLang(CommandSender receiver, String message, Map<String, String> formatMap) {
+    public static void sendLang(CommandSender receiver, StringLangConfigEntry message, Map<String, String> formatMap) {
         if (receiver == null) {
             return;
         }
         formatMap.put("<prefix>", Languages.PREFIX.value());
         formatMap.put("<version>", Craftorithm.instance().getDescription().getVersion());
-
-        for (String formatStr : formatMap.keySet()) {
-            message = message.replace(formatStr, formatMap.get(formatStr));
-        }
-        if (receiver instanceof Player)
-            message = TextUtil.placeholder((Player) receiver, message);
-        receiver.sendMessage(TextUtil.color(message));
+        MessageSender.sendMsg(receiver, message, formatMap);
     }
 
-    public static void info(String message) {
+    public static void info(StringLangConfigEntry message) {
         sendLang(Bukkit.getConsoleSender(), message);
     }
 
-    public static void info(String message, Map<String, String> map) {
+    public static void info(StringLangConfigEntry message, Map<String, String> map) {
         sendLang(Bukkit.getConsoleSender(), message, map);
     }
 
diff --git a/src/main/java/com/github/yufiriamazenta/craftorithm/util/PluginHookUtil.java b/src/main/java/com/github/yufiriamazenta/craftorithm/util/PluginHookUtil.java
index 3f4f87f6..58c99daf 100644
--- a/src/main/java/com/github/yufiriamazenta/craftorithm/util/PluginHookUtil.java
+++ b/src/main/java/com/github/yufiriamazenta/craftorithm/util/PluginHookUtil.java
@@ -27,17 +27,17 @@ public static void hookPlugins() {
     private static void hookVault() {
         economyLoaded = Bukkit.getPluginManager().isPluginEnabled("Vault");
         if (!economyLoaded) {
-            LangUtil.info(Languages.LOAD_HOOK_PLUGIN_NOT_EXIST.value(), CollectionsUtil.newStringHashMap("<plugin>", "Vault"));
+            LangUtil.info(Languages.LOAD_HOOK_PLUGIN_NOT_EXIST, CollectionsUtil.newStringHashMap("<plugin>", "Vault"));
             return;
         }
         RegisteredServiceProvider<Economy> vaultRsp = Bukkit.getServer().getServicesManager().getRegistration(Economy.class);
         if (vaultRsp == null) {
             economyLoaded = false;
-            LangUtil.info(Languages.LOAD_HOOK_PLUGIN_NOT_EXIST.value(), CollectionsUtil.newStringHashMap("<plugin>", "Vault"));
+            LangUtil.info(Languages.LOAD_HOOK_PLUGIN_NOT_EXIST, CollectionsUtil.newStringHashMap("<plugin>", "Vault"));
             return;
         }
 
-        LangUtil.info(Languages.LOAD_HOOK_PLUGIN_SUCCESS.value(), CollectionsUtil.newStringHashMap("<plugin>", "Vault"));
+        LangUtil.info(Languages.LOAD_HOOK_PLUGIN_SUCCESS, CollectionsUtil.newStringHashMap("<plugin>", "Vault"));
         economyLoaded = true;
         economy = vaultRsp.getProvider();
     }
@@ -52,9 +52,9 @@ private static void hookPlayerPoints() {
         pointsLoaded = Bukkit.getPluginManager().isPluginEnabled("PlayerPoints");
         if (pointsLoaded) {
             playerPoints = (PlayerPoints) Bukkit.getPluginManager().getPlugin("PlayerPoints");
-            LangUtil.info(Languages.LOAD_HOOK_PLUGIN_SUCCESS.value(), CollectionsUtil.newStringHashMap("<plugin>", "PlayerPoints"));
+            LangUtil.info(Languages.LOAD_HOOK_PLUGIN_SUCCESS, CollectionsUtil.newStringHashMap("<plugin>", "PlayerPoints"));
         } else
-            LangUtil.info(Languages.LOAD_HOOK_PLUGIN_NOT_EXIST.value(), CollectionsUtil.newStringHashMap("<plugin>", "PlayerPoints"));
+            LangUtil.info(Languages.LOAD_HOOK_PLUGIN_NOT_EXIST, CollectionsUtil.newStringHashMap("<plugin>", "PlayerPoints"));
     }
 
     public static boolean isPlayerPointsLoaded() { return pointsLoaded; }
@@ -67,50 +67,50 @@ private static void hookItemsAdder() {
         itemsAdderLoaded = Bukkit.getPluginManager().isPluginEnabled("ItemsAdder");
         if (itemsAdderLoaded) {
             ItemManager.INSTANCE.regItemProvider(ItemsAdderItemProvider.INSTANCE);
-            LangUtil.info(Languages.LOAD_HOOK_PLUGIN_SUCCESS.value(), CollectionsUtil.newStringHashMap("<plugin>", "ItemsAdder"));
+            LangUtil.info(Languages.LOAD_HOOK_PLUGIN_SUCCESS, CollectionsUtil.newStringHashMap("<plugin>", "ItemsAdder"));
         }
         else
-            LangUtil.info(Languages.LOAD_HOOK_PLUGIN_NOT_EXIST.value(), CollectionsUtil.newStringHashMap("<plugin>", "ItemsAdder"));
+            LangUtil.info(Languages.LOAD_HOOK_PLUGIN_NOT_EXIST, CollectionsUtil.newStringHashMap("<plugin>", "ItemsAdder"));
     }
 
     private static void hookOraxen() {
         oraxenLoaded = Bukkit.getPluginManager().isPluginEnabled("Oraxen");
         if (oraxenLoaded) {
             ItemManager.INSTANCE.regItemProvider(OraxenItemProvider.INSTANCE);
-            LangUtil.info(Languages.LOAD_HOOK_PLUGIN_SUCCESS.value(), CollectionsUtil.newStringHashMap("<plugin>", "Oraxen"));
+            LangUtil.info(Languages.LOAD_HOOK_PLUGIN_SUCCESS, CollectionsUtil.newStringHashMap("<plugin>", "Oraxen"));
         }
         else
-            LangUtil.info(Languages.LOAD_HOOK_PLUGIN_NOT_EXIST.value(), CollectionsUtil.newStringHashMap("<plugin>", "Oraxen"));
+            LangUtil.info(Languages.LOAD_HOOK_PLUGIN_NOT_EXIST, CollectionsUtil.newStringHashMap("<plugin>", "Oraxen"));
     }
 
     private static void hookMythicMobs() {
         mythicLoaded = Bukkit.getPluginManager().isPluginEnabled("MythicMobs");
         if (mythicLoaded) {
             ItemManager.INSTANCE.regItemProvider(MythicMobsItemProvider.INSTANCE);
-            LangUtil.info(Languages.LOAD_HOOK_PLUGIN_SUCCESS.value(), CollectionsUtil.newStringHashMap("<plugin>", "MythicMobs"));
+            LangUtil.info(Languages.LOAD_HOOK_PLUGIN_SUCCESS, CollectionsUtil.newStringHashMap("<plugin>", "MythicMobs"));
         }
         else
-            LangUtil.info(Languages.LOAD_HOOK_PLUGIN_NOT_EXIST.value(), CollectionsUtil.newStringHashMap("<plugin>", "MythicMobs"));
+            LangUtil.info(Languages.LOAD_HOOK_PLUGIN_NOT_EXIST, CollectionsUtil.newStringHashMap("<plugin>", "MythicMobs"));
     }
 
     private static void hookNeigeItems() {
         neigeItemsLoaded = Bukkit.getPluginManager().isPluginEnabled("NeigeItems");
         if (neigeItemsLoaded) {
             ItemManager.INSTANCE.regItemProvider(NeigeItemsItemProvider.INSTANCE);
-            LangUtil.info(Languages.LOAD_HOOK_PLUGIN_SUCCESS.value(), CollectionsUtil.newStringHashMap("<plugin>", "NeigeItems"));
+            LangUtil.info(Languages.LOAD_HOOK_PLUGIN_SUCCESS, CollectionsUtil.newStringHashMap("<plugin>", "NeigeItems"));
         }
         else
-            LangUtil.info(Languages.LOAD_HOOK_PLUGIN_NOT_EXIST.value(), CollectionsUtil.newStringHashMap("<plugin>", "NeigeItems"));
+            LangUtil.info(Languages.LOAD_HOOK_PLUGIN_NOT_EXIST, CollectionsUtil.newStringHashMap("<plugin>", "NeigeItems"));
     }
 
     private static void hookMMOItems() {
         mmoitemsLoaded = Bukkit.getPluginManager().isPluginEnabled("MMOItems");
         if (mmoitemsLoaded) {
             ItemManager.INSTANCE.regItemProvider(MMOItemsItemProvider.INSTANCE);
-            LangUtil.info(Languages.LOAD_HOOK_PLUGIN_SUCCESS.value(), CollectionsUtil.newStringHashMap("<plugin>", "MMOItems"));
+            LangUtil.info(Languages.LOAD_HOOK_PLUGIN_SUCCESS, CollectionsUtil.newStringHashMap("<plugin>", "MMOItems"));
         }
         else
-            LangUtil.info(Languages.LOAD_HOOK_PLUGIN_NOT_EXIST.value(), CollectionsUtil.newStringHashMap("<plugin>", "MMOItems"));
+            LangUtil.info(Languages.LOAD_HOOK_PLUGIN_NOT_EXIST, CollectionsUtil.newStringHashMap("<plugin>", "MMOItems"));
     }
 
     public static boolean isItemsAdderLoaded() {
diff --git a/src/main/java/com/github/yufiriamazenta/craftorithm/util/UpdateUtil.java b/src/main/java/com/github/yufiriamazenta/craftorithm/util/UpdateUtil.java
index 9f84ae1b..b40099cb 100644
--- a/src/main/java/com/github/yufiriamazenta/craftorithm/util/UpdateUtil.java
+++ b/src/main/java/com/github/yufiriamazenta/craftorithm/util/UpdateUtil.java
@@ -29,7 +29,7 @@ public static void pullUpdateCheckRequest(CommandSender sender) {
                 pluginVersion = pluginVersion.substring(0, pluginVersion.indexOf("-"));
                 if (checkVersion(latestVersion, pluginVersion)) {
                     CrypticLib.platform().scheduler().runTask(Craftorithm.instance(), () -> {
-                        LangUtil.sendLang(sender, Languages.NEW_VERSION.value(), CollectionsUtil.newStringHashMap("<new_version>", latestVersion));
+                        LangUtil.sendLang(sender, Languages.NEW_VERSION, CollectionsUtil.newStringHashMap("<new_version>", latestVersion));
                     });
                 }
                 is.close();
diff --git a/src/main/resources/lang/en_us.yml b/src/main/resources/lang/en_us.yml
new file mode 100644
index 00000000..4b91323f
--- /dev/null
+++ b/src/main/resources/lang/en_us.yml
@@ -0,0 +1,115 @@
+prefix: '&8[&3Craftorithm&8]'
+unsupported_version: '<prefix> Unsupported Version'
+new_version: '<prefix> &aDetected a new version <new_version>, please update to the latest version promptly!'
+#使用命令的一些反馈消息
+command:
+  no_perm: '<prefix> &cYou do not have permission to use this command.'
+  player_only: '<prefix> &cOnly players can execute this command.'
+  not_enough_param: '<prefix> &cThe Command is missing parameters, <number> parameters required.'
+  undefined_subcmd: '<prefix> &cUndefined subcommand!'
+  item:
+    save:
+      success: '<prefix> &aItem saved successfully.'
+      failed_save_air: '<prefix> &cItem save failed. Reason: Cannot save a non-existent item.'
+    give:
+      success: '<prefix> &aGive item successfully'
+      not_exist_item: '<prefix> &cItem <item_name> does not exist.'
+      player_offline: '<prefix> &cThe player is not online or does not have a profile.'
+  reload:
+    success: '<prefix> &aPlugin reload!'
+    exception: '<prefix> &cError occurred during plugin reload, please check the console.'
+  remove:
+    success: '<prefix> &aRecipe removed successfully.'
+    not_exist: '<prefix> &cRecipe does not exist.'
+  disable:
+    success: '<prefix> &cRecipe disabled successfully.'
+    not_exist: '<prefix> &cRecipe does not exist or has already been disabled.'
+    failed: '<prefix> &cFailed to disable recipe, it may already be disabled or does not exist.'
+  version: '<prefix> &aPlugin version: <version>'
+  create:
+    unsupported_recipe_type: '<prefix> &cUnsupported recipe type.'
+    unsupported_recipe_name: '<prefix> &cUnsupported recipe name, only [a-z0-9/._-]+ characters are allowed.'
+    name_used: '<prefix> &cRecipe ID has already been used.'
+    null_result: '<prefix> &cRecipe result cannot be empty!'
+    null_source: '<prefix> &cRecipe ingredients cannot be empty!'
+    success: '<prefix> &a<recipe_type> recipe <recipe_name> created successfully.'
+  run_arcenciel:
+    success: '<prefix> &aExecution successful, took <time> ms.'
+  list:
+    unsupported_version: '<prefix> &cThis feature is only available in version 1.16 and above.'
+menu:
+  recipe_list:
+    title: '&3&lRecipe List'
+    icon:
+      frame: '&3&lRecipe List'
+      previous: '&aPrevious Page'
+      next: '&aNext Page'
+  new_recipe_list:
+    title: '&3&lCraftorithm New Recipe List'
+    icon:
+      frame: '&3&lNew recipe list'
+      previous: '&aPrevious Page'
+      next: '&aNext Page'
+  recipe_display:
+    title:
+      shaped: Shaped Recipe
+      shapeless: Shapeless Recipe
+      furnace: Furnace Recipe
+      blasting: Blast Furnace Recipe
+      smoking: Smoker Recipe
+      campfire: Campfire Recipe
+      smithing: Smithing Recipe
+      stone_cutting: Stonecutter Recipe
+      potion: Brewing Recipe
+      anvil: Anvil Recipe
+  recipe_creator:
+    title: '&3Creating <recipe_type> recipe: <recipe_name>'
+    icon:
+      frame: '&aCreating Recipe'
+      result_frame: '&aRecipe Result'
+      confirm: '&3&lConfirm Creation'
+      unlock: '&aUnlock Recipe for Player: <unlock>'
+      cooking_frame: '&aCooking Ingredients'
+      furnace_toggle: '&aEnable Furnace Recipe: <enable>'
+      blast_furnace_toggle: '&aEnable Blast Furnace Recipe: <enable>'
+      smoker_toggle: '&aEnable Smoker Recipe: <enable>'
+      campfire_toggle: '&aEnable Campfire Recipe: <enable>'
+      cooking_time:
+        name: '&aCooking Time: <time> tick'
+        lore:
+          - '&3Click to Modify Cooking Time'
+        input_hint: '&aPlease enter cooking time in ticks. Type ''cancel'' to cancel.'
+      cooking_exp:
+        name: '&aExperience Reward: <exp>'
+        lore:
+          - '&3Click to Modify Experience Reward. Type ''cancel'' to cancel.'
+        input_hint: '&aPlease enter experience reward.'
+      smithing_frame: '&aSmithing Ingredients'
+      potion_frame: '&aBrewing Ingredients'
+      anvil_frame: '&aAnvil Ingredients'
+      anvil_copy_nbt_toggle: '&aPreserve Item NBT: <enable>'
+      anvil_cost_level:
+        name: '&aRequired Level: <level>'
+        lore:
+          - '&3Click to Modify Required Level'
+        input_hint: '&aPlease enter required level. Type ''cancel'' to cancel.'
+recipe_type_name:
+  shaped: Shaped
+  shapeless: Shapeless
+  cooking: Cooking
+  smithing: Smithing
+  stone_cutting: Stonecutting
+  potion: Brewing
+  anvil: Anvil
+#Arcenciel脚本的提示消息
+arcenciel:
+  not_enough_param: '<prefix> &cStatement "<statement>" is incomplete.'
+  unknown_token: '<prefix> &cUndefined keyword or function: <token>'
+#插件加载的反馈信息
+load:
+  finish: '<prefix> &aPlugin loaded successfully.'
+  recipe_load_exception: '<prefix> &cError occurred while loading recipe <recipe_name>.'
+  item_load_exception: '<prefix> &cError occurred while loading item <item_name>.'
+  hook_plugin:
+    success: '<prefix> &aFound <plugin>, hooked successfully.'
+    not_exist: '<prefix> &cPlugin <plugin> not found.'
diff --git a/src/main/resources/lang.yml b/src/main/resources/lang/zh_cn.yml
similarity index 100%
rename from src/main/resources/lang.yml
rename to src/main/resources/lang/zh_cn.yml
diff --git a/src/main/resources/lang/zh_tw.yml b/src/main/resources/lang/zh_tw.yml
new file mode 100644
index 00000000..b9fbb2f4
--- /dev/null
+++ b/src/main/resources/lang/zh_tw.yml
@@ -0,0 +1,115 @@
+prefix: '&8[&3Craftorithm&8]'
+unsupported_version: '<prefix> 不支援的版本。'
+new_version: '<prefix> &a偵測到有新版本<new_version>,請及時更新到新版本!'
+#使用命令的一些反馈消息
+command:
+  no_perm: '<prefix> &c你沒有使用此指令的權限。'
+  player_only: '<prefix> &c只有玩家才能執行此指令。'
+  not_enough_param: '<prefix> &c指令缺少參數,缺少<number>個參數。'
+  undefined_subcmd: '<prefix> &c未定義的子指令。'
+  item:
+    save:
+      success: '<prefix> &a物品保存成功。'
+      failed_save_air: '<prefix> &c物品保存失敗,原因:無法保存不存在的物品。'
+    give:
+      success: '<prefix> &a物品獲取成功。'
+      not_exist_item: '<prefix> &c不存在物品 <item_name>。'
+      player_offline: '<prefix> &c該玩家不在線上或不存在。'
+  reload:
+    success: '<prefix> &a插件重載成功。'
+    exception: '<prefix> &c插件重載過程中發生錯誤,請查看控制台。'
+  remove:
+    success: '<prefix> &a配方刪除成功。'
+    not_exist: '<prefix> &c配方不存在。'
+  disable:
+    success: '<prefix> &c禁用配方成功。'
+    not_exist: '<prefix> &c配方不存在或已經被禁用。'
+    failed: '<prefix> &c配方禁用失敗,可能已被禁用或不存在。'
+  version: '<prefix> &a插件版本:<version>。'
+  create:
+    unsupported_recipe_type: '<prefix> &c不支援的配方類型。'
+    unsupported_recipe_name: '<prefix> &c不支援的配方名稱,只能使用[a-z0-9/._-]+允許的內容。'
+    name_used: '<prefix> &c配方ID已經被使用。'
+    null_result: '<prefix> &c配方結果不允許為空!'
+    null_source: '<prefix> &c配方原料不允許為空!'
+    success: '<prefix> &a<recipe_type>類型配方<recipe_name>創建成功'
+  run_arcenciel:
+    success: '<prefix> &a運行成功,耗時<time>毫秒。'
+  list:
+    unsupported_version: '<prefix> &c此功能僅在1.16及以上版本可用。'
+menu:
+  recipe_list:
+    title: '&3&l配方列表'
+    icon:
+      frame: '&3&l配方列表'
+      previous: '&a上一頁'
+      next: '&a下一頁'
+  new_recipe_list:
+    title: '&3&lCraftorithm新增配方列表'
+    icon:
+      frame: '&3&l新增配方列表'
+      previous: '&a上一頁'
+      next: '&a下一頁'
+  recipe_display:
+    title:
+      shaped: 有序配方
+      shapeless: 無序配方
+      furnace: 熔爐配方
+      blasting: 高爐配方
+      smoking: 煙燻爐配方
+      campfire: 營火配方
+      smithing: 鍛造配方
+      stone_cutting: 切石配方
+      potion: 釀造配方
+      anvil: 鐵砧配方
+  recipe_creator:
+    title: '&3創建<recipe_type>配方: <recipe_name>'
+    icon:
+      frame: '&a創建配方'
+      result_frame: '&a配方結果'
+      confirm: '&3&l確認創建'
+      unlock: '&a是否為玩家解鎖配方:<unlock>'
+      cooking_frame: '&a燒煉原料'
+      furnace_toggle: '&a啟用熔爐配方:<enable>'
+      blast_furnace_toggle: '&a啟用高爐配方:<enable>'
+      smoker_toggle: '&a啟用煙燻爐配方:<enable>'
+      campfire_toggle: '&a啟用營火配方:<enable>'
+      cooking_time:
+        name: '&a燒煉時間: <time> tick'
+        lore:
+          - '&3點擊修改燒煉時間'
+        input_hint: '&a請輸入燒煉時間,單位為tick,輸入"cancel"取消。'
+      cooking_exp:
+        name: '&a獎勵經驗值: <exp>'
+        lore:
+          - '&3點擊修改獎勵經驗,輸入"cancel"取消。'
+        input_hint: '&a請輸入獎勵經驗'
+      smithing_frame: '&a鍛造物品'
+      potion_frame: '&a釀造原料'
+      anvil_frame: '&a製作材料'
+      anvil_copy_nbt_toggle: '&a保留物品NBT:<enable>'
+      anvil_cost_level:
+        name: '&a所需等級: <level>'
+        lore:
+          - '&3點擊修改所需等級'
+        input_hint: '&a請輸入所需等級,輸入“cancel”取消。'
+recipe_type_name:
+  shaped: 有序
+  shapeless: 無序
+  cooking: 煉製
+  smithing: 鍛造
+  stone_cutting: 切石
+  potion: 釀造
+  anvil: 鐵砧
+#Arcenciel脚本的提示消息
+arcenciel:
+  not_enough_param: '<prefix> &c語句"<statement>"不完整'
+  unknown_token: '<prefix> &c未定義的關鍵字或函式<token>'
+#插件加载的反馈信息
+load:
+  finish: '<prefix> &a插件載入成功'
+  recipe_load_exception: '<prefix> &c載入配方<recipe_name>時發生錯誤。'
+  item_load_exception: '<prefix> &c載入物品<item_name>時發生錯誤。'
+  hook_plugin:
+    success: '<prefix> &a發現<plugin>,已連結。'
+    not_exist: '<prefix> &c未發現<plugin>。'