From a915cbbe4b2f914a052cfbc02e775b2e6c4edb95 Mon Sep 17 00:00:00 2001 From: ChomeNS <95471003+ChomeNS@users.noreply.github.com> Date: Tue, 6 May 2025 16:11:09 +0700 Subject: [PATCH] feat: localization (hopefully i didn't miss anything but surely i will) it took around 4 hours but i think it's pretty normal for such things like this --- build-number.txt | 2 +- .../java/me/chayapak1/chomens_bot/Main.java | 9 +- .../chomens_bot/command/Command.java | 8 - .../chomens_bot/command/CommandContext.java | 30 +- .../chomens_bot/command/TrustLevel.java | 9 +- .../contexts/ChomeNSModCommandContext.java | 3 +- .../contexts/ConsoleCommandContext.java | 3 +- .../contexts/DiscordCommandContext.java | 6 +- .../command/contexts/IRCCommandContext.java | 3 +- .../contexts/PlayerCommandContext.java | 5 +- .../contexts/RemoteCommandContext.java | 3 +- .../commands/BotVisibilityCommand.java | 30 +- .../chomens_bot/commands/BruhifyCommand.java | 1 - .../commands/ClearChatCommand.java | 16 +- .../commands/ClearChatQueueCommand.java | 8 +- .../chomens_bot/commands/CloopCommand.java | 18 +- .../commands/CommandBlockCommand.java | 28 +- .../chomens_bot/commands/ConsoleCommand.java | 39 ++- .../chomens_bot/commands/CowsayCommand.java | 1 - .../chomens_bot/commands/EchoCommand.java | 3 +- .../chomens_bot/commands/EndCommand.java | 4 +- .../chomens_bot/commands/EvalCommand.java | 7 +- .../chomens_bot/commands/FilterCommand.java | 49 +-- .../chomens_bot/commands/FindAltsCommand.java | 8 +- .../chomens_bot/commands/GrepLogCommand.java | 16 +- .../chomens_bot/commands/HelpCommand.java | 32 +- .../chomens_bot/commands/IPFilterCommand.java | 47 +-- .../chomens_bot/commands/InfoCommand.java | 161 +++++---- .../chomens_bot/commands/KickCommand.java | 20 +- .../chomens_bot/commands/ListCommand.java | 74 ++--- .../chomens_bot/commands/MailCommand.java | 50 ++- .../chomens_bot/commands/MusicCommand.java | 199 +++++------ .../commands/NetCommandCommand.java | 3 +- .../commands/NetMessageCommand.java | 10 +- .../commands/RandomTeleportCommand.java | 14 +- .../commands/RefillCoreCommand.java | 8 +- .../chomens_bot/commands/RestartCommand.java | 6 +- .../commands/ScreenshareCommand.java | 4 +- .../chomens_bot/commands/SeenCommand.java | 37 ++- .../commands/ServerEvalCommand.java | 3 +- .../chomens_bot/commands/StopCommand.java | 3 +- .../chomens_bot/commands/TPSBarCommand.java | 21 +- .../chomens_bot/commands/TestCommand.java | 3 +- .../chomens_bot/commands/TimeCommand.java | 8 +- .../commands/TranslateCommand.java | 7 +- .../chomens_bot/commands/UUIDCommand.java | 27 +- .../chomens_bot/commands/UrbanCommand.java | 48 +-- .../chomens_bot/commands/ValidateCommand.java | 23 +- .../chomens_bot/commands/WeatherCommand.java | 8 +- .../commands/WhitelistCommand.java | 29 +- .../commands/WikipediaCommand.java | 9 +- .../chomens_bot/data/logging/LogType.java | 17 +- .../chomens_bot/plugins/AuthPlugin.java | 7 +- .../plugins/ChomeNSModIntegrationPlugin.java | 3 +- .../plugins/CommandHandlerPlugin.java | 88 ++++- .../chomens_bot/plugins/DiscordPlugin.java | 22 +- .../chomens_bot/plugins/GrepLogPlugin.java | 18 +- .../chomens_bot/plugins/IRCPlugin.java | 3 +- .../chomens_bot/plugins/LoggerPlugin.java | 10 +- .../plugins/MusicPlayerPlugin.java | 26 +- .../chomens_bot/plugins/TrustedPlugin.java | 15 +- .../chomens_bot/plugins/VoiceChatPlugin.java | 5 +- .../chomens_bot/util/ComponentUtilities.java | 2 +- .../chomens_bot/util/I18nUtilities.java | 67 ++++ src/main/resources/language-en_us.json | 308 ++++++++++++++++++ .../{language.json => minecraftLanguage.json} | 0 66 files changed, 1098 insertions(+), 656 deletions(-) create mode 100644 src/main/java/me/chayapak1/chomens_bot/util/I18nUtilities.java create mode 100644 src/main/resources/language-en_us.json rename src/main/resources/{language.json => minecraftLanguage.json} (100%) diff --git a/build-number.txt b/build-number.txt index 05bd5c3c..9d0683e6 100644 --- a/build-number.txt +++ b/build-number.txt @@ -1 +1 @@ -3118 \ No newline at end of file +3142 \ No newline at end of file diff --git a/src/main/java/me/chayapak1/chomens_bot/Main.java b/src/main/java/me/chayapak1/chomens_bot/Main.java index a7edd69d..b2e2f815 100644 --- a/src/main/java/me/chayapak1/chomens_bot/Main.java +++ b/src/main/java/me/chayapak1/chomens_bot/Main.java @@ -8,6 +8,7 @@ import me.chayapak1.chomens_bot.plugins.DiscordPlugin; import me.chayapak1.chomens_bot.plugins.IRCPlugin; import me.chayapak1.chomens_bot.util.ArrayUtilities; import me.chayapak1.chomens_bot.util.HttpUtilities; +import me.chayapak1.chomens_bot.util.I18nUtilities; import me.chayapak1.chomens_bot.util.LoggerUtilities; import net.dv8tion.jda.api.requests.restaction.MessageCreateAction; import org.yaml.snakeyaml.LoaderOptions; @@ -147,7 +148,7 @@ public class Main { if (config.discord.enabled) discord = new DiscordPlugin(config); if (config.irc.enabled) irc = new IRCPlugin(config); - LoggerUtilities.log("Initialized all bots. Now connecting"); + LoggerUtilities.log(I18nUtilities.get("initialized")); for (final Bot bot : bots) bot.connect(); } catch (final Exception e) { @@ -183,9 +184,9 @@ public class Main { else stopping = true; final String stoppingMessage = String.format( - "%s (%s)", - type != null ? type : "Stopping..", - reason != null ? reason : "No reason given" + I18nUtilities.get("info.stopping.generic"), + type != null ? type : I18nUtilities.get("info.stopping"), + reason != null ? reason : I18nUtilities.get("info.no_reason") ); LoggerUtilities.log(stoppingMessage); diff --git a/src/main/java/me/chayapak1/chomens_bot/command/Command.java b/src/main/java/me/chayapak1/chomens_bot/command/Command.java index 0f104822..642668e4 100644 --- a/src/main/java/me/chayapak1/chomens_bot/command/Command.java +++ b/src/main/java/me/chayapak1/chomens_bot/command/Command.java @@ -7,7 +7,6 @@ import java.util.Arrays; public abstract class Command { public final String name; - public final String description; public String[] usages; public final String[] aliases; public final TrustLevel trustLevel; @@ -16,13 +15,11 @@ public abstract class Command { public Command ( final String name, - final String description, final String[] usages, final String[] aliases, final TrustLevel trustLevel ) { this.name = name; - this.description = description; this.usages = usages; this.aliases = aliases; this.trustLevel = trustLevel; @@ -31,14 +28,12 @@ public abstract class Command { public Command ( final String name, - final String description, final String[] usages, final String[] aliases, final TrustLevel trustLevel, final boolean consoleOnly ) { this.name = name; - this.description = description; this.usages = usages; this.aliases = aliases; this.trustLevel = trustLevel; @@ -47,7 +42,6 @@ public abstract class Command { public Command ( final String name, - final String description, final String[] usages, final String[] aliases, final TrustLevel trustLevel, @@ -55,7 +49,6 @@ public abstract class Command { final ChatPacketType[] disallowedPacketTypes ) { this.name = name; - this.description = description; this.usages = usages; this.aliases = aliases; this.trustLevel = trustLevel; @@ -69,7 +62,6 @@ public abstract class Command { public String toString () { return "Command{" + "name='" + name + '\'' + - ", description='" + description + '\'' + ", usages=" + Arrays.toString(usages) + ", aliases=" + Arrays.toString(aliases) + ", trustLevel=" + trustLevel + diff --git a/src/main/java/me/chayapak1/chomens_bot/command/CommandContext.java b/src/main/java/me/chayapak1/chomens_bot/command/CommandContext.java index 8fa07c64..8f227464 100644 --- a/src/main/java/me/chayapak1/chomens_bot/command/CommandContext.java +++ b/src/main/java/me/chayapak1/chomens_bot/command/CommandContext.java @@ -62,7 +62,7 @@ public class CommandContext { if (required) { throw new CommandException( Component.translatable( - "Expected %s at position %s (%s %s)%s", + "arguments_parsing.error.expected_string", Component.text(type), Component.text(argsPosition), Component.text(prefix + userInputCommandName), @@ -79,7 +79,7 @@ public class CommandContext { Component.translatable("[%s]") .arguments( Component - .text("click for usages") + .translatable("arguments_parsing.hover.usages") .clickEvent(ClickEvent.suggestCommand(prefix + "help " + this.commandName)) ) ) : @@ -112,14 +112,10 @@ public class CommandContext { if (greedyString.charAt(pointer - 1) != quote) { throw new CommandException( Component - .translatable("Unterminated quote at %s <-- %s") + .translatable("arguments_parsing.error.unterminated_quote") .arguments( - Component - .text(greedyString) - .color(bot.colorPalette.string), - Component - .text(quote) - .color(NamedTextColor.YELLOW) + Component.text(greedyString, bot.colorPalette.string), + Component.text(quote, NamedTextColor.YELLOW) ) ); } @@ -139,7 +135,7 @@ public class CommandContext { if (pointer >= greedyString.length()) { throw new CommandException( Component - .translatable("Unterminated escape at %s <--") + .translatable("arguments_parsing.error.unterminated_escape") .arguments( Component .text(greedyString) @@ -225,7 +221,7 @@ public class CommandContext { try { return Integer.parseInt(string); } catch (final NumberFormatException e) { - throw new CommandException(Component.text("Invalid integer")); + throw new CommandException(Component.translatable("arguments_parsing.error.invalid_type", Component.text("integer"))); } } @@ -237,7 +233,7 @@ public class CommandContext { try { return Long.parseLong(string); } catch (final NumberFormatException e) { - throw new CommandException(Component.text("Invalid long")); + throw new CommandException(Component.translatable("arguments_parsing.error.invalid_type", Component.text("long"))); } } @@ -252,7 +248,7 @@ public class CommandContext { if (!Double.isFinite(parsedDouble) && !allowInfinite) throw new NumberFormatException(); else return parsedDouble; } catch (final NumberFormatException e) { - throw new CommandException(Component.text("Invalid double")); + throw new CommandException(Component.translatable("arguments_parsing.error.invalid_type", Component.text("double"))); } } @@ -267,7 +263,7 @@ public class CommandContext { if (!Float.isFinite(parsedFloat) && !allowInfinite) throw new NumberFormatException(); else return parsedFloat; } catch (final NumberFormatException e) { - throw new CommandException(Component.text("Invalid float")); + throw new CommandException(Component.translatable("arguments_parsing.error.invalid_type", Component.text("float"))); } } @@ -279,7 +275,7 @@ public class CommandContext { return switch (string) { case "true" -> true; case "false" -> false; - default -> throw new CommandException(Component.text("Invalid boolean")); + default -> throw new CommandException(Component.translatable("arguments_parsing.error.invalid_type", Component.text("boolean"))); }; } @@ -293,7 +289,7 @@ public class CommandContext { throw new CommandException( Component.translatable( - "Invalid %s. Possible values are: %s", + "arguments_parsing.error.invalid_enum", Component.text(enumClass.getSimpleName()), Component.text(Arrays.toString(values)) ) @@ -312,7 +308,7 @@ public class CommandContext { if (count > maximumArgs) throw new CommandException( Component.translatable( - "Too many arguments, expected %s max", + "arguments_parsing.error.too_many_arguments", Component.text(maximumArgs) ) ); diff --git a/src/main/java/me/chayapak1/chomens_bot/command/TrustLevel.java b/src/main/java/me/chayapak1/chomens_bot/command/TrustLevel.java index bdc4bf8d..fe2adf06 100644 --- a/src/main/java/me/chayapak1/chomens_bot/command/TrustLevel.java +++ b/src/main/java/me/chayapak1/chomens_bot/command/TrustLevel.java @@ -2,6 +2,7 @@ package me.chayapak1.chomens_bot.command; import me.chayapak1.chomens_bot.Configuration; import me.chayapak1.chomens_bot.Main; +import me.chayapak1.chomens_bot.util.I18nUtilities; import net.dv8tion.jda.api.entities.Role; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; @@ -9,10 +10,10 @@ import net.kyori.adventure.text.format.NamedTextColor; import java.util.List; public enum TrustLevel { - PUBLIC(0, Component.text("Public").color(NamedTextColor.GREEN)), - TRUSTED(1, Component.text("Trusted").color(NamedTextColor.RED)), - ADMIN(2, Component.text("Admin").color(NamedTextColor.DARK_RED)), - OWNER(3, Component.text("Owner").color(NamedTextColor.LIGHT_PURPLE)); + PUBLIC(0, Component.text(I18nUtilities.get("trust_level.public"), NamedTextColor.GREEN)), + TRUSTED(1, Component.text(I18nUtilities.get("trust_level.trusted")).color(NamedTextColor.RED)), + ADMIN(2, Component.text(I18nUtilities.get("trust_level.admin")).color(NamedTextColor.DARK_RED)), + OWNER(3, Component.text(I18nUtilities.get("trust_level.owner")).color(NamedTextColor.LIGHT_PURPLE)); public final int level; public final Component component; diff --git a/src/main/java/me/chayapak1/chomens_bot/command/contexts/ChomeNSModCommandContext.java b/src/main/java/me/chayapak1/chomens_bot/command/contexts/ChomeNSModCommandContext.java index 52fccd80..c9960c3f 100644 --- a/src/main/java/me/chayapak1/chomens_bot/command/contexts/ChomeNSModCommandContext.java +++ b/src/main/java/me/chayapak1/chomens_bot/command/contexts/ChomeNSModCommandContext.java @@ -18,9 +18,10 @@ public class ChomeNSModCommandContext extends CommandContext { @Override public void sendOutput (final Component component) { + final Component rendered = bot.commandHandler.renderTranslatable(component); bot.chomeNSMod.send( sender, - new ClientboundMessagePacket(component) + new ClientboundMessagePacket(rendered) ); } diff --git a/src/main/java/me/chayapak1/chomens_bot/command/contexts/ConsoleCommandContext.java b/src/main/java/me/chayapak1/chomens_bot/command/contexts/ConsoleCommandContext.java index 51c9660b..5e5d5025 100644 --- a/src/main/java/me/chayapak1/chomens_bot/command/contexts/ConsoleCommandContext.java +++ b/src/main/java/me/chayapak1/chomens_bot/command/contexts/ConsoleCommandContext.java @@ -39,7 +39,8 @@ public class ConsoleCommandContext extends CommandContext { @Override public void sendOutput (final Component component) { - bot.logger.log(LogType.COMMAND_OUTPUT, component); + final Component rendered = bot.commandHandler.renderTranslatable(component); + bot.logger.log(LogType.COMMAND_OUTPUT, rendered, false); } @Override diff --git a/src/main/java/me/chayapak1/chomens_bot/command/contexts/DiscordCommandContext.java b/src/main/java/me/chayapak1/chomens_bot/command/contexts/DiscordCommandContext.java index 5d76be8a..9ce618b0 100644 --- a/src/main/java/me/chayapak1/chomens_bot/command/contexts/DiscordCommandContext.java +++ b/src/main/java/me/chayapak1/chomens_bot/command/contexts/DiscordCommandContext.java @@ -47,10 +47,12 @@ public class DiscordCommandContext extends CommandContext { @Override public void sendOutput (final Component component) { - String output = ComponentUtilities.stringifyDiscordAnsi(component); + final Component rendered = bot.commandHandler.renderTranslatable(component); + + String output = ComponentUtilities.stringifyDiscordAnsi(rendered); if (output.length() > 2048) { - output = ComponentUtilities.stringify(component); + output = ComponentUtilities.stringify(rendered); event.getMessage().replyFiles( FileUpload.fromData( diff --git a/src/main/java/me/chayapak1/chomens_bot/command/contexts/IRCCommandContext.java b/src/main/java/me/chayapak1/chomens_bot/command/contexts/IRCCommandContext.java index ff50292a..28eab81f 100644 --- a/src/main/java/me/chayapak1/chomens_bot/command/contexts/IRCCommandContext.java +++ b/src/main/java/me/chayapak1/chomens_bot/command/contexts/IRCCommandContext.java @@ -39,7 +39,8 @@ public class IRCCommandContext extends CommandContext { @Override public void sendOutput (final Component component) { - Main.irc.sendMessage(bot, ComponentUtilities.stringifyAnsi(component)); + final Component rendered = bot.commandHandler.renderTranslatable(component); + Main.irc.sendMessage(bot, ComponentUtilities.stringifyAnsi(rendered)); } @Override diff --git a/src/main/java/me/chayapak1/chomens_bot/command/contexts/PlayerCommandContext.java b/src/main/java/me/chayapak1/chomens_bot/command/contexts/PlayerCommandContext.java index efcb4f59..aeb40d1b 100644 --- a/src/main/java/me/chayapak1/chomens_bot/command/contexts/PlayerCommandContext.java +++ b/src/main/java/me/chayapak1/chomens_bot/command/contexts/PlayerCommandContext.java @@ -31,11 +31,12 @@ public class PlayerCommandContext extends CommandContext { } @Override - public void sendOutput (final Component message) { + public void sendOutput (final Component component) { + final Component rendered = bot.commandHandler.renderTranslatable(component); bot.chat.tellraw( Component.translatable( "%s", - message, + rendered, Component.text("chomens_bot_command_output" + ((commandName != null) ? "_" + commandName : "")) ), selector diff --git a/src/main/java/me/chayapak1/chomens_bot/command/contexts/RemoteCommandContext.java b/src/main/java/me/chayapak1/chomens_bot/command/contexts/RemoteCommandContext.java index 064038e5..ad44e71b 100644 --- a/src/main/java/me/chayapak1/chomens_bot/command/contexts/RemoteCommandContext.java +++ b/src/main/java/me/chayapak1/chomens_bot/command/contexts/RemoteCommandContext.java @@ -18,6 +18,7 @@ public class RemoteCommandContext extends CommandContext { @Override public void sendOutput (final Component component) { + final Component rendered = bot.commandHandler.renderTranslatable(component); source.sendOutput( Component .translatable( @@ -25,7 +26,7 @@ public class RemoteCommandContext extends CommandContext { Component.text(targetBot.getServerString(), NamedTextColor.GRAY), Component.empty() .color(NamedTextColor.WHITE) - .append(component) + .append(rendered) ) .color(NamedTextColor.DARK_GRAY) ); diff --git a/src/main/java/me/chayapak1/chomens_bot/commands/BotVisibilityCommand.java b/src/main/java/me/chayapak1/chomens_bot/commands/BotVisibilityCommand.java index dd1b9ca5..db403e1d 100644 --- a/src/main/java/me/chayapak1/chomens_bot/commands/BotVisibilityCommand.java +++ b/src/main/java/me/chayapak1/chomens_bot/commands/BotVisibilityCommand.java @@ -13,7 +13,6 @@ public class BotVisibilityCommand extends Command { public BotVisibilityCommand () { super( "botvisibility", - "Changes the bot's visibility", new String[] { "", "", "" }, new String[] { "botvis", "togglevis", "togglevisibility" }, TrustLevel.TRUSTED @@ -38,31 +37,34 @@ public class BotVisibilityCommand extends Command { final String visibleOrInvisible = vanish.visible ? "visible" : "invisible"; - return Component.empty() - .append(Component.text("The bot's visibility is now ")) - .append(Component.text(visibleOrInvisible).color(greenOrGold)) - .color(bot.colorPalette.defaultColor); + return Component.translatable( + "commands.botvisibility.message", + bot.colorPalette.defaultColor, + Component.translatable("commands.botvisibility." + visibleOrInvisible, greenOrGold) + ); } else { switch (action) { case "on", "true" -> { vanish.visible = true; vanish.needsRunning = true; - return Component.empty() - .append(Component.text("The bot's visibility is now ")) - .append(Component.text("visible").color(NamedTextColor.GREEN)) - .color(bot.colorPalette.defaultColor); + return Component.translatable( + "commands.botvisibility.message", + bot.colorPalette.defaultColor, + Component.translatable("commands.botvisibility.visible", NamedTextColor.GREEN) + ); } case "off", "false" -> { vanish.visible = false; vanish.needsRunning = true; - return Component.empty() - .append(Component.text("The bot's visibility is now ")) - .append(Component.text("invisible").color(NamedTextColor.GOLD)) - .color(bot.colorPalette.defaultColor); + return Component.translatable( + "commands.botvisibility.message", + bot.colorPalette.defaultColor, + Component.translatable("commands.botvisibility.invisible", NamedTextColor.GOLD) + ); } - default -> throw new CommandException(Component.text("Invalid action")); + default -> throw new CommandException(Component.translatable("commands.generic.error.invalid_action")); } } } diff --git a/src/main/java/me/chayapak1/chomens_bot/commands/BruhifyCommand.java b/src/main/java/me/chayapak1/chomens_bot/commands/BruhifyCommand.java index e78eb571..b6ec69e5 100644 --- a/src/main/java/me/chayapak1/chomens_bot/commands/BruhifyCommand.java +++ b/src/main/java/me/chayapak1/chomens_bot/commands/BruhifyCommand.java @@ -11,7 +11,6 @@ public class BruhifyCommand extends Command { public BruhifyCommand () { super( "bruhify", - "RecycleBots bruhify but actionbar", new String[] { "[message]" }, new String[] {}, TrustLevel.PUBLIC diff --git a/src/main/java/me/chayapak1/chomens_bot/commands/ClearChatCommand.java b/src/main/java/me/chayapak1/chomens_bot/commands/ClearChatCommand.java index d6e2ae02..49cd3957 100644 --- a/src/main/java/me/chayapak1/chomens_bot/commands/ClearChatCommand.java +++ b/src/main/java/me/chayapak1/chomens_bot/commands/ClearChatCommand.java @@ -16,12 +16,11 @@ public class ClearChatCommand extends Command { public ClearChatCommand () { super( "clearchat", - "Clears the chat", new String[] { "[player]" }, new String[] { "cc" }, TrustLevel.PUBLIC, false, - new ChatPacketType[]{ ChatPacketType.DISGUISED } + new ChatPacketType[] { ChatPacketType.DISGUISED } ); } @@ -34,7 +33,7 @@ public class ClearChatCommand extends Command { if (!name.isEmpty()) { final PlayerEntry entry = bot.players.getEntry(name); - if (entry == null) throw new CommandException(Component.text("Invalid player name")); + if (entry == null) throw new CommandException(Component.translatable("commands.generic.error.invalid_player")); final UUID uuid = entry.profile.getId(); @@ -42,10 +41,11 @@ public class ClearChatCommand extends Command { Component.empty() .append(Component.text("\n".repeat(1000))) .append( - Component.empty() - .append(Component.text("Your chat has been cleared by ")) - .append(context.displayName()) - .color(NamedTextColor.DARK_GREEN) + Component.translatable( + "commands.clearchat.specific", + NamedTextColor.DARK_GREEN, + context.displayName() + ) ), uuid ); @@ -53,7 +53,7 @@ public class ClearChatCommand extends Command { bot.chat.tellraw( Component.empty() .append(Component.text("\n".repeat(1000))) - .append(Component.text("The chat has been cleared").color(NamedTextColor.DARK_GREEN)) + .append(Component.translatable("commands.clearchat.everyone").color(NamedTextColor.DARK_GREEN)) ); } diff --git a/src/main/java/me/chayapak1/chomens_bot/commands/ClearChatQueueCommand.java b/src/main/java/me/chayapak1/chomens_bot/commands/ClearChatQueueCommand.java index 8e1b800e..2bc9a321 100644 --- a/src/main/java/me/chayapak1/chomens_bot/commands/ClearChatQueueCommand.java +++ b/src/main/java/me/chayapak1/chomens_bot/commands/ClearChatQueueCommand.java @@ -11,7 +11,6 @@ public class ClearChatQueueCommand extends Command { public ClearChatQueueCommand () { super( "clearchatqueue", - "Clears the bots chat queue", new String[] {}, new String[] { "ccq" }, TrustLevel.PUBLIC @@ -26,8 +25,9 @@ public class ClearChatQueueCommand extends Command { bot.chat.clearQueue(); - return Component - .text("Cleared the bot's chat queue") - .color(bot.colorPalette.defaultColor); + return Component.translatable( + "commands.clearchatqueue.output", + bot.colorPalette.defaultColor + ); } } diff --git a/src/main/java/me/chayapak1/chomens_bot/commands/CloopCommand.java b/src/main/java/me/chayapak1/chomens_bot/commands/CloopCommand.java index 4981dcf6..986d0c83 100644 --- a/src/main/java/me/chayapak1/chomens_bot/commands/CloopCommand.java +++ b/src/main/java/me/chayapak1/chomens_bot/commands/CloopCommand.java @@ -18,7 +18,6 @@ public class CloopCommand extends Command { public CloopCommand () { super( "cloop", - "Loops commands", new String[] { "add ", "remove ", "clear", "list" }, new String[] { "commandloop" }, TrustLevel.TRUSTED @@ -39,7 +38,7 @@ public class CloopCommand extends Command { final ChronoUnit unit = context.getEnum(ChronoUnit.class); if (unit == ChronoUnit.NANOS && interval < 1000) - throw new CommandException(Component.text("Interval must not be less than 1000 nanoseconds")); + throw new CommandException(Component.translatable("commands.cloop.add.error.too_low_nanoseconds")); final String command = context.getString(true, true); @@ -50,11 +49,12 @@ public class CloopCommand extends Command { } return Component.translatable( - "Added %s with interval %s %s to the cloops", + "commands.cloop.add.output", + bot.colorPalette.defaultColor, Component.text(command).color(bot.colorPalette.string), Component.text(interval).color(bot.colorPalette.number), Component.text(unit.toString()).color(bot.colorPalette.string) - ).color(bot.colorPalette.defaultColor); + ); } case "remove" -> { context.checkOverloadArgs(2); @@ -65,18 +65,18 @@ public class CloopCommand extends Command { final CommandLoop cloop = bot.cloop.remove(index); return Component.translatable( - "Removed cloop %s", + "commands.cloop.remove.output", Component.text(cloop.command()).color(bot.colorPalette.string) ).color(bot.colorPalette.defaultColor); } catch (final IndexOutOfBoundsException | IllegalArgumentException | NullPointerException ignored) { - throw new CommandException(Component.text("Invalid index")); + throw new CommandException(Component.translatable("commands.generic.error.invalid_index")); } } case "clear" -> { context.checkOverloadArgs(1); bot.cloop.clear(); - return Component.text("Cleared all cloops").color(bot.colorPalette.defaultColor); + return Component.translatable("commands.cloop.clear.output", bot.colorPalette.defaultColor); } case "list" -> { context.checkOverloadArgs(1); @@ -98,7 +98,7 @@ public class CloopCommand extends Command { } return Component.empty() - .append(Component.text("Cloops ").color(NamedTextColor.GREEN)) + .append(Component.translatable("commands.cloop.list.cloops_text").color(NamedTextColor.GREEN)) .append(Component.text("(").color(NamedTextColor.DARK_GRAY)) .append(Component.text(bot.cloop.loops.size()).color(NamedTextColor.GRAY)) .append(Component.text(")").color(NamedTextColor.DARK_GRAY)) @@ -107,7 +107,7 @@ public class CloopCommand extends Command { Component.join(JoinConfiguration.newlines(), cloopsComponent) ); } - default -> throw new CommandException(Component.text("Invalid action")); + default -> throw new CommandException(Component.translatable("commands.generic.error.invalid_action")); } } } diff --git a/src/main/java/me/chayapak1/chomens_bot/commands/CommandBlockCommand.java b/src/main/java/me/chayapak1/chomens_bot/commands/CommandBlockCommand.java index 13142399..a4ee61ac 100644 --- a/src/main/java/me/chayapak1/chomens_bot/commands/CommandBlockCommand.java +++ b/src/main/java/me/chayapak1/chomens_bot/commands/CommandBlockCommand.java @@ -25,7 +25,6 @@ public class CommandBlockCommand extends Command { public CommandBlockCommand () { super( "cb", - "Executes a command in the command core and return its output", new String[] { "", "", @@ -79,28 +78,23 @@ public class CommandBlockCommand extends Command { final String command = commandBuilder.toString(); return Component.translatable( - """ - Size: %s - Layers: %s - From: %s - To: %s - Block: %s - Dimension: %s - %s""", - Component - .text(256 * layers) - .append(Component.text(" blocks")) - .color(bot.colorPalette.string), + "commands.cb.info.output", + bot.colorPalette.secondary, + Component.translatable( + "commands.cb.info.size", + bot.colorPalette.string, + Component.text(256 * layers) + ), Component.text(layers).color(bot.colorPalette.string), Component.text(from.toString()).color(bot.colorPalette.string), Component.text(to.toString()).color(bot.colorPalette.string), Component.text(block.toString()).color(bot.colorPalette.string), Component.text(bot.world.currentDimension).color(bot.colorPalette.string), Component - .text("Click here to teleport to the command core", NamedTextColor.GREEN) + .translatable("commands.cb.info.click_to_teleport", NamedTextColor.GREEN) .hoverEvent(HoverEvent.showText(Component.text(command, bot.colorPalette.secondary))) .clickEvent(ClickEvent.runCommand(command)) - ).color(bot.colorPalette.secondary); + ); } private void runCommand (final Bot bot, final CommandContext context, final String command, final PlayerEntry player) { @@ -189,9 +183,9 @@ public class CommandBlockCommand extends Command { .color(bot.colorPalette.uuid) ) .append(Component.newline()) - .append(Component.text("Click to copy the username to your clipboard").color(NamedTextColor.GREEN)) + .append(Component.translatable("commands.generic.click_to_copy_username", NamedTextColor.GREEN)) .append(Component.newline()) - .append(Component.text("Shift+Click to insert the UUID into your chat box").color(NamedTextColor.GREEN)) + .append(Component.translatable("commands.generic.shift_click_to_insert_uuid", NamedTextColor.GREEN)) ) ) .clickEvent(ClickEvent.copyToClipboard(player.profile.getName())) diff --git a/src/main/java/me/chayapak1/chomens_bot/commands/ConsoleCommand.java b/src/main/java/me/chayapak1/chomens_bot/commands/ConsoleCommand.java index 73bffc92..78d30f6b 100644 --- a/src/main/java/me/chayapak1/chomens_bot/commands/ConsoleCommand.java +++ b/src/main/java/me/chayapak1/chomens_bot/commands/ConsoleCommand.java @@ -16,7 +16,6 @@ public class ConsoleCommand extends Command { public ConsoleCommand () { super( "console", - "Controls stuff about console", new String[] { "server ", "logtoconsole ", @@ -48,9 +47,11 @@ public class ConsoleCommand extends Command { if (server.equalsIgnoreCase("all")) { Main.console.consoleServer = "all"; - return Component.text( - "Set the console server to all servers" - ).color(bot.colorPalette.defaultColor); + return Component.translatable( + "commands.console.server.set", + bot.colorPalette.defaultColor, + Component.translatable("commands.console.server.all_servers") + ); } try { @@ -61,11 +62,17 @@ public class ConsoleCommand extends Command { .orElse("all"); return Component.translatable( - "Set the console server to %s", + "commands.console.server.set", + bot.colorPalette.defaultColor, Component.text(Main.console.consoleServer) - ).color(bot.colorPalette.defaultColor); + ); } catch (final ArrayIndexOutOfBoundsException e) { - throw new CommandException(Component.text("Invalid server: " + server)); + throw new CommandException( + Component.translatable( + "commands.console.server.error.invalid_server", + Component.text(server) + ) + ); } } case "logtoconsole" -> { @@ -76,9 +83,12 @@ public class ConsoleCommand extends Command { bot.logger.logToConsole = bool; return Component.translatable( - "Logging to console is now %s", - bool ? Component.text("enabled").color(NamedTextColor.GREEN) : Component.text("disabled").color(NamedTextColor.RED) - ).color(bot.colorPalette.defaultColor); + "commands.console.logtoconsole.set", + bot.colorPalette.defaultColor, + bool + ? Component.translatable("commands.generic.enabled").color(NamedTextColor.GREEN) + : Component.translatable("commands.generic.disabled").color(NamedTextColor.RED) + ); } case "printdisconnectedreason" -> { context.checkOverloadArgs(2); @@ -88,9 +98,12 @@ public class ConsoleCommand extends Command { bot.printDisconnectedCause = bool; return Component.translatable( - "Printing the disconnected cause is now %s", - bool ? Component.text("enabled").color(NamedTextColor.GREEN) : Component.text("disabled").color(NamedTextColor.RED) - ).color(bot.colorPalette.defaultColor); + "commands.console.printdisconnectedreason.set", + bot.colorPalette.defaultColor, + bool + ? Component.translatable("commands.generic.enabled").color(NamedTextColor.GREEN) + : Component.translatable("commands.generic.disabled").color(NamedTextColor.RED) + ); } } diff --git a/src/main/java/me/chayapak1/chomens_bot/commands/CowsayCommand.java b/src/main/java/me/chayapak1/chomens_bot/commands/CowsayCommand.java index ed2e8a37..27c0a1b5 100644 --- a/src/main/java/me/chayapak1/chomens_bot/commands/CowsayCommand.java +++ b/src/main/java/me/chayapak1/chomens_bot/commands/CowsayCommand.java @@ -11,7 +11,6 @@ public class CowsayCommand extends Command { public CowsayCommand () { super( "cowsay", - "Moo", new String[] { "" }, new String[] {}, TrustLevel.PUBLIC diff --git a/src/main/java/me/chayapak1/chomens_bot/commands/EchoCommand.java b/src/main/java/me/chayapak1/chomens_bot/commands/EchoCommand.java index e80e11bb..c39ac312 100644 --- a/src/main/java/me/chayapak1/chomens_bot/commands/EchoCommand.java +++ b/src/main/java/me/chayapak1/chomens_bot/commands/EchoCommand.java @@ -12,12 +12,11 @@ public class EchoCommand extends Command { public EchoCommand () { super( "echo", - "Makes the bot say a message", new String[] { "" }, new String[] { "say" }, TrustLevel.PUBLIC, false, - new ChatPacketType[]{ ChatPacketType.DISGUISED } + new ChatPacketType[] { ChatPacketType.DISGUISED } ); } diff --git a/src/main/java/me/chayapak1/chomens_bot/commands/EndCommand.java b/src/main/java/me/chayapak1/chomens_bot/commands/EndCommand.java index 621adf7e..a0bea8ce 100644 --- a/src/main/java/me/chayapak1/chomens_bot/commands/EndCommand.java +++ b/src/main/java/me/chayapak1/chomens_bot/commands/EndCommand.java @@ -5,13 +5,13 @@ import me.chayapak1.chomens_bot.command.Command; import me.chayapak1.chomens_bot.command.CommandContext; import me.chayapak1.chomens_bot.command.CommandException; import me.chayapak1.chomens_bot.command.TrustLevel; +import me.chayapak1.chomens_bot.util.I18nUtilities; import net.kyori.adventure.text.Component; public class EndCommand extends Command { public EndCommand () { super( "end", - "Reconnects the bot", new String[] { "" }, new String[] { "reconnect" }, TrustLevel.TRUSTED @@ -24,7 +24,7 @@ public class EndCommand extends Command { final Bot bot = context.bot; - bot.session.disconnect("End command"); + bot.session.disconnect(I18nUtilities.get("commands.end.disconnect_reason")); return null; } diff --git a/src/main/java/me/chayapak1/chomens_bot/commands/EvalCommand.java b/src/main/java/me/chayapak1/chomens_bot/commands/EvalCommand.java index e52751f6..8bb53cc2 100644 --- a/src/main/java/me/chayapak1/chomens_bot/commands/EvalCommand.java +++ b/src/main/java/me/chayapak1/chomens_bot/commands/EvalCommand.java @@ -16,7 +16,6 @@ public class EvalCommand extends Command { public EvalCommand () { super( "eval", - "Evaluate JavaScript codes on a Node.JS container running @n8n/vm2", new String[] { "run ", "reset" }, new String[] {}, TrustLevel.PUBLIC, @@ -29,7 +28,7 @@ public class EvalCommand extends Command { public Component execute (final CommandContext context) throws CommandException { final Bot bot = context.bot; - if (!bot.eval.connected) throw new CommandException(Component.text("Eval server is not online")); + if (!bot.eval.connected) throw new CommandException(Component.translatable("commands.eval.error.offline")); final String action = context.getAction(); @@ -49,9 +48,9 @@ public class EvalCommand extends Command { case "reset" -> { bot.eval.reset(); - return Component.text("Reset the eval worker").color(bot.colorPalette.defaultColor); + return Component.translatable("commands.eval.reset", bot.colorPalette.defaultColor); } - default -> throw new CommandException(Component.text("Invalid action")); + default -> throw new CommandException(Component.translatable("commands.generic.error.invalid_action")); } return null; diff --git a/src/main/java/me/chayapak1/chomens_bot/commands/FilterCommand.java b/src/main/java/me/chayapak1/chomens_bot/commands/FilterCommand.java index ad3afa79..44e095b1 100644 --- a/src/main/java/me/chayapak1/chomens_bot/commands/FilterCommand.java +++ b/src/main/java/me/chayapak1/chomens_bot/commands/FilterCommand.java @@ -18,7 +18,6 @@ public class FilterCommand extends Command { public FilterCommand () { super( "filter", - "Filter players", new String[] { "add [reason]", "-ignorecase add [reason]", @@ -57,7 +56,7 @@ public class FilterCommand extends Command { ) { throw new CommandException( Component.translatable( - "The player %s is already in the filters", + "commands.filter.error.already_exists", Component.text(player) ) ); @@ -70,7 +69,7 @@ public class FilterCommand extends Command { } catch (final PatternSyntaxException e) { throw new CommandException( Component.translatable( - "Failed to parse filter regex: %s", + "commands.filter.error.invalid_regex", Component.text(e.toString()) ) ); @@ -81,15 +80,17 @@ public class FilterCommand extends Command { if (reason.isEmpty()) { return Component.translatable( - "Added %s to the filters", + "commands.filter.add.no_reason", + bot.colorPalette.defaultColor, Component.text(player).color(bot.colorPalette.username) - ).color(bot.colorPalette.defaultColor); + ); } else { return Component.translatable( - "Added %s to the filters with reason %s", + "commands.filter.add.reason", + bot.colorPalette.defaultColor, Component.text(player).color(bot.colorPalette.username), Component.text(reason).color(bot.colorPalette.string) - ).color(bot.colorPalette.defaultColor); + ); } } case "remove" -> { @@ -99,20 +100,21 @@ public class FilterCommand extends Command { final FilteredPlayer player = PlayerFilterPlugin.localList.get(index); - if (player == null) throw new CommandException(Component.text("Invalid index")); + if (player == null) throw new CommandException(Component.translatable("commands.generic.error.invalid_index")); DatabasePlugin.EXECUTOR_SERVICE.submit(() -> bot.playerFilter.remove(player.playerName())); return Component.translatable( - "Removed %s from the filters", - Component.text(player.playerName()).color(bot.colorPalette.username) - ).color(bot.colorPalette.defaultColor); + "commands.filter.remove.output", + bot.colorPalette.defaultColor, + Component.text(player.playerName(), bot.colorPalette.username) + ); } case "clear" -> { context.checkOverloadArgs(1); DatabasePlugin.EXECUTOR_SERVICE.submit(bot.playerFilter::clear); - return Component.text("Cleared the filter").color(bot.colorPalette.defaultColor); + return Component.translatable("commands.filter.clear.output").color(bot.colorPalette.defaultColor); } case "list" -> { context.checkOverloadArgs(1); @@ -126,8 +128,8 @@ public class FilterCommand extends Command { if (player.ignoreCase() || player.regex()) { final List args = new ArrayList<>(); - if (player.ignoreCase()) args.add(Component.text("ignore case")); - if (player.regex()) args.add(Component.text("regex")); + if (player.ignoreCase()) args.add(Component.translatable("commands.filter.list.ignore_case")); + if (player.regex()) args.add(Component.translatable("commands.filter.list.regex")); options = options .append(Component.text("(")) @@ -146,11 +148,12 @@ public class FilterCommand extends Command { if (!player.reason().isEmpty()) { options = options .append(Component.text("(")) - .append(Component.text("reason: ").color(NamedTextColor.GRAY)) .append( - Component - .text(player.reason()) - .color(bot.colorPalette.string) + Component.translatable( + "commands.filter.list.reason", + NamedTextColor.GRAY, + Component.text(player.reason(), bot.colorPalette.string) + ) ) .append(Component.text(")")); } @@ -168,16 +171,16 @@ public class FilterCommand extends Command { } return Component.empty() - .append(Component.text("Filtered players ").color(NamedTextColor.GREEN)) - .append(Component.text("(").color(NamedTextColor.DARK_GRAY)) - .append(Component.text(PlayerFilterPlugin.localList.size()).color(NamedTextColor.GRAY)) - .append(Component.text(")").color(NamedTextColor.DARK_GRAY)) + .append(Component.translatable("commands.filter.list.filtered_players_text", NamedTextColor.GREEN)) + .append(Component.text("(", NamedTextColor.DARK_GRAY)) + .append(Component.text(PlayerFilterPlugin.localList.size(), NamedTextColor.GRAY)) + .append(Component.text(")", NamedTextColor.DARK_GRAY)) .append(Component.newline()) .append( Component.join(JoinConfiguration.newlines(), filtersComponents) ); } - default -> throw new CommandException(Component.text("Invalid action")); + default -> throw new CommandException(Component.translatable("commands.generic.error.invalid_action")); } } } diff --git a/src/main/java/me/chayapak1/chomens_bot/commands/FindAltsCommand.java b/src/main/java/me/chayapak1/chomens_bot/commands/FindAltsCommand.java index b8ee8190..b7c17874 100644 --- a/src/main/java/me/chayapak1/chomens_bot/commands/FindAltsCommand.java +++ b/src/main/java/me/chayapak1/chomens_bot/commands/FindAltsCommand.java @@ -25,7 +25,6 @@ public class FindAltsCommand extends Command { public FindAltsCommand () { super( "findalts", - "Finds players with the same IP address", new String[] { "-allservers ", "" }, new String[] { "alts", "sameip" }, TrustLevel.PUBLIC, @@ -39,7 +38,7 @@ public class FindAltsCommand extends Command { final Bot bot = context.bot; if (Main.database == null) - throw new CommandException(Component.text("Database is not enabled in the bot's config")); + throw new CommandException(Component.translatable("commands.generic.error.database_disabled")); Main.database.checkOverloaded(); @@ -82,10 +81,9 @@ public class FindAltsCommand extends Command { .color(bot.colorPalette.username); Component component = Component - .translatable("Possible alts for the %s %s:") - .color(bot.colorPalette.defaultColor) + .translatable("commands.findalts.output", bot.colorPalette.defaultColor) .arguments( - Component.text(argumentIsIP ? "IP" : "player"), + Component.translatable(argumentIsIP ? "commands.findalts.ip" : "commands.findalts.player"), argumentIsIP ? playerComponent : Component.translatable("%s (%s)") diff --git a/src/main/java/me/chayapak1/chomens_bot/commands/GrepLogCommand.java b/src/main/java/me/chayapak1/chomens_bot/commands/GrepLogCommand.java index 2f8642c5..65818857 100644 --- a/src/main/java/me/chayapak1/chomens_bot/commands/GrepLogCommand.java +++ b/src/main/java/me/chayapak1/chomens_bot/commands/GrepLogCommand.java @@ -14,7 +14,6 @@ public class GrepLogCommand extends Command { public GrepLogCommand () { super( "greplog", - "Queries the bot's logs", new String[] { "", "-ignorecase ...", "-regex ...", "stop" }, new String[] { "logquery", "findlog" }, TrustLevel.PUBLIC @@ -26,7 +25,7 @@ public class GrepLogCommand extends Command { final Bot bot = context.bot; if (Main.discord == null || Main.discord.jda == null) { - throw new CommandException(Component.text("The bot's Discord integration has to be enabled to use this command.")); + throw new CommandException(Component.translatable("commands.generic.error.discord_disabled")); } final List flags = context.getFlags(true, CommonFlags.IGNORE_CASE, CommonFlags.REGEX); @@ -37,26 +36,23 @@ public class GrepLogCommand extends Command { final String input = context.getString(true, true); if (input.equalsIgnoreCase("stop")) { - if (thread == null) throw new CommandException(Component.text("There is no query process running")); + if (thread == null) throw new CommandException(Component.translatable("commands.greplog.error.not_running")); bot.grepLog.running = false; bot.grepLog.pattern = null; thread = null; - return Component.text("Stopped querying the logs").color(bot.colorPalette.defaultColor); + return Component.translatable("commands.greplog.stopped").color(bot.colorPalette.defaultColor); } - if (thread != null) throw new CommandException(Component.text("Another query is already running")); + if (thread != null) throw new CommandException(Component.translatable("commands.greplog.error.already_running")); context.sendOutput( Component - .translatable("Started querying the logs for %s") - .color(bot.colorPalette.defaultColor) + .translatable("commands.greplog.started", bot.colorPalette.defaultColor) .arguments( - Component - .text(input) - .color(bot.colorPalette.string) + Component.text(input, bot.colorPalette.string) ) ); diff --git a/src/main/java/me/chayapak1/chomens_bot/commands/HelpCommand.java b/src/main/java/me/chayapak1/chomens_bot/commands/HelpCommand.java index a4a5841c..4d5d87b8 100644 --- a/src/main/java/me/chayapak1/chomens_bot/commands/HelpCommand.java +++ b/src/main/java/me/chayapak1/chomens_bot/commands/HelpCommand.java @@ -22,7 +22,6 @@ public class HelpCommand extends Command { public HelpCommand () { super( "help", - "Shows a command list or usage for a command", new String[] { "[command]" }, new String[] { "heko", "cmds", "commands" }, TrustLevel.PUBLIC @@ -57,7 +56,7 @@ public class HelpCommand extends Command { ); return Component.empty() - .append(Component.text("Commands ").color(NamedTextColor.GRAY)) + .append(Component.translatable("commands.help.commands_text").color(NamedTextColor.GRAY)) .append(Component.text("(").color(NamedTextColor.DARK_GRAY)) .append(Component.text(list.size()).color(NamedTextColor.GREEN)) .append(Component.text(") ").color(NamedTextColor.DARK_GRAY)) @@ -117,18 +116,31 @@ public class HelpCommand extends Command { usages.add( Component.empty() + .color(NamedTextColor.GRAY) .append(Component.text(prefix + actualCommandName).color(bot.colorPalette.secondary)) - .append(Component.text( - (command.aliases.length > 0 && !command.aliases[0].isEmpty()) ? - " (" + String.join(", ", command.aliases) + ")" : - "" - ).color(NamedTextColor.WHITE)) - .append(Component.text(" - " + command.description)).color(NamedTextColor.GRAY) + .append( + Component + .text( + (command.aliases.length > 0 && !command.aliases[0].isEmpty()) ? + " (" + String.join(", ", command.aliases) + ")" : + "", + NamedTextColor.WHITE + ) + ) + .append(Component.text(" - ")) + .append( + Component.translatable( + String.format( + "commands.%s.description", + actualCommandName + ) + ) + ) ); usages.add( Component.empty() - .append(Component.text("Trust level: ").color(NamedTextColor.GREEN)) + .append(Component.translatable("commands.help.trust_level").color(NamedTextColor.GREEN)) .append( command.trustLevel.component .append(Component.text(" - ")) @@ -149,6 +161,6 @@ public class HelpCommand extends Command { return Component.join(JoinConfiguration.separator(Component.newline()), usages); } - throw new CommandException(Component.text("Unknown command")); + throw new CommandException(Component.translatable("commands.help.error.unknown_command")); } } diff --git a/src/main/java/me/chayapak1/chomens_bot/commands/IPFilterCommand.java b/src/main/java/me/chayapak1/chomens_bot/commands/IPFilterCommand.java index 1b83245f..a09c9762 100644 --- a/src/main/java/me/chayapak1/chomens_bot/commands/IPFilterCommand.java +++ b/src/main/java/me/chayapak1/chomens_bot/commands/IPFilterCommand.java @@ -19,7 +19,6 @@ public class IPFilterCommand extends Command { public IPFilterCommand () { super( "ipfilter", - "Filters IPs", new String[] { "add [reason]", "remove ", @@ -46,7 +45,7 @@ public class IPFilterCommand extends Command { if (IPFilterPlugin.localList.containsKey(ip)) { throw new CommandException( Component.translatable( - "The IP %s is already in the filters", + "commands.ipfilter.add.error.already_exists", Component.text(ip) ) ); @@ -56,15 +55,17 @@ public class IPFilterCommand extends Command { if (reason.isEmpty()) { return Component.translatable( - "Added %s to the filters", - Component.text(ip).color(bot.colorPalette.number) - ).color(bot.colorPalette.defaultColor); + "commands.filter.add.no_reason", + bot.colorPalette.defaultColor, + Component.text(ip).color(bot.colorPalette.username) + ); } else { return Component.translatable( - "Added %s to the filters with reason %s", - Component.text(ip).color(bot.colorPalette.number), + "commands.filter.add.reason", + bot.colorPalette.defaultColor, + Component.text(ip).color(bot.colorPalette.username), Component.text(reason).color(bot.colorPalette.string) - ).color(bot.colorPalette.defaultColor); + ); } } case "remove" -> { @@ -74,20 +75,21 @@ public class IPFilterCommand extends Command { final String targetIP = new ArrayList<>(IPFilterPlugin.localList.keySet()).get(index); - if (targetIP == null) throw new CommandException(Component.text("Invalid index")); + if (targetIP == null) throw new CommandException(Component.translatable("commands.generic.error.invalid_index")); DatabasePlugin.EXECUTOR_SERVICE.submit(() -> bot.ipFilter.remove(targetIP)); return Component.translatable( - "Removed %s from the filters", - Component.text(targetIP).color(bot.colorPalette.number) - ).color(bot.colorPalette.defaultColor); + "commands.ipfilter.remove.output", + bot.colorPalette.defaultColor, + Component.text(targetIP, bot.colorPalette.username) + ); } case "clear" -> { context.checkOverloadArgs(1); DatabasePlugin.EXECUTOR_SERVICE.submit(bot.ipFilter::clear); - return Component.text("Cleared the filter").color(bot.colorPalette.defaultColor); + return Component.translatable("commands.ipfilter.clear.output").color(bot.colorPalette.defaultColor); } case "list" -> { context.checkOverloadArgs(1); @@ -104,11 +106,12 @@ public class IPFilterCommand extends Command { if (!reason.isEmpty()) { reasonComponent = reasonComponent .append(Component.text("(")) - .append(Component.text("reason: ").color(NamedTextColor.GRAY)) .append( - Component - .text(reason) - .color(bot.colorPalette.string) + Component.translatable( + "commands.ipfilter.list.reason", + NamedTextColor.GRAY, + Component.text(reason, bot.colorPalette.string) + ) ) .append(Component.text(")")); } @@ -126,16 +129,16 @@ public class IPFilterCommand extends Command { } return Component.empty() - .append(Component.text("Filtered IPs ").color(NamedTextColor.GREEN)) - .append(Component.text("(").color(NamedTextColor.DARK_GRAY)) - .append(Component.text(IPFilterPlugin.localList.size()).color(NamedTextColor.GRAY)) - .append(Component.text(")").color(NamedTextColor.DARK_GRAY)) + .append(Component.translatable("commands.ipfilter.list.filtered_ips_text", NamedTextColor.GREEN)) + .append(Component.text("(", NamedTextColor.DARK_GRAY)) + .append(Component.text(IPFilterPlugin.localList.size(), NamedTextColor.GRAY)) + .append(Component.text(")", NamedTextColor.DARK_GRAY)) .append(Component.newline()) .append( Component.join(JoinConfiguration.newlines(), filtersComponents) ); } - default -> throw new CommandException(Component.text("Invalid action")); + default -> throw new CommandException(Component.translatable("commands.generic.error.invalid_action")); } } } diff --git a/src/main/java/me/chayapak1/chomens_bot/commands/InfoCommand.java b/src/main/java/me/chayapak1/chomens_bot/commands/InfoCommand.java index 4a3019e9..d7073a08 100644 --- a/src/main/java/me/chayapak1/chomens_bot/commands/InfoCommand.java +++ b/src/main/java/me/chayapak1/chomens_bot/commands/InfoCommand.java @@ -47,7 +47,6 @@ public class InfoCommand extends Command { public InfoCommand () { super( "info", - "Shows an info about various things", new String[] { "", "creator", @@ -68,27 +67,30 @@ public class InfoCommand extends Command { final Bot bot = context.bot; - final String action = !context.userInputCommandName.equalsIgnoreCase(this.name) ? // if the input command is not `info` - context.userInputCommandName.toLowerCase() : // use that as the action (e.g. "discord", "creator") - context.getString(false, false, true); // else just take the argument of `info` + final String action = !context.userInputCommandName.equalsIgnoreCase(this.name) // if the input command is not `info` + ? context.userInputCommandName.toLowerCase() // use that as the action (e.g. "discord", "creator") + : context.getString(false, false, true); // else just take the argument of `info` switch (action) { case "creator" -> { - return Component.empty() - .append(Component.text("ChomeNS Bot ").color(bot.colorPalette.primary)) - .append(Component.text("is created by ").color(bot.colorPalette.defaultColor)) - .append(Component.text("chayapak").color(bot.colorPalette.ownerName)); + return Component.translatable( + "commands.info.creator.output", + bot.colorPalette.defaultColor, + Component.text("ChomeNS Bot", bot.colorPalette.primary), + Component.text("chayapak", bot.colorPalette.ownerName) + ); } case "discord" -> { final String link = bot.config.discord.inviteLink; - return Component.empty() - .append(Component.text("The Discord invite is ").color(bot.colorPalette.defaultColor)) - .append( - Component - .text(link) - .clickEvent(ClickEvent.openUrl(link)) - .color(NamedTextColor.BLUE) - ); + + return Component.translatable( + "commands.info.discord.output", + bot.colorPalette.defaultColor, + Component + .text(link) + .clickEvent(ClickEvent.openUrl(link)) + .color(NamedTextColor.BLUE) + ); } case "server" -> { // totallynotskiddedâ„¢ from extras' serverinfo @@ -138,17 +140,8 @@ public class InfoCommand extends Command { } catch (final UnknownHostException ignored) { } component = Component.translatable( - """ - Hostname: %s - Working directory: %s - OS architecture: %s - OS version: %s - OS name: %s - CPU cores: %s - CPU model: %s - Threads: %s - Heap memory usage: %s - JVM memory usage: %s""", + "commands.info.server.output", + bot.colorPalette.secondary, Component.text(localHost == null ? "N/A" : localHost.getHostName()).color(color), Component.text(System.getProperty("user.dir")).color(color), Component.text(os.getArch()).color(color), @@ -169,7 +162,7 @@ public class InfoCommand extends Command { Component.text((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / 1024L / 1024L), Component.text(Runtime.getRuntime().totalMemory() / 1024L / 1024L) ).color(color) - ).color(bot.colorPalette.secondary); + ); return component; } @@ -178,34 +171,31 @@ public class InfoCommand extends Command { final String uuid = bot.profile.getIdAsString(); return Component.translatable( - "The bot's username is: %s and the UUID is: %s", + "commands.info.botuser.output", + bot.colorPalette.defaultColor, Component - .text(username) + .text(username, bot.colorPalette.username) .hoverEvent( HoverEvent.showText( - Component - .text("Click here to copy the username to your clipboard") - .color(NamedTextColor.GREEN) + Component.translatable( + "commands.generic.click_to_copy_username", + NamedTextColor.GREEN + ) ) ) - .clickEvent( - ClickEvent.copyToClipboard(username) - ) - .color(bot.colorPalette.username), + .clickEvent(ClickEvent.copyToClipboard(username)), Component - .text(uuid) + .text(uuid, bot.colorPalette.uuid) .hoverEvent( HoverEvent.showText( - Component - .text("Click here to copy the UUID to your clipboard") - .color(NamedTextColor.GREEN) + Component.translatable( + "commands.generic.click_to_copy_uuid", + NamedTextColor.GREEN + ) ) ) - .clickEvent( - ClickEvent.copyToClipboard(uuid) - ) - .color(bot.colorPalette.uuid) - ).color(bot.colorPalette.defaultColor); + .clickEvent(ClickEvent.copyToClipboard(uuid)) + ); } case "botlogintime" -> { final long loginTime = bot.loginTime; @@ -222,14 +212,11 @@ public class InfoCommand extends Command { final String formattedTimeSince = timeSinceFormatter.format(new Date(System.currentTimeMillis() - loginTime)); return Component.translatable( - "The bots login time is %s and has been on the server for %s", - Component - .text(formattedLoginTime) - .color(bot.colorPalette.string), - Component - .text(formattedTimeSince) - .color(bot.colorPalette.string) - ).color(bot.colorPalette.defaultColor); + "commands.info.botlogintime.output", + bot.colorPalette.defaultColor, + Component.text(formattedLoginTime, bot.colorPalette.string), + Component.text(formattedTimeSince, bot.colorPalette.string) + ); } case "uptime" -> { final long uptime = ManagementFactory.getRuntimeMXBean().getUptime() / 1000; @@ -240,9 +227,11 @@ public class InfoCommand extends Command { final long seconds = TimeUnit.SECONDS.toSeconds(uptime) - (TimeUnit.SECONDS.toMinutes(uptime) * 60); return Component.translatable( - "The bots uptime is: %s", + "commands.info.uptime.output", + bot.colorPalette.defaultColor, Component.translatable( "%s %s, %s %s, %s %s, %s %s", + NamedTextColor.GREEN, Component.text(days), Component.text(StringUtilities.addPlural(days, "day")), Component.text(hours), @@ -251,46 +240,53 @@ public class InfoCommand extends Command { Component.text(StringUtilities.addPlural(minutes, "minute")), Component.text(seconds), Component.text(StringUtilities.addPlural(seconds, "second")) - ).color(NamedTextColor.GREEN) - ).color(bot.colorPalette.defaultColor); + ) + ); } default -> { - return Component.empty() - .color(bot.colorPalette.defaultColor) - .append(Component.text("ChomeNS Bot").color(NamedTextColor.YELLOW)) - .append(Component.space()) + return Component + .translatable( + "commands.info.default.main_output", + bot.colorPalette.defaultColor, + Component.text("ChomeNS Bot").color(NamedTextColor.YELLOW), + Component + .text("Kaboom") + .style( + Style.style() + .color(NamedTextColor.GRAY) + .decorate(TextDecoration.BOLD) + ) + ) + .append(Component.newline()) .append( Component .translatable( - "is an open-source utility bot and a moderation bot made for " + - "the %s Minecraft server (and its clones) " + - "but also works on vanilla Minecraft servers. " + - "It was originally made for fun but " + - "I got addicted and made it a full blown bot." - ) - .arguments(Component.text("Kaboom").style(Style.style().color(NamedTextColor.GRAY).decorate(TextDecoration.BOLD))) - ) - .append(Component.newline()) - .append(Component.text("Original repository: ")) - .append( - Component - .text(ORIGINAL_REPOSITORY_URL) - .color(bot.colorPalette.string) - .clickEvent( - ClickEvent.openUrl(ORIGINAL_REPOSITORY_URL) + "commands.info.default.original_repository", + bot.colorPalette.defaultColor, + Component + .text(ORIGINAL_REPOSITORY_URL) + .color(bot.colorPalette.string) + .clickEvent( + ClickEvent.openUrl(ORIGINAL_REPOSITORY_URL) + ) ) ) .append(Component.newline()) - .append(Component.text("Compiled at ")) .append( Component - .text(BUILD_INFO.getProperty("build.date", "unknown")) - .color(bot.colorPalette.string) + .translatable( + "commands.info.default.compiled_at", + bot.colorPalette.defaultColor, + Component + .text(BUILD_INFO.getProperty("build.date", "unknown")) + .color(bot.colorPalette.string) + ) ) .append( Component .translatable( - ", Git commit %s (%s)", + "commands.info.default.git_commit", + bot.colorPalette.defaultColor, Component .text(BUILD_INFO.getProperty("build.git.commit.hash", "unknown")) .color(bot.colorPalette.string), @@ -303,7 +299,8 @@ public class InfoCommand extends Command { .append( Component .translatable( - "Build %s", + "commands.info.default.build", + bot.colorPalette.defaultColor, Component .text(BUILD_INFO.getProperty("build.number", "unknown")) .color(bot.colorPalette.number) diff --git a/src/main/java/me/chayapak1/chomens_bot/commands/KickCommand.java b/src/main/java/me/chayapak1/chomens_bot/commands/KickCommand.java index e468c900..7d191d84 100644 --- a/src/main/java/me/chayapak1/chomens_bot/commands/KickCommand.java +++ b/src/main/java/me/chayapak1/chomens_bot/commands/KickCommand.java @@ -16,13 +16,12 @@ public class KickCommand extends Command { public KickCommand () { super( "kick", - "Kicks a player", new String[] {}, new String[] {}, TrustLevel.TRUSTED ); - final String allMethods = String.join("|", Arrays.stream(Kick.values()).map(Enum::name).toList()); + final String allMethods = String.join(" | ", Arrays.stream(Kick.values()).map(Enum::name).toList()); this.usages = new String[] { "<" + allMethods + "> " }; } @@ -35,21 +34,18 @@ public class KickCommand extends Command { final PlayerEntry entry = bot.players.getEntry(context.getString(true, true)); - if (entry == null) throw new CommandException(Component.text("Invalid player name")); + if (entry == null) throw new CommandException(Component.translatable("commands.generic.error.invalid_player")); final String name = entry.profile.getName(); final UUID uuid = entry.profile.getId(); bot.exploits.kick(method, uuid); - return Component.empty() - .append(Component.text("Kicking player")) - .append(Component.space()) - .append(Component.text(name).color(bot.colorPalette.username)) - .append(Component.space()) - .append(Component.text("with method")) - .append(Component.space()) - .append(Component.text(method.name()).color(bot.colorPalette.string)) - .color(bot.colorPalette.defaultColor); + return Component.translatable( + "commands.kick.output", + bot.colorPalette.defaultColor, + Component.text(name, bot.colorPalette.username), + Component.text(method.toString(), bot.colorPalette.string) + ); } } diff --git a/src/main/java/me/chayapak1/chomens_bot/commands/ListCommand.java b/src/main/java/me/chayapak1/chomens_bot/commands/ListCommand.java index 34d1b952..612e3b0d 100644 --- a/src/main/java/me/chayapak1/chomens_bot/commands/ListCommand.java +++ b/src/main/java/me/chayapak1/chomens_bot/commands/ListCommand.java @@ -19,7 +19,6 @@ public class ListCommand extends Command { public ListCommand () { super( "list", - "Lists all players in the server (including vanished)", new String[] {}, new String[] { "players" }, TrustLevel.PUBLIC @@ -57,12 +56,14 @@ public class ListCommand extends Command { .append(Component.newline()) .append(Component.newline()) .append( - entry.usernames.isEmpty() ? - Component - .text("No other usernames associated") - .color(NamedTextColor.GRAY) : - Component.translatable( - "Usernames: %s", + entry.usernames.isEmpty() + ? Component.translatable( + "commands.list.no_other_usernames", + NamedTextColor.GRAY + ) + : Component.translatable( + "commands.list.with_usernames", + bot.colorPalette.secondary, Component .join( JoinConfiguration.commas(true), @@ -72,68 +73,55 @@ public class ListCommand extends Command { .toList() ) .color(bot.colorPalette.string) - ).color(bot.colorPalette.secondary) + ) ) .append(Component.newline()) .append( Component.translatable( - "Vanished: %s", - Component - .text(!entry.listed) - .color(bot.colorPalette.string) - ).color(bot.colorPalette.secondary) + "commands.list.vanished", + bot.colorPalette.secondary, + Component.text(!entry.listed, bot.colorPalette.string) + ) ) .append(Component.newline()) .append( Component.translatable( - "Latency: %s", + "commands.list.latency", + bot.colorPalette.secondary, Component - .text(entry.latency) + .text(entry.latency, bot.colorPalette.string) // using number color palette will not blend in (GOLD) .append(Component.text("ms")) - .color(bot.colorPalette.string) // using number color palette will not blend in (GOLD) - ).color(bot.colorPalette.secondary) + ) ) .append(Component.newline()) .append( Component.translatable( - "Game Mode: %s", - Component - .text(entry.gamemode.name()) - .color(bot.colorPalette.string) - ).color(bot.colorPalette.secondary) + "commands.list.game_mode", + bot.colorPalette.secondary, + Component.text(entry.gamemode.name(), bot.colorPalette.string) + ) ) .append(Component.newline()) .append( Component.translatable( - "IP Address: %s", - Component - .text(entry.ip == null ? "N/A" : entry.ip) - .color(bot.colorPalette.string) - ).color(bot.colorPalette.secondary) + "commands.list.ip_address", + bot.colorPalette.secondary, + Component.text(entry.ip == null ? "N/A" : entry.ip, bot.colorPalette.string) + ) ) .append(Component.newline()) .append(Component.newline()) - .append(Component.text("Click to copy the username to your clipboard").color(NamedTextColor.GREEN)) + .append(Component.translatable("commands.generic.click_to_copy_username", NamedTextColor.GREEN)) .append(Component.newline()) - .append(Component.text("Shift+Click to insert the UUID into your chat box").color(NamedTextColor.GREEN)); + .append(Component.translatable("commands.generic.shift_click_to_insert_uuid", NamedTextColor.GREEN)); playersComponent.add( - Component.translatable( + Component + .translatable( "%s", entry.displayName == null ? Component.text(entry.profile.getName()) : - entry.displayName, - Component - .text(entry.profile.getIdAsString()) - .hoverEvent( - HoverEvent.showText( - Component.text("Click here to copy the UUID to your clipboard").color(NamedTextColor.GREEN) - ) - ) - .clickEvent( - ClickEvent.copyToClipboard(entry.profile.getIdAsString()) - ) - .color(bot.colorPalette.uuid) + entry.displayName ) .hoverEvent( HoverEvent.showText(hoverEvent) @@ -146,7 +134,7 @@ public class ListCommand extends Command { } return Component.empty() - .append(Component.text("Players ").color(NamedTextColor.GREEN)) + .append(Component.translatable("commands.list.players_text").color(NamedTextColor.GREEN)) .append(Component.text("(").color(NamedTextColor.DARK_GRAY)) .append(Component.text(list.size()).color(NamedTextColor.GRAY)) .append(Component.text(")").color(NamedTextColor.DARK_GRAY)) diff --git a/src/main/java/me/chayapak1/chomens_bot/commands/MailCommand.java b/src/main/java/me/chayapak1/chomens_bot/commands/MailCommand.java index 7f3d9eab..49f86f3b 100644 --- a/src/main/java/me/chayapak1/chomens_bot/commands/MailCommand.java +++ b/src/main/java/me/chayapak1/chomens_bot/commands/MailCommand.java @@ -26,7 +26,6 @@ public class MailCommand extends Command { public MailCommand () { super( "mail", - "Sends a mail", new String[] { "send ", "sendselecteditem ", "read" }, new String[] {}, TrustLevel.PUBLIC @@ -38,7 +37,7 @@ public class MailCommand extends Command { final Bot bot = context.bot; if (Main.database == null) - throw new CommandException(Component.text("Database is not enabled in the bot's config")); + throw new CommandException(Component.translatable("commands.generic.error.database_disabled")); Main.database.checkOverloaded(); @@ -61,7 +60,7 @@ public class MailCommand extends Command { ) ); - context.sendOutput(Component.text("Mail sent!").color(bot.colorPalette.defaultColor)); + context.sendOutput(Component.translatable("commands.mail.sent", bot.colorPalette.defaultColor)); } catch (final CommandException e) { context.sendOutput(e.message.color(NamedTextColor.RED)); } @@ -77,7 +76,7 @@ public class MailCommand extends Command { future.thenApply(output -> { try { if (output.isEmpty()) { - throw new CommandException(Component.text("Player has no `message` NBT tag in their selected item's minecraft:custom_data")); + throw new CommandException(Component.translatable("commands.mail.sendselecteditem.error.no_item_nbt")); } DatabasePlugin.EXECUTOR_SERVICE.submit(() -> { @@ -92,9 +91,7 @@ public class MailCommand extends Command { ) ); - context.sendOutput( - Component.text("Mail sent!").color(bot.colorPalette.defaultColor) - ); + context.sendOutput(Component.translatable("commands.mail.sent", bot.colorPalette.defaultColor)); } catch (final CommandException e) { context.sendOutput(e.message.color(NamedTextColor.RED)); } @@ -120,7 +117,7 @@ public class MailCommand extends Command { } if (senderMailSize == 0) { - context.sendOutput(Component.text("You have no new mails").color(NamedTextColor.RED)); + context.sendOutput(Component.translatable("commands.mail.read.no_new_mails", NamedTextColor.RED)); return; } @@ -140,29 +137,24 @@ public class MailCommand extends Command { mailsComponent.add( Component.translatable( - """ - %s %s Sent by: %s %s - Contents: - %s""", - Component.text(count).color(bot.colorPalette.number), - Component.text("-").color(NamedTextColor.DARK_GRAY), + "commands.mail.read.mail_contents", + Component.text(count, bot.colorPalette.number), + Component.text("-", NamedTextColor.DARK_GRAY), - Component.text(mail.sentBy()).color(bot.colorPalette.username), + Component.text(mail.sentBy(), bot.colorPalette.username), Component - .text("[Hover here for more info]") - .color(NamedTextColor.GREEN) + .translatable("commands.mail.read.hover_more_info", NamedTextColor.GREEN) .hoverEvent( HoverEvent.showText( Component.translatable( - """ - Time sent: %s - Server: %s""", - Component.text(formattedTime).color(bot.colorPalette.string), - Component.text(mail.server()).color(bot.colorPalette.string) - ).color(NamedTextColor.GREEN) + "commands.mail.read.hover_info", + NamedTextColor.GREEN, + Component.text(formattedTime, bot.colorPalette.string), + Component.text(mail.server(), bot.colorPalette.string) + ) ) ), - Component.text(mail.contents()).color(NamedTextColor.WHITE) + Component.text(mail.contents(), NamedTextColor.WHITE) ).color(NamedTextColor.GREEN) ); @@ -170,26 +162,28 @@ public class MailCommand extends Command { } final Component component = Component.empty() - .append(Component.text("Mails ").color(NamedTextColor.GREEN)) + .append(Component.translatable("commands.mail.read.mails_text").color(NamedTextColor.GREEN)) .append(Component.text("(").color(NamedTextColor.DARK_GRAY)) .append(Component.text(tempFinalSenderMailSize).color(NamedTextColor.GRAY)) .append(Component.text(")").color(NamedTextColor.DARK_GRAY)) .append(Component.newline()) .append(Component.join(JoinConfiguration.newlines(), mailsComponent)); + final Component renderedComponent = bot.commandHandler.renderTranslatable(component); + if (context.inGame) { bot.chat.tellraw( - component, + renderedComponent, context.sender.profile.getId() ); } else { - context.sendOutput(component); + context.sendOutput(renderedComponent); } bot.mail.clear(sender.profile.getName()); }); } - default -> context.sendOutput(Component.text("Invalid action").color(NamedTextColor.RED)); + default -> throw new CommandException(Component.translatable("commands.generic.error.invalid_action")); } return null; diff --git a/src/main/java/me/chayapak1/chomens_bot/commands/MusicCommand.java b/src/main/java/me/chayapak1/chomens_bot/commands/MusicCommand.java index aeb53747..f5a145ae 100644 --- a/src/main/java/me/chayapak1/chomens_bot/commands/MusicCommand.java +++ b/src/main/java/me/chayapak1/chomens_bot/commands/MusicCommand.java @@ -16,6 +16,7 @@ import me.chayapak1.chomens_bot.song.Loop; import me.chayapak1.chomens_bot.song.Note; import me.chayapak1.chomens_bot.song.Song; import me.chayapak1.chomens_bot.util.Ascii85; +import me.chayapak1.chomens_bot.util.I18nUtilities; import me.chayapak1.chomens_bot.util.PathUtilities; import me.chayapak1.chomens_bot.util.TimestampUtilities; import net.kyori.adventure.text.Component; @@ -46,7 +47,6 @@ public class MusicCommand extends Command implements Listener { public MusicCommand () { super( "music", - "Plays music", new String[] { "play ", "playitem", @@ -82,7 +82,7 @@ public class MusicCommand extends Command implements Listener { else commandsPerSecond.getAndIncrement(); if (context.bot.music.locked && !(context instanceof ConsoleCommandContext)) - throw new CommandException(Component.text("Managing music is currently locked")); + throw new CommandException(Component.translatable("commands.music.error.locked")); final String action = context.getAction(); @@ -104,14 +104,14 @@ public class MusicCommand extends Command implements Listener { case "pause", "resume" -> pause(context); case "info" -> info(context); case "testsong" -> testSong(context); - default -> Component.text("Invalid action").color(NamedTextColor.RED); + default -> throw new CommandException(Component.translatable("commands.generic.error.invalid_action")); }; } public Component play (final CommandContext context) throws CommandException { final MusicPlayerPlugin player = context.bot.music; - if (player.loaderThread != null) throw new CommandException(Component.text("Already loading a song")); + if (player.loaderThread != null) throw new CommandException(Component.translatable("commands.music.play.error.already_loading")); final String stringPath = context.getString(true, true); @@ -151,13 +151,13 @@ public class MusicCommand extends Command implements Listener { .filter(song -> song.equalsIgnoreCase(lowerCaseFile) || song.toLowerCase().contains(lowerCaseFile)) .toArray(String[]::new); - if (matchedArray.length == 0) throw new CommandException(Component.text("Song not found")); + if (matchedArray.length == 0) throw new CommandException(Component.translatable("commands.music.error.song_not_found")); final String file = matchedArray[0]; player.loadSong(Path.of(realPath.toString(), file), context.sender); } catch (final NoSuchFileException e) { - throw new CommandException(Component.text("Directory does not exist")); + throw new CommandException(Component.translatable("commands.music.error.no_directory")); } } else { try (final DirectoryStream stream = Files.newDirectoryStream(ROOT)) { @@ -173,7 +173,7 @@ public class MusicCommand extends Command implements Listener { .filter(song -> song.equalsIgnoreCase(stringPath) || song.toLowerCase().contains(stringPath.toLowerCase())) .toArray(String[]::new); - if (matchedArray.length == 0) throw new CommandException(Component.text("Song not found")); + if (matchedArray.length == 0) throw new CommandException(Component.translatable("commands.music.error.song_not_found")); final String file = matchedArray[0]; @@ -184,9 +184,9 @@ public class MusicCommand extends Command implements Listener { } } } catch (final MalformedURLException e) { - throw new CommandException(Component.text("Invalid URL")); + throw new CommandException(Component.translatable("commands.music.error.invalid_url")); } catch (final IndexOutOfBoundsException e) { - throw new CommandException(Component.text("Song not found")); + throw new CommandException(Component.translatable("commands.music.error.song_not_found")); } catch (final CommandException e) { throw e; } catch (final Exception e) { @@ -208,7 +208,7 @@ public class MusicCommand extends Command implements Listener { future.thenApply(output -> { if (output.isEmpty()) { - context.sendOutput(Component.text("Player has no `SongItemData.SongData` NBT tag in their selected item's minecraft:custom_data").color(NamedTextColor.RED)); + context.sendOutput(Component.translatable("commands.music.playitem.error.no_item_nbt", NamedTextColor.RED)); return null; } @@ -224,7 +224,7 @@ public class MusicCommand extends Command implements Listener { context.sender ); } catch (final IllegalArgumentException e2) { - context.sendOutput(Component.text("Invalid Base64 or Ascii85 in the selected item").color(NamedTextColor.RED)); + context.sendOutput(Component.translatable("commands.music.playitem.invalid_data", NamedTextColor.RED)); } } @@ -242,7 +242,7 @@ public class MusicCommand extends Command implements Listener { bot.music.songQueue.clear(); bot.music.loaderThread = null; - return Component.text("Cleared the song queue").color(bot.colorPalette.defaultColor); + return Component.translatable("commands.music.stop", bot.colorPalette.defaultColor); } public Component loop (final CommandContext context) throws CommandException { @@ -256,28 +256,32 @@ public class MusicCommand extends Command implements Listener { switch (loop) { case OFF -> { - return Component.empty() - .append(Component.text("Looping is now ")) - .append(Component.text("disabled").color(NamedTextColor.RED)) - .color(bot.colorPalette.defaultColor); + return Component.translatable( + "commands.music.loop.off", + bot.colorPalette.defaultColor, + Component.translatable("commands.music.loop.off.disabled", NamedTextColor.RED) + ); } case CURRENT -> { if (bot.music.currentSong != null) { - return Component.empty() - .append(Component.text("Now looping ")) - .append(Component.text(bot.music.currentSong.name).color(bot.colorPalette.secondary)) - .color(bot.colorPalette.defaultColor); + return Component.translatable( + "commands.music.loop.current.with_song", + bot.colorPalette.defaultColor, + Component.text(bot.music.currentSong.name, bot.colorPalette.secondary) + ); } else { - return Component.empty() - .append(Component.text("Will now loop the next song")) - .color(bot.colorPalette.defaultColor); + return Component.translatable( + "commands.music.loop.current.without_song", + bot.colorPalette.defaultColor + ); } } case ALL -> { - return Component.text("Now looping every song").color(bot.colorPalette.defaultColor); + return Component.translatable("commands.music.loop.all", bot.colorPalette.defaultColor); } - default -> throw new CommandException(Component.text("Invalid action")); } + + return null; } public Component list (final CommandContext context) throws CommandException { @@ -348,7 +352,7 @@ public class MusicCommand extends Command implements Listener { list.clear(); } } catch (final IOException e) { - throw new CommandException(Component.text("Directory doesn't exist")); + throw new CommandException(Component.translatable("commands.music.error.no_directory")); } return null; @@ -359,18 +363,15 @@ public class MusicCommand extends Command implements Listener { final Bot bot = context.bot; final MusicPlayerPlugin music = bot.music; - if (music.currentSong == null) throw new CommandException(Component.text("No song is currently playing")); - - context.sendOutput( - Component.empty() - .append(Component.text("Skipping ")) - .append(Component.text(music.currentSong.name).color(bot.colorPalette.secondary)) - .color(bot.colorPalette.defaultColor) - ); + if (music.currentSong == null) throw new CommandException(Component.translatable("commands.music.error.not_playing")); music.skip(); - return null; + return Component.translatable( + "commands.music.skip", + bot.colorPalette.defaultColor, + Component.text(music.currentSong.name, bot.colorPalette.secondary) + ); } public Component nowPlaying (final CommandContext context) throws CommandException { @@ -378,12 +379,13 @@ public class MusicCommand extends Command implements Listener { final Bot bot = context.bot; final Song song = bot.music.currentSong; - if (song == null) throw new CommandException(Component.text("No song is currently playing")); + if (song == null) throw new CommandException(Component.translatable("commands.music.error.not_playing")); - return Component.empty() - .append(Component.text("Now playing ")) - .append(Component.text(song.name).color(bot.colorPalette.secondary)) - .color(bot.colorPalette.defaultColor); + return Component.translatable( + "commands.music.nowplaying", + bot.colorPalette.defaultColor, + Component.text(song.name, bot.colorPalette.secondary) + ); } public Component queue (final CommandContext context) throws CommandException { @@ -396,13 +398,20 @@ public class MusicCommand extends Command implements Listener { int i = 0; for (final Song song : queue) { queueWithNames.add( - Component.text(song.name).color((i++ & 1) == 0 ? bot.colorPalette.primary : bot.colorPalette.secondary) + Component.text( + song.name, + (i++ & 1) == 0 + ? bot.colorPalette.primary + : bot.colorPalette.secondary + ) ); } - return Component.empty() - .append(Component.text("Queue: ").color(NamedTextColor.GREEN)) - .append(Component.join(JoinConfiguration.separator(Component.text(", ")), queueWithNames)); + return Component.translatable( + "commands.music.queue", + NamedTextColor.GREEN, + Component.join(JoinConfiguration.commas(true), queueWithNames) + ); } // lazy fix for java using "goto" as keyword real @@ -414,17 +423,18 @@ public class MusicCommand extends Command implements Listener { final long timestamp = TimestampUtilities.parseTimestamp(input); - if (currentSong == null) throw new CommandException(Component.text("No song is currently playing")); + if (currentSong == null) throw new CommandException(Component.translatable("commands.music.error.not_playing")); - if (timestamp < 0 || timestamp > currentSong.length * bot.music.speed) - throw new CommandException(Component.text("Invalid timestamp")); + if (timestamp < 0 || timestamp > currentSong.length / bot.music.speed) + throw new CommandException(Component.translatable("commands.music.goto.error.invalid_timestamp")); - currentSong.setTime(timestamp); + currentSong.setTime(timestamp / bot.music.speed); - return Component - .text("Set the time to ") - .append(Component.text(input).color(bot.colorPalette.number)) - .color(bot.colorPalette.defaultColor); + return Component.translatable( + "commands.music.goto", + bot.colorPalette.defaultColor, + Component.text(input, bot.colorPalette.number) + ); } public Component pitch (final CommandContext context) throws CommandException { @@ -436,10 +446,11 @@ public class MusicCommand extends Command implements Listener { bot.music.pitch = pitch; - return Component.empty() - .append(Component.text("Set the pitch to ")) - .append(Component.text(pitch).color(bot.colorPalette.number)) - .color(bot.colorPalette.defaultColor); + return Component.translatable( + "commands.music.pitch", + bot.colorPalette.defaultColor, + Component.text(pitch, bot.colorPalette.number) + ); } public Component speed (final CommandContext context) throws CommandException { @@ -450,8 +461,8 @@ public class MusicCommand extends Command implements Listener { final double speed = context.getDouble(true, false); - if (speed > 5) throw new CommandException(Component.text("Too fast!")); - else if (speed < 0) throw new CommandException(Component.text("Invalid speed")); + if (speed > 5) throw new CommandException(Component.translatable("commands.music.speed.error.too_fast")); + else if (speed < 0) throw new CommandException(Component.translatable("commands.music.speed.error.negative")); double oldTime = -1; @@ -461,10 +472,11 @@ public class MusicCommand extends Command implements Listener { if (currentSong != null) currentSong.setTime(oldTime); - return Component.empty() - .append(Component.text("Set the speed to ")) - .append(Component.text(speed).color(bot.colorPalette.number)) - .color(bot.colorPalette.defaultColor); + return Component.translatable( + "commands.music.speed", + bot.colorPalette.defaultColor, + Component.text(speed, bot.colorPalette.number) + ); } public Component volume (final CommandContext context) throws CommandException { @@ -476,10 +488,11 @@ public class MusicCommand extends Command implements Listener { bot.music.volume = volume; - return Component.empty() - .append(Component.text("Set the volume modifier to ")) - .append(Component.text(volume).color(bot.colorPalette.number)) - .color(bot.colorPalette.defaultColor); + return Component.translatable( + "commands.music.volume", + bot.colorPalette.defaultColor, + Component.text(volume, bot.colorPalette.number) + ); } public Component amplify (final CommandContext context) throws CommandException { @@ -489,15 +502,16 @@ public class MusicCommand extends Command implements Listener { final int amplify = context.getInteger(true); - if (amplify > 8) throw new CommandException(Component.text("Too big value")); - else if (amplify < 0) throw new CommandException(Component.text("Invalid amplification value")); + if (amplify > 8) throw new CommandException(Component.translatable("commands.music.amplify.error.too_big_value")); + else if (amplify < 0) throw new CommandException(Component.translatable("commands.music.amplify.error.negative")); bot.music.amplify = amplify; - return Component.empty() - .append(Component.text("Set the amplification to ")) - .append(Component.text(amplify).color(bot.colorPalette.number)) - .color(bot.colorPalette.defaultColor); + return Component.translatable( + "commands.music.amplify", + bot.colorPalette.defaultColor, + Component.text(amplify, bot.colorPalette.number) + ); } public Component noteInstrument (final CommandContext context) throws CommandException { @@ -507,13 +521,14 @@ public class MusicCommand extends Command implements Listener { bot.music.instrument = instrument; - if (!instrument.equals("off")) { - return Component.empty() - .append(Component.text("Set the instrument for every note to ")) - .append(Component.text(instrument).color(bot.colorPalette.secondary)) - .color(bot.colorPalette.defaultColor); + if (instrument.equalsIgnoreCase("off")) { + return Component.translatable("commands.music.noteinstrument.off", bot.colorPalette.defaultColor); } else { - return Component.text("Every notes are now using its instrument").color(bot.colorPalette.defaultColor); + return Component.translatable( + "commands.music.noteinstrument.set", + bot.colorPalette.defaultColor, + Component.text(instrument) + ); } } @@ -523,14 +538,14 @@ public class MusicCommand extends Command implements Listener { final Bot bot = context.bot; final Song currentSong = bot.music.currentSong; - if (currentSong == null) throw new CommandException(Component.text("No song is currently playing")); + if (currentSong == null) throw new CommandException(Component.translatable("commands.music.error.not_playing")); if (currentSong.paused) { currentSong.play(); - return Component.text("Resumed the current song").color(bot.colorPalette.defaultColor); + return Component.translatable("commands.music.resumed", bot.colorPalette.defaultColor); } else { currentSong.pause(); - return Component.text("Paused the current song").color(bot.colorPalette.defaultColor); + return Component.translatable("commands.music.paused", bot.colorPalette.defaultColor); } } @@ -540,7 +555,7 @@ public class MusicCommand extends Command implements Listener { final Bot bot = context.bot; final Song currentSong = bot.music.currentSong; - if (currentSong == null) throw new CommandException(Component.text("No song is currently playing")); + if (currentSong == null) throw new CommandException(Component.translatable("commands.music.error.not_playing")); final List components = new ObjectArrayList<>(); @@ -552,18 +567,18 @@ public class MusicCommand extends Command implements Listener { final String formattedNotesCount = formatter.format(currentSong.size()); if (isNotNullAndNotBlank(currentSong.name)) - components.add(Component.translatable("Title/Filename: %s", keyColor, Component.text(currentSong.name, valueColor))); + components.add(Component.translatable("commands.music.info.title", keyColor, Component.text(currentSong.name, valueColor))); if (isNotNullAndNotBlank(currentSong.requester)) - components.add(Component.translatable("Requested by: %s", keyColor, Component.text(currentSong.requester, valueColor))); + components.add(Component.translatable("commands.music.info.requester", keyColor, Component.text(currentSong.requester, valueColor))); if (isNotNullAndNotBlank(currentSong.songAuthor)) - components.add(Component.translatable("Author: %s", keyColor, Component.text(currentSong.songAuthor, valueColor))); + components.add(Component.translatable("commands.music.info.author", keyColor, Component.text(currentSong.songAuthor, valueColor))); if (isNotNullAndNotBlank(currentSong.songOriginalAuthor)) - components.add(Component.translatable("Original author: %s", keyColor, Component.text(currentSong.songOriginalAuthor, valueColor))); + components.add(Component.translatable("commands.music.info.original_author", keyColor, Component.text(currentSong.songOriginalAuthor, valueColor))); if (isNotNullAndNotBlank(currentSong.tracks)) - components.add(Component.translatable("Tracks: %s", keyColor, Component.text(currentSong.tracks, valueColor))); - components.add(Component.translatable("Notes: %s", keyColor, Component.text(formattedNotesCount, valueColor))); + components.add(Component.translatable("commands.music.info.tracks", keyColor, Component.text(currentSong.tracks, valueColor))); + components.add(Component.translatable("commands.music.info.notes", keyColor, Component.text(formattedNotesCount, valueColor))); if (isNotNullAndNotBlank(currentSong.songDescription)) - components.add(Component.translatable("Description: %s", keyColor, Component.text(currentSong.songDescription, valueColor))); + components.add(Component.translatable("commands.music.info.description", keyColor, Component.text(currentSong.songDescription, valueColor))); return Component.join(JoinConfiguration.newlines(), components); } @@ -576,10 +591,10 @@ public class MusicCommand extends Command implements Listener { final Song song = new Song( "test_song", bot, - "Test Song", + I18nUtilities.get("commands.music.testsong.title"), "chayapak", "hhhzzzsss", - "SongPlayer's test song ported to ChomeNS Bot", + I18nUtilities.get("commands.music.testsong.description"), null, false ); @@ -613,6 +628,6 @@ public class MusicCommand extends Command implements Listener { bot.music.songQueue.add(song); - return Component.text("Test song has been added to the song queue").color(bot.colorPalette.defaultColor); + return Component.translatable("commands.music.testsong.output", bot.colorPalette.defaultColor); } } diff --git a/src/main/java/me/chayapak1/chomens_bot/commands/NetCommandCommand.java b/src/main/java/me/chayapak1/chomens_bot/commands/NetCommandCommand.java index 18039567..ff013e75 100644 --- a/src/main/java/me/chayapak1/chomens_bot/commands/NetCommandCommand.java +++ b/src/main/java/me/chayapak1/chomens_bot/commands/NetCommandCommand.java @@ -15,7 +15,6 @@ public class NetCommandCommand extends Command { public NetCommandCommand () { super( "netcmd", - "Runs a command on the specified server(s) and return its output", new String[] { " " }, new String[] { "networkcommand", "irccommand", "remotecommand" }, TrustLevel.TRUSTED @@ -52,7 +51,7 @@ public class NetCommandCommand extends Command { } } - if (bots.isEmpty()) throw new CommandException(Component.text("No servers have been found with your input")); + if (bots.isEmpty()) throw new CommandException(Component.translatable("commands.netcmd.error.no_servers_found")); final String command = context.getString(true, true); diff --git a/src/main/java/me/chayapak1/chomens_bot/commands/NetMessageCommand.java b/src/main/java/me/chayapak1/chomens_bot/commands/NetMessageCommand.java index 6a4c80bf..241effeb 100644 --- a/src/main/java/me/chayapak1/chomens_bot/commands/NetMessageCommand.java +++ b/src/main/java/me/chayapak1/chomens_bot/commands/NetMessageCommand.java @@ -18,7 +18,6 @@ public class NetMessageCommand extends Command { public NetMessageCommand () { super( "netmsg", - "Broadcasts a message to all of the servers that the bot is connected", new String[] { "" }, new String[] { "networkmessage", "irc" }, TrustLevel.PUBLIC, @@ -46,7 +45,7 @@ public class NetMessageCommand extends Command { Component.empty() .append(Component.text(originServerAddress).color(NamedTextColor.GRAY)) .append(Component.newline()) - .append(Component.text("Click here to copy the server host and port to your clipboard").color(NamedTextColor.GREEN)) + .append(Component.translatable("commands.netmsg.hover.copy_server_to_clipboard", NamedTextColor.GREEN)) ) ); @@ -68,9 +67,10 @@ public class NetMessageCommand extends Command { .clickEvent(ClickEvent.copyToClipboard(rawMessage)) .hoverEvent( HoverEvent.showText( - Component - .text("Click here to copy the message to your clipboard") - .color(NamedTextColor.GREEN) + Component.translatable( + "commands.generic.copy_to_copy_message", + NamedTextColor.GREEN + ) ) ) ).color(NamedTextColor.DARK_GRAY); diff --git a/src/main/java/me/chayapak1/chomens_bot/commands/RandomTeleportCommand.java b/src/main/java/me/chayapak1/chomens_bot/commands/RandomTeleportCommand.java index 1d6b8a90..e2cb7835 100644 --- a/src/main/java/me/chayapak1/chomens_bot/commands/RandomTeleportCommand.java +++ b/src/main/java/me/chayapak1/chomens_bot/commands/RandomTeleportCommand.java @@ -15,7 +15,6 @@ public class RandomTeleportCommand extends Command { public RandomTeleportCommand () { super( "rtp", - "Randomly teleports you", new String[] {}, new String[] { "randomteleport" }, TrustLevel.PUBLIC, @@ -38,12 +37,11 @@ public class RandomTeleportCommand extends Command { bot.core.run("essentials:teleport " + sender.profile.getIdAsString() + " " + stringPosition); - return Component.empty() - .append(Component.text("Teleporting ")) - .append(Component.text(sender.profile.getName()).color(bot.colorPalette.username)) - .append(Component.text(" to ")) - .append(Component.text(stringPosition).color(NamedTextColor.GREEN)) - .append(Component.text("...")) - .color(bot.colorPalette.defaultColor); + return Component.translatable( + "commands.rtp.output", + bot.colorPalette.defaultColor, + Component.text(sender.profile.getName()).color(bot.colorPalette.username), + Component.text(stringPosition).color(NamedTextColor.GREEN) + ); } } diff --git a/src/main/java/me/chayapak1/chomens_bot/commands/RefillCoreCommand.java b/src/main/java/me/chayapak1/chomens_bot/commands/RefillCoreCommand.java index 496c91fc..0ab1680b 100644 --- a/src/main/java/me/chayapak1/chomens_bot/commands/RefillCoreCommand.java +++ b/src/main/java/me/chayapak1/chomens_bot/commands/RefillCoreCommand.java @@ -11,7 +11,6 @@ public class RefillCoreCommand extends Command { public RefillCoreCommand () { super( "refillcore", - "Refills and resets the bots command core", new String[] {}, new String[] { "rc" }, TrustLevel.PUBLIC @@ -27,8 +26,9 @@ public class RefillCoreCommand extends Command { bot.core.reset(); bot.core.refill(); - return Component - .text("Refilled the command core") - .color(bot.colorPalette.defaultColor); + return Component.translatable( + "commands.refillcore.output", + bot.colorPalette.defaultColor + ); } } diff --git a/src/main/java/me/chayapak1/chomens_bot/commands/RestartCommand.java b/src/main/java/me/chayapak1/chomens_bot/commands/RestartCommand.java index 32a5dfba..6cbb500f 100644 --- a/src/main/java/me/chayapak1/chomens_bot/commands/RestartCommand.java +++ b/src/main/java/me/chayapak1/chomens_bot/commands/RestartCommand.java @@ -6,13 +6,13 @@ import me.chayapak1.chomens_bot.command.Command; import me.chayapak1.chomens_bot.command.CommandContext; import me.chayapak1.chomens_bot.command.CommandException; import me.chayapak1.chomens_bot.command.TrustLevel; +import me.chayapak1.chomens_bot.util.I18nUtilities; import net.kyori.adventure.text.Component; public class RestartCommand extends Command { public RestartCommand () { super( "restart", - "Gracefully restarts the bot", new String[] { "[reason]" }, new String[] {}, TrustLevel.OWNER @@ -25,8 +25,8 @@ public class RestartCommand extends Command { final String reason = context.getString(true, false); - Main.stop(12, reason.isEmpty() ? null : reason, "Restarting.."); + Main.stop(12, reason.isEmpty() ? null : reason, I18nUtilities.get("info.restarting")); - return Component.text("Restarting").color(bot.colorPalette.defaultColor); + return Component.translatable("commands.restart.output", bot.colorPalette.defaultColor); } } diff --git a/src/main/java/me/chayapak1/chomens_bot/commands/ScreenshareCommand.java b/src/main/java/me/chayapak1/chomens_bot/commands/ScreenshareCommand.java index 5f5dcec0..c8e0eac6 100644 --- a/src/main/java/me/chayapak1/chomens_bot/commands/ScreenshareCommand.java +++ b/src/main/java/me/chayapak1/chomens_bot/commands/ScreenshareCommand.java @@ -8,11 +8,11 @@ import me.chayapak1.chomens_bot.command.TrustLevel; import net.kyori.adventure.text.Component; import org.cloudburstmc.math.vector.Vector3i; +// this command uses english public class ScreenshareCommand extends Command { public ScreenshareCommand () { super( "screenshare", - "Shares my screen", new String[] { "start ", "stop", @@ -82,7 +82,7 @@ public class ScreenshareCommand extends Command { .append(Component.text(fps).color(bot.colorPalette.number)) .color(bot.colorPalette.defaultColor); } - default -> throw new CommandException(Component.text("Invalid action")); + default -> throw new CommandException(Component.translatable("commands.generic.error.invalid_action")); } } catch (final NumberFormatException e) { throw new CommandException(Component.text("Invalid integer")); diff --git a/src/main/java/me/chayapak1/chomens_bot/commands/SeenCommand.java b/src/main/java/me/chayapak1/chomens_bot/commands/SeenCommand.java index 72919405..8ac3c8d1 100644 --- a/src/main/java/me/chayapak1/chomens_bot/commands/SeenCommand.java +++ b/src/main/java/me/chayapak1/chomens_bot/commands/SeenCommand.java @@ -24,7 +24,6 @@ public class SeenCommand extends Command { public SeenCommand () { super( "seen", - "Shows the last seen of a player", new String[] { "" }, new String[] { "lastseen" }, TrustLevel.PUBLIC @@ -36,7 +35,7 @@ public class SeenCommand extends Command { final Bot bot = context.bot; if (Main.database == null) - throw new CommandException(Component.text("Database is not enabled in the bot's config")); + throw new CommandException(Component.translatable("commands.generic.error.database_disabled")); Main.database.checkOverloaded(); @@ -51,11 +50,12 @@ public class SeenCommand extends Command { online = true; onlineComponents.add( - Component.empty() - .append(Component.text(player)) - .append(Component.text(" is currently online on ")) - .append(Component.text(eachBot.getServerString())) - .color(NamedTextColor.RED) + Component.translatable( + "commands.seen.error.currently_online", + NamedTextColor.RED, + Component.text(player), + Component.text(eachBot.getServerString()) + ) ); } } @@ -66,22 +66,22 @@ public class SeenCommand extends Command { try { final JsonNode playerElement = bot.playersDatabase.getPlayerData(player); if (playerElement == null) throw new CommandException(Component.translatable( - "%s was never seen", + "commands.seen.error.never_seen", Component.text(player) )); final ObjectNode lastSeen = (ObjectNode) playerElement.get("lastSeen"); if (lastSeen == null || lastSeen.isNull()) - throw new CommandException(Component.text("This player doesn't seem to have the last seen entry in the database for some reason.")); + throw new CommandException(Component.translatable("commands.seen.error.no_last_seen_entry")); final JsonNode time = lastSeen.get("time"); if (time == null || time.isNull()) - throw new CommandException(Component.text("This player doesn't seem to have the `lastSeen.time` entry in the database for some reason.")); + throw new CommandException(Component.translatable("commands.seen.error.no_time_entry")); final Instant instant = Instant.ofEpochMilli(time.asLong()); - final ZoneId zoneId = ZoneId.of("UTC"); // should i be doing this? + final ZoneId zoneId = ZoneId.of("UTC"); // should i be using this? final OffsetDateTime localDateTime = OffsetDateTime.ofInstant(instant, zoneId); final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEEE, MMMM d, yyyy, hh:mm:ss a Z"); @@ -89,12 +89,15 @@ public class SeenCommand extends Command { final String server = lastSeen.get("server").asText(); - context.sendOutput(Component.translatable( - "%s was last seen at %s on %s", - Component.text(player).color(bot.colorPalette.username), - Component.text(formattedTime).color(bot.colorPalette.string), - Component.text(server).color(bot.colorPalette.string) - ).color(bot.colorPalette.defaultColor)); + context.sendOutput( + Component.translatable( + "commands.seen.output", + bot.colorPalette.defaultColor, + Component.text(player, bot.colorPalette.username), + Component.text(formattedTime, bot.colorPalette.string), + Component.text(server, bot.colorPalette.string) + ) + ); } catch (final CommandException e) { context.sendOutput(e.message.color(NamedTextColor.RED)); } diff --git a/src/main/java/me/chayapak1/chomens_bot/commands/ServerEvalCommand.java b/src/main/java/me/chayapak1/chomens_bot/commands/ServerEvalCommand.java index af4c900f..5f819bb6 100644 --- a/src/main/java/me/chayapak1/chomens_bot/commands/ServerEvalCommand.java +++ b/src/main/java/me/chayapak1/chomens_bot/commands/ServerEvalCommand.java @@ -19,7 +19,6 @@ public class ServerEvalCommand extends Command { public ServerEvalCommand () { super( "servereval", - "Evaluate codes using LuaJ", new String[] { "" }, new String[] {}, TrustLevel.OWNER @@ -36,7 +35,7 @@ public class ServerEvalCommand extends Command { if (lua != null) lua.close(); lua = null; - return Component.text("Reset the Lua instance").color(bot.colorPalette.defaultColor); + return Component.translatable("commands.servereval.reset", bot.colorPalette.defaultColor); } bot.executorService.submit(() -> { diff --git a/src/main/java/me/chayapak1/chomens_bot/commands/StopCommand.java b/src/main/java/me/chayapak1/chomens_bot/commands/StopCommand.java index a5094124..03449e70 100644 --- a/src/main/java/me/chayapak1/chomens_bot/commands/StopCommand.java +++ b/src/main/java/me/chayapak1/chomens_bot/commands/StopCommand.java @@ -12,7 +12,6 @@ public class StopCommand extends Command { public StopCommand () { super( "stop", - "Gracefully stops the bot", new String[] { "[reason]" }, new String[] {}, TrustLevel.OWNER @@ -27,6 +26,6 @@ public class StopCommand extends Command { Main.stop(0, reason.isEmpty() ? null : reason); - return Component.text("Stopping").color(bot.colorPalette.defaultColor); + return Component.translatable("commands.stop.output").color(bot.colorPalette.defaultColor); } } diff --git a/src/main/java/me/chayapak1/chomens_bot/commands/TPSBarCommand.java b/src/main/java/me/chayapak1/chomens_bot/commands/TPSBarCommand.java index a8d7a34f..15cf3e2a 100644 --- a/src/main/java/me/chayapak1/chomens_bot/commands/TPSBarCommand.java +++ b/src/main/java/me/chayapak1/chomens_bot/commands/TPSBarCommand.java @@ -12,7 +12,6 @@ public class TPSBarCommand extends Command { public TPSBarCommand () { super( "tpsbar", - "Shows the server's TPS using Minecraft Bossbar", new String[] { "" }, new String[] { "tps" }, TrustLevel.PUBLIC @@ -30,19 +29,21 @@ public class TPSBarCommand extends Command { switch (action) { case "on" -> { bot.tps.on(); - return Component.empty() - .append(Component.text("TPSBar is now ")) - .append(Component.text("enabled").color(NamedTextColor.GREEN)) - .color(bot.colorPalette.defaultColor); + return Component.translatable( + "commands.tpsbar.output", + bot.colorPalette.defaultColor, + Component.translatable("commands.generic.enabled", NamedTextColor.GREEN) + ); } case "off" -> { bot.tps.off(); - return Component.empty() - .append(Component.text("TPSBar is now ")) - .append(Component.text("disabled").color(NamedTextColor.RED)) - .color(bot.colorPalette.defaultColor); + return Component.translatable( + "commands.tpsbar.output", + bot.colorPalette.defaultColor, + Component.translatable("commands.generic.disabled", NamedTextColor.RED) + ); } - default -> throw new CommandException(Component.text("Invalid action")); + default -> throw new CommandException(Component.translatable("commands.generic.error.invalid_action")); } } } diff --git a/src/main/java/me/chayapak1/chomens_bot/commands/TestCommand.java b/src/main/java/me/chayapak1/chomens_bot/commands/TestCommand.java index 7c7327e7..6b687100 100644 --- a/src/main/java/me/chayapak1/chomens_bot/commands/TestCommand.java +++ b/src/main/java/me/chayapak1/chomens_bot/commands/TestCommand.java @@ -11,7 +11,6 @@ public class TestCommand extends Command { public TestCommand () { super( "test", - "Tests if the bot is working", new String[] { "[args]" }, new String[] {}, TrustLevel.PUBLIC @@ -21,7 +20,7 @@ public class TestCommand extends Command { @Override public Component execute (final CommandContext context) throws CommandException { return Component.translatable( - "Hello, World! Username: %s, Sender UUID: %s, Prefix: %s, Args: %s", + "commands.test.output", Component.text(context.sender.profile.getName()), Component.text(context.sender.profile.getIdAsString()), Component.text(context.prefix), diff --git a/src/main/java/me/chayapak1/chomens_bot/commands/TimeCommand.java b/src/main/java/me/chayapak1/chomens_bot/commands/TimeCommand.java index f6b9cf39..0657e8b0 100644 --- a/src/main/java/me/chayapak1/chomens_bot/commands/TimeCommand.java +++ b/src/main/java/me/chayapak1/chomens_bot/commands/TimeCommand.java @@ -17,7 +17,6 @@ public class TimeCommand extends Command { public TimeCommand () { super( "time", - "Shows the date and time for the specified timezone", new String[] { "" }, new String[] { "dateandtime", "date" }, TrustLevel.PUBLIC @@ -38,12 +37,13 @@ public class TimeCommand extends Command { final String formattedTime = zonedDateTime.format(formatter); return Component.translatable( - "The current time for %s is: %s", + "commands.time.output", + bot.colorPalette.defaultColor, Component.text(timezone).color(bot.colorPalette.string), Component.text(formattedTime).color(NamedTextColor.GREEN) - ).color(bot.colorPalette.defaultColor); + ); } catch (final DateTimeException e) { - throw new CommandException(Component.text("Invalid timezone (case-sensitive)")); + throw new CommandException(Component.translatable("commands.time.error.invalid_timezone")); } } } diff --git a/src/main/java/me/chayapak1/chomens_bot/commands/TranslateCommand.java b/src/main/java/me/chayapak1/chomens_bot/commands/TranslateCommand.java index ccfad654..f1248c49 100644 --- a/src/main/java/me/chayapak1/chomens_bot/commands/TranslateCommand.java +++ b/src/main/java/me/chayapak1/chomens_bot/commands/TranslateCommand.java @@ -32,7 +32,6 @@ public class TranslateCommand extends Command { public TranslateCommand () { super( "translate", - "Translates a message using Google Translate", new String[] { " " }, new String[] {}, TrustLevel.PUBLIC, @@ -66,10 +65,10 @@ public class TranslateCommand extends Command { context.sendOutput( Component .translatable( - "Result: %s", - Component.text(result.translation()).color(NamedTextColor.GREEN) + "commands.translate.result", + bot.colorPalette.secondary, + Component.text(result.translation(), NamedTextColor.GREEN) ) - .color(bot.colorPalette.secondary) ); } catch (final Exception e) { context.sendOutput(Component.text(e.toString()).color(NamedTextColor.RED)); diff --git a/src/main/java/me/chayapak1/chomens_bot/commands/UUIDCommand.java b/src/main/java/me/chayapak1/chomens_bot/commands/UUIDCommand.java index ba1473cd..380951fa 100644 --- a/src/main/java/me/chayapak1/chomens_bot/commands/UUIDCommand.java +++ b/src/main/java/me/chayapak1/chomens_bot/commands/UUIDCommand.java @@ -16,7 +16,6 @@ public class UUIDCommand extends Command { public UUIDCommand () { super( "uuid", - "Shows your UUID or other player's UUID", new String[] { "[username]" }, new String[] {}, TrustLevel.PUBLIC @@ -44,39 +43,45 @@ public class UUIDCommand extends Command { } return Component.translatable( - "%s's UUID: %s", + "commands.uuid.other", + NamedTextColor.GREEN, Component.text(name), Component - .text(uuid) + .text(uuid, bot.colorPalette.uuid) .hoverEvent( HoverEvent.showText( - Component.text("Click here to copy the UUID to your clipboard").color(NamedTextColor.GREEN) + Component.translatable( + "commands.generic.click_to_copy_uuid", + NamedTextColor.GREEN + ) ) ) .clickEvent( ClickEvent.copyToClipboard(uuid) ) - .color(bot.colorPalette.uuid) - ).color(NamedTextColor.GREEN); + ); } else { final PlayerEntry entry = context.sender; final String uuid = entry.profile.getIdAsString(); return Component.translatable( - "Your UUID: %s", + "commands.uuid.self", + NamedTextColor.GREEN, Component - .text(uuid) + .text(uuid, bot.colorPalette.uuid) .hoverEvent( HoverEvent.showText( - Component.text("Click here to copy the UUID to your clipboard").color(NamedTextColor.GREEN) + Component.translatable( + "commands.generic.click_to_copy_uuid", + NamedTextColor.GREEN + ) ) ) .clickEvent( ClickEvent.copyToClipboard(uuid) ) - .color(bot.colorPalette.uuid) - ).color(NamedTextColor.GREEN); + ); } } } diff --git a/src/main/java/me/chayapak1/chomens_bot/commands/UrbanCommand.java b/src/main/java/me/chayapak1/chomens_bot/commands/UrbanCommand.java index e865e9ad..833e41fe 100644 --- a/src/main/java/me/chayapak1/chomens_bot/commands/UrbanCommand.java +++ b/src/main/java/me/chayapak1/chomens_bot/commands/UrbanCommand.java @@ -34,7 +34,6 @@ public class UrbanCommand extends Command { public UrbanCommand () { super( "urban", - "Urban Dictionary in Minecraft", new String[] { "" }, new String[] {}, TrustLevel.PUBLIC, @@ -46,7 +45,7 @@ public class UrbanCommand extends Command { } public Component execute (final CommandContext context) throws CommandException { - if (requestsPerSecond.get() > 3) throw new CommandException(Component.text("Too many requests")); + if (requestsPerSecond.get() > 3) throw new CommandException(Component.translatable("commands.urban.error.too_many_requests")); final Bot bot = context.bot; @@ -69,9 +68,9 @@ public class UrbanCommand extends Command { final JsonArray list = jsonObject.getAsJsonArray("list"); - if (list.isEmpty()) context.sendOutput(Component.text("No results found").color(NamedTextColor.RED)); + if (list.isEmpty()) context.sendOutput(Component.translatable("commands.urban.error.no_results", NamedTextColor.RED)); - Component discordComponent = Component.text("*Showing only 3 results because Discord*").append(Component.newline()); + Component discordComponent = Component.translatable("commands.urban.discord_warning").append(Component.newline()); int count = 0; int index = 1; @@ -81,7 +80,7 @@ public class UrbanCommand extends Command { final JsonObject definitionObject = element.getAsJsonObject(); final String word = definitionObject.get("word").getAsString(); - final String _definition = definitionObject.get("definition").getAsString(); + final String originalDefinition = definitionObject.get("definition").getAsString(); final DecimalFormat formatter = new DecimalFormat("#,###"); @@ -90,40 +89,35 @@ public class UrbanCommand extends Command { final String thumbsDown = formatter.format(definitionObject.get("thumbs_down").getAsInt()); final String example = definitionObject.get("example").getAsString(); - // whats the best way to implement this? + // what's the best way to implement this? // also ohio code warning Component definitionComponent = Component.empty(); - final String definition = _definition.replaceAll("\r\n?", "\n"); + final String definition = originalDefinition.replaceAll("\r\n?", "\n"); - final String[] splittedDefinition = definition.split("[\\[\\]]"); - for (int i = 0; i < splittedDefinition.length; i++) { + final String[] splitDefinition = definition.split("[\\[\\]]"); + for (int i = 0; i < splitDefinition.length; i++) { final boolean even = i % 2 == 0; final String wordWithDefinition = word + " - " + definition; final Component globalHoverEvent = Component.translatable( - """ - Written by %s - Thumbs up: %s - Thumbs down: %s - Example: %s""", - Component.text(author).color(bot.colorPalette.string), - Component.text(thumbsUp).color(NamedTextColor.GREEN), - Component.text(thumbsDown).color(NamedTextColor.RED), - Component.text(example.replaceAll("\r\n?", "\n")).color(bot.colorPalette.string) + "commands.urban.hover.info", + Component.text(author, bot.colorPalette.string), + Component.text(thumbsUp, NamedTextColor.GREEN), + Component.text(thumbsDown, NamedTextColor.RED), + Component.text(example.replaceAll("\r\n?", "\n"), bot.colorPalette.string) ); if (even) { definitionComponent = definitionComponent.append( Component - .text(splittedDefinition[i]) - .color(NamedTextColor.GRAY) + .text(splitDefinition[i], NamedTextColor.GRAY) .hoverEvent( HoverEvent.showText( globalHoverEvent .append(Component.newline()) - .append(Component.text("Click here to copy the word and the definition to your clipboard").color(NamedTextColor.GREEN)) + .append(Component.translatable("commands.urban.hover.copy", NamedTextColor.GREEN)) ) ) .clickEvent(ClickEvent.copyToClipboard(wordWithDefinition)) @@ -132,17 +126,23 @@ public class UrbanCommand extends Command { final String command = context.prefix + name + " " + - splittedDefinition[i]; + splitDefinition[i]; definitionComponent = definitionComponent.append( Component - .text(splittedDefinition[i]) + .text(splitDefinition[i]) .style(Style.style(TextDecoration.UNDERLINED)) .hoverEvent( HoverEvent.showText( globalHoverEvent .append(Component.newline()) - .append(Component.text("Click here to run " + command).color(NamedTextColor.GREEN)) + .append( + Component.translatable( + "commands.urban.hover.run", + NamedTextColor.GREEN, + Component.text(command) + ) + ) ) ) .clickEvent( diff --git a/src/main/java/me/chayapak1/chomens_bot/commands/ValidateCommand.java b/src/main/java/me/chayapak1/chomens_bot/commands/ValidateCommand.java index c3507f3f..c3f0afd2 100644 --- a/src/main/java/me/chayapak1/chomens_bot/commands/ValidateCommand.java +++ b/src/main/java/me/chayapak1/chomens_bot/commands/ValidateCommand.java @@ -12,7 +12,6 @@ public class ValidateCommand extends Command { public ValidateCommand () { super( "validate", - "Validates/shows your trust level", new String[] { "" }, new String[] { "checkhash" }, TrustLevel.TRUSTED @@ -23,21 +22,23 @@ public class ValidateCommand extends Command { public Component execute (final CommandContext context) { // Trusted - 1 // Admin - 2 - // ....... + // ... final Component trustLevelComponent = context.trustLevel.component .append(Component.text(" - ")) .append(Component.text(context.trustLevel.level)); if (context instanceof DiscordCommandContext) return Component - .translatable("You are trusted! (%s)") - .arguments(trustLevelComponent) - .color(NamedTextColor.GREEN); + .translatable( + "commands.validate.discord", + NamedTextColor.GREEN, + trustLevelComponent + ); else if (context instanceof ConsoleCommandContext) return Component - .text("You are the console! You have no trust level") - .color(NamedTextColor.GREEN); - else return Component - .translatable("Valid hash (%s)") - .arguments(trustLevelComponent) - .color(NamedTextColor.GREEN); + .translatable("commands.validate.console", NamedTextColor.GREEN); + else return Component.translatable( + "commands.validate.player", + NamedTextColor.GREEN, + trustLevelComponent + ); } } diff --git a/src/main/java/me/chayapak1/chomens_bot/commands/WeatherCommand.java b/src/main/java/me/chayapak1/chomens_bot/commands/WeatherCommand.java index eca22512..8027918a 100644 --- a/src/main/java/me/chayapak1/chomens_bot/commands/WeatherCommand.java +++ b/src/main/java/me/chayapak1/chomens_bot/commands/WeatherCommand.java @@ -20,7 +20,6 @@ public class WeatherCommand extends Command { public WeatherCommand () { super( "weather", - "Shows the weather in a place", new String[] { "" }, new String[] {}, TrustLevel.PUBLIC @@ -48,7 +47,8 @@ public class WeatherCommand extends Command { final JsonObject jsonObject = gson.fromJson(jsonOutput, JsonObject.class); return Component.translatable( - "Current weather for %s, %s:\n%s (%s), feels like %s (%s)\nCondition: %s\nCloud cover: %s\nHumidity: %s\nTime: %s", + "commands.weather.info", + bot.colorPalette.defaultColor, Component.text(jsonObject.get("location").getAsJsonObject().get("name").getAsString()).color(bot.colorPalette.string), Component.text(jsonObject.get("location").getAsJsonObject().get("country").getAsString()).color(bot.colorPalette.string), Component @@ -131,9 +131,9 @@ public class WeatherCommand extends Command { .getAsString() ) .color(bot.colorPalette.string) - ).color(bot.colorPalette.defaultColor); + ); } catch (final Exception e) { - throw new CommandException(Component.text("Location \"" + location + "\" not found")); + throw new CommandException(Component.translatable("commands.weather.error.not_found", Component.text(location))); } } } diff --git a/src/main/java/me/chayapak1/chomens_bot/commands/WhitelistCommand.java b/src/main/java/me/chayapak1/chomens_bot/commands/WhitelistCommand.java index 97393edc..60289114 100644 --- a/src/main/java/me/chayapak1/chomens_bot/commands/WhitelistCommand.java +++ b/src/main/java/me/chayapak1/chomens_bot/commands/WhitelistCommand.java @@ -16,7 +16,6 @@ public class WhitelistCommand extends Command { public WhitelistCommand () { super( "whitelist", - "Manages whitelist", new String[] { "enable", "disable", "add ", "remove ", "clear", "list" }, new String[] {}, TrustLevel.ADMIN @@ -35,14 +34,14 @@ public class WhitelistCommand extends Command { bot.whitelist.enable(); - return Component.text("Enabled whitelist").color(bot.colorPalette.defaultColor); + return Component.translatable("commands.whitelist.enable", bot.colorPalette.defaultColor); } case "disable" -> { context.checkOverloadArgs(1); bot.whitelist.disable(); - return Component.text("Disabled whitelist").color(bot.colorPalette.defaultColor); + return Component.translatable("commands.whitelist.disable", bot.colorPalette.defaultColor); } case "add" -> { final String player = context.getString(true, true); @@ -50,9 +49,10 @@ public class WhitelistCommand extends Command { bot.whitelist.add(player); return Component.translatable( - "Added %s to the whitelist", - Component.text(player).color(bot.colorPalette.username) - ).color(bot.colorPalette.defaultColor); + "commands.whitelist.add", + bot.colorPalette.defaultColor, + Component.text(player, bot.colorPalette.username) + ); } case "remove" -> { try { @@ -61,11 +61,12 @@ public class WhitelistCommand extends Command { final String player = bot.whitelist.remove(index); return Component.translatable( - "Removed %s from the whitelist", - Component.text(player).color(bot.colorPalette.username) - ).color(bot.colorPalette.defaultColor); - } catch (final IndexOutOfBoundsException | IllegalArgumentException | NullPointerException ignored) { - throw new CommandException(Component.text("Invalid index")); + "commands.whitelist.remove", + bot.colorPalette.defaultColor, + Component.text(player, bot.colorPalette.username) + ); + } catch (final IndexOutOfBoundsException | IllegalArgumentException | NullPointerException e) { + throw new CommandException(Component.translatable("commands.generic.error.invalid_index")); } } case "clear" -> { @@ -73,7 +74,7 @@ public class WhitelistCommand extends Command { bot.whitelist.clear(); - return Component.text("Cleared the whitelist").color(bot.colorPalette.defaultColor); + return Component.translatable("commands.whitelist.clear", bot.colorPalette.defaultColor); } case "list" -> { context.checkOverloadArgs(1); @@ -94,7 +95,7 @@ public class WhitelistCommand extends Command { } return Component.empty() - .append(Component.text("Whitelisted players ").color(NamedTextColor.GREEN)) + .append(Component.translatable("commands.whitelist.whitelisted_players_text").color(NamedTextColor.GREEN)) .append(Component.text("(").color(NamedTextColor.DARK_GRAY)) .append(Component.text(bot.whitelist.list.size()).color(NamedTextColor.GRAY)) .append(Component.text(")").color(NamedTextColor.DARK_GRAY)) @@ -103,7 +104,7 @@ public class WhitelistCommand extends Command { Component.join(JoinConfiguration.newlines(), playersComponent) ); } - default -> throw new CommandException(Component.text("Invalid action")); + default -> throw new CommandException(Component.translatable("commands.generic.error.invalid_action")); } } } diff --git a/src/main/java/me/chayapak1/chomens_bot/commands/WikipediaCommand.java b/src/main/java/me/chayapak1/chomens_bot/commands/WikipediaCommand.java index 0b73fe0e..03a56cc1 100644 --- a/src/main/java/me/chayapak1/chomens_bot/commands/WikipediaCommand.java +++ b/src/main/java/me/chayapak1/chomens_bot/commands/WikipediaCommand.java @@ -29,12 +29,11 @@ public class WikipediaCommand extends Command { public WikipediaCommand () { super( "wikipedia", - "Wikipedia in Minecraft", new String[] { "" }, new String[] { "wiki" }, TrustLevel.PUBLIC, false, - new ChatPacketType[]{ ChatPacketType.DISGUISED } + new ChatPacketType[] { ChatPacketType.DISGUISED } ); } @@ -84,7 +83,7 @@ public class WikipediaCommand extends Command { if (pageID == -1) { throw new CommandException( Component.translatable( - "Cannot find page: %s", + "commands.wikipedia.error.not_found", Component.text(page) ) ); @@ -102,7 +101,7 @@ public class WikipediaCommand extends Command { final String title = pageOutput.get("title").getAsString(); final String extracted = HTMLUtilities.toFormattingCodes(pageOutput.get("extract").getAsString()); - if (extracted == null) throw new CommandException(Component.text("No contents found")); + if (extracted == null) throw new CommandException(Component.translatable("commands.wikipedia.error.no_contents")); component = component .append( @@ -119,7 +118,7 @@ public class WikipediaCommand extends Command { context.sendOutput(component); } catch (final NumberFormatException e) { - context.sendOutput(Component.text("Failed parsing page ID").color(NamedTextColor.RED)); + context.sendOutput(Component.translatable("commands.wikipedia.error.fail_page_id_parse").color(NamedTextColor.RED)); bot.logger.error(e); } catch (final CommandException e) { context.sendOutput(e.message.color(NamedTextColor.RED)); diff --git a/src/main/java/me/chayapak1/chomens_bot/data/logging/LogType.java b/src/main/java/me/chayapak1/chomens_bot/data/logging/LogType.java index e394b6a3..5efec74f 100644 --- a/src/main/java/me/chayapak1/chomens_bot/data/logging/LogType.java +++ b/src/main/java/me/chayapak1/chomens_bot/data/logging/LogType.java @@ -1,17 +1,18 @@ package me.chayapak1.chomens_bot.data.logging; +import me.chayapak1.chomens_bot.util.I18nUtilities; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; public enum LogType { - INFO(Component.text("Info").color(NamedTextColor.GREEN)), - CHAT(Component.text("Chat").color(NamedTextColor.GOLD)), - TRUSTED_BROADCAST(Component.text("Trusted Broadcast").color(NamedTextColor.AQUA)), - ERROR(Component.text("Error").color(NamedTextColor.RED)), - COMMAND_OUTPUT(Component.text("Command Output").color(NamedTextColor.LIGHT_PURPLE)), - AUTH(Component.text("Auth").color(NamedTextColor.RED)), - SIMPLE_VOICE_CHAT(Component.text("Simple Voice Chat").color(NamedTextColor.AQUA)), - DISCORD(Component.text("Discord").color(NamedTextColor.BLUE)); + INFO(Component.translatable(I18nUtilities.get("log_type.info"), NamedTextColor.GREEN)), + CHAT(Component.translatable(I18nUtilities.get("log_type.chat"), NamedTextColor.GOLD)), + TRUSTED_BROADCAST(Component.translatable(I18nUtilities.get("log_type.trusted_broadcast"), NamedTextColor.AQUA)), + ERROR(Component.translatable(I18nUtilities.get("log_type.error"), NamedTextColor.RED)), + COMMAND_OUTPUT(Component.translatable(I18nUtilities.get("log_type.command_output"), NamedTextColor.LIGHT_PURPLE)), + AUTH(Component.translatable(I18nUtilities.get("log_type.auth"), NamedTextColor.RED)), + SIMPLE_VOICE_CHAT(Component.translatable(I18nUtilities.get("log_type.simple_voice_chat"), NamedTextColor.AQUA)), + DISCORD(Component.translatable(I18nUtilities.get("log_type.discord"), NamedTextColor.BLUE)); public final Component component; diff --git a/src/main/java/me/chayapak1/chomens_bot/plugins/AuthPlugin.java b/src/main/java/me/chayapak1/chomens_bot/plugins/AuthPlugin.java index 386fa0e5..f37f47d3 100644 --- a/src/main/java/me/chayapak1/chomens_bot/plugins/AuthPlugin.java +++ b/src/main/java/me/chayapak1/chomens_bot/plugins/AuthPlugin.java @@ -4,6 +4,7 @@ import me.chayapak1.chomens_bot.Bot; import me.chayapak1.chomens_bot.data.listener.Listener; import me.chayapak1.chomens_bot.data.logging.LogType; import me.chayapak1.chomens_bot.data.player.PlayerEntry; +import me.chayapak1.chomens_bot.util.I18nUtilities; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import org.geysermc.mcprotocollib.network.event.session.DisconnectedEvent; @@ -44,14 +45,14 @@ public class AuthPlugin implements Listener { bot.logger.log( LogType.AUTH, Component - .text("Player has been verified") + .text(I18nUtilities.get("auth.logger_verified")) .color(NamedTextColor.GREEN) ); bot.chomeNSMod.sendMessage( target, Component - .text("You have been verified") + .text(I18nUtilities.get("auth.player_verified")) .color(NamedTextColor.GREEN) ); } @@ -63,7 +64,7 @@ public class AuthPlugin implements Listener { if (target == null) return; - bot.filterManager.add(target, "Authentication timed out"); + bot.filterManager.add(target, I18nUtilities.get("auth.timed_out")); } private void cleanup () { diff --git a/src/main/java/me/chayapak1/chomens_bot/plugins/ChomeNSModIntegrationPlugin.java b/src/main/java/me/chayapak1/chomens_bot/plugins/ChomeNSModIntegrationPlugin.java index 11b93b80..4df3bcb1 100644 --- a/src/main/java/me/chayapak1/chomens_bot/plugins/ChomeNSModIntegrationPlugin.java +++ b/src/main/java/me/chayapak1/chomens_bot/plugins/ChomeNSModIntegrationPlugin.java @@ -20,6 +20,7 @@ import me.chayapak1.chomens_bot.data.listener.Listener; import me.chayapak1.chomens_bot.data.logging.LogType; import me.chayapak1.chomens_bot.data.player.PlayerEntry; import me.chayapak1.chomens_bot.util.Ascii85; +import me.chayapak1.chomens_bot.util.I18nUtilities; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.TranslatableComponent; @@ -186,7 +187,7 @@ public class ChomeNSModIntegrationPlugin implements Listener { bot.logger.log( LogType.INFO, Component.translatable( - "Ignoring suspected replay attack payload with metadata: %s", + I18nUtilities.get("chomens_mod.replay_attack"), Component.text(metadata.toString()) // PayloadMetadata has toString() ) ); diff --git a/src/main/java/me/chayapak1/chomens_bot/plugins/CommandHandlerPlugin.java b/src/main/java/me/chayapak1/chomens_bot/plugins/CommandHandlerPlugin.java index 3928683d..4670ca96 100644 --- a/src/main/java/me/chayapak1/chomens_bot/plugins/CommandHandlerPlugin.java +++ b/src/main/java/me/chayapak1/chomens_bot/plugins/CommandHandlerPlugin.java @@ -10,13 +10,18 @@ import me.chayapak1.chomens_bot.command.contexts.*; import me.chayapak1.chomens_bot.commands.*; import me.chayapak1.chomens_bot.data.listener.Listener; import me.chayapak1.chomens_bot.util.ExceptionUtilities; +import me.chayapak1.chomens_bot.util.I18nUtilities; import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Role; import net.dv8tion.jda.api.events.message.MessageReceivedEvent; import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.TranslatableComponent; +import net.kyori.adventure.text.TranslationArgument; import net.kyori.adventure.text.event.HoverEvent; +import net.kyori.adventure.text.event.HoverEventSource; import net.kyori.adventure.text.format.NamedTextColor; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; @@ -136,14 +141,20 @@ public class CommandHandlerPlugin implements Listener { // so I made it return nothing if we're in game if (command == null) { if (!inGame) - context.sendOutput(Component.text("Unknown command: " + commandName).color(NamedTextColor.RED)); + context.sendOutput( + Component.translatable( + "command_handler.unknown_command", + NamedTextColor.RED, + Component.text(commandName) + ) + ); return; } if (!bypass) { if (disabled) { - context.sendOutput(Component.text("ChomeNS Bot is currently disabled").color(NamedTextColor.RED)); + context.sendOutput(Component.translatable("command_handler.disabled", NamedTextColor.RED)); return; } else if ( context instanceof final PlayerCommandContext playerContext && @@ -157,7 +168,7 @@ public class CommandHandlerPlugin implements Listener { final TrustLevel trustLevel = command.trustLevel; if (trustLevel != TrustLevel.PUBLIC && splitInput.length < 2 && inGame) { - context.sendOutput(Component.text("Please provide a hash").color(NamedTextColor.RED)); + context.sendOutput(Component.translatable("command_handler.no_hash_provided", NamedTextColor.RED)); return; } @@ -173,9 +184,7 @@ public class CommandHandlerPlugin implements Listener { if (context instanceof final RemoteCommandContext remote) { if (remote.source.trustLevel.level < trustLevel.level) { context.sendOutput( - Component - .text("Your don't have enough permission to execute this command!") - .color(NamedTextColor.RED) + Component.translatable("command_handler.not_enough_roles", NamedTextColor.RED) ); return; } @@ -194,7 +203,7 @@ public class CommandHandlerPlugin implements Listener { context.sendOutput( Component .translatable( - "Your current roles don't allow you to execute %s commands!", + "command_handler.not_enough_roles.trust_level", Component.text(trustLevel.name()) ) .color(NamedTextColor.RED) @@ -210,10 +219,10 @@ public class CommandHandlerPlugin implements Listener { context.sendOutput( Component .translatable( - "Invalid %s hash", - Component.text(trustLevel.name()) + "command_handler.invalid_hash", + NamedTextColor.RED, + Component.text(trustLevel.toString()) ) - .color(NamedTextColor.RED) ); return; } @@ -227,7 +236,7 @@ public class CommandHandlerPlugin implements Listener { // should i give access to all bypass contexts instead of only console? if (!bypass && command.consoleOnly) { - context.sendOutput(Component.text("This command can only be run via console").color(NamedTextColor.RED)); + context.sendOutput(Component.translatable("command_handler.console_only", NamedTextColor.RED)); return; } @@ -253,19 +262,64 @@ public class CommandHandlerPlugin implements Listener { else context.sendOutput( Component - .text("An error occurred while trying to execute the command, hover here for stacktrace", NamedTextColor.RED) + .translatable("command_handler.exception", NamedTextColor.RED) .hoverEvent( HoverEvent.showText( - Component - .text(stackTrace) - .color(NamedTextColor.RED) + Component.text(stackTrace, NamedTextColor.RED) ) ) - .color(NamedTextColor.RED) ); } else { - context.sendOutput(Component.text(stackTrace).color(NamedTextColor.RED)); + context.sendOutput(Component.text(stackTrace, NamedTextColor.RED)); } } } + + public Component renderTranslatable (final Component original) { + final List renderedChildren = new ArrayList<>(); + final List renderedArguments = new ArrayList<>(); + + for (final Component child : original.children()) { + final Component rendered = renderTranslatable(child); + renderedChildren.add(rendered); + } + + if (original instanceof final TranslatableComponent translatableComponent) { + for (final TranslationArgument argument : translatableComponent.arguments()) { + final Component rendered = renderTranslatable(argument.asComponent()); + renderedArguments.add(TranslationArgument.component(rendered)); + } + } + + final HoverEvent hoverEvent = original.hoverEvent(); + final HoverEventSource hoverEventSource; + if ( + hoverEvent != null + && hoverEvent.action() == HoverEvent.Action.SHOW_TEXT + && hoverEvent.value() instanceof final Component hoverComponent + ) { + final Component rendered = renderTranslatable(hoverComponent); + hoverEventSource = HoverEvent.showText(rendered); + } else { + hoverEventSource = null; + } + + if (original instanceof final TranslatableComponent translatableComponent) { + final String translated = I18nUtilities.get(translatableComponent.key()); + + return translatableComponent + .key( + (translated == null ? "" : "chomens_bot.") + // sometimes we can collide with minecraft's + translatableComponent.key() + ) + .fallback(translated) + .children(renderedChildren) + .arguments(renderedArguments) + .hoverEvent(hoverEventSource); + } else { + return original + .children(renderedChildren) + .hoverEvent(hoverEventSource); + } + } } diff --git a/src/main/java/me/chayapak1/chomens_bot/plugins/DiscordPlugin.java b/src/main/java/me/chayapak1/chomens_bot/plugins/DiscordPlugin.java index 165556de..f4ffe733 100644 --- a/src/main/java/me/chayapak1/chomens_bot/plugins/DiscordPlugin.java +++ b/src/main/java/me/chayapak1/chomens_bot/plugins/DiscordPlugin.java @@ -9,6 +9,7 @@ import me.chayapak1.chomens_bot.discord.GuildMessageEventHandler; import me.chayapak1.chomens_bot.discord.MessageLogger; import me.chayapak1.chomens_bot.util.CodeBlockUtilities; import me.chayapak1.chomens_bot.util.ComponentUtilities; +import me.chayapak1.chomens_bot.util.I18nUtilities; import me.chayapak1.chomens_bot.util.LoggerUtilities; import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.JDABuilder; @@ -108,15 +109,15 @@ public class DiscordPlugin { public void onConnecting () { if (bot.connectAttempts > 6) return; else if (bot.connectAttempts == 6) { - sendMessageInstantly("Suppressing connection status messages from now on", channelId); + sendMessageInstantly(I18nUtilities.get("info.suppressing"), channelId); return; } sendMessageInstantly( String.format( - "Connecting to: `%s`", - bot.getServerString() + I18nUtilities.get("info.connecting"), + "`" + bot.getServerString().replace("`", "\\`") + "`" ), channelId ); @@ -126,8 +127,8 @@ public class DiscordPlugin { public void connected (final ConnectedEvent event) { sendMessageInstantly( String.format( - "Successfully connected to: `%s`", - bot.getServerString() + I18nUtilities.get("info.connected"), + "`" + bot.getServerString().replace("`", "\\`") + "`" ), channelId ); @@ -139,10 +140,13 @@ public class DiscordPlugin { final String reason = ComponentUtilities.stringifyDiscordAnsi(event.getReason()); sendMessageInstantly( - "Disconnected: \n" + - "```ansi\n" + - reason.replace("`", "\\`") + - "\n```", + String.format( + I18nUtilities.get("info.disconnected"), + "\n" + + "```ansi\n" + + CodeBlockUtilities.escape(reason) + + "\n```" + ), channelId ); } diff --git a/src/main/java/me/chayapak1/chomens_bot/plugins/GrepLogPlugin.java b/src/main/java/me/chayapak1/chomens_bot/plugins/GrepLogPlugin.java index 625d260f..47f5ecb1 100644 --- a/src/main/java/me/chayapak1/chomens_bot/plugins/GrepLogPlugin.java +++ b/src/main/java/me/chayapak1/chomens_bot/plugins/GrepLogPlugin.java @@ -10,7 +10,6 @@ import net.dv8tion.jda.api.entities.channel.concrete.TextChannel; import net.dv8tion.jda.api.utils.FileUpload; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.event.ClickEvent; -import net.kyori.adventure.text.event.HoverEvent; import net.kyori.adventure.text.format.NamedTextColor; import java.io.*; @@ -86,7 +85,7 @@ public class GrepLogPlugin { final long matches = stringifiedResult.lines().count(); - if (matches == 0) throw new CommandException(Component.text("No matches has been found")); + if (matches == 0) throw new CommandException(Component.translatable("commands.greplog.error.no_matches_found")); final String channelId = Main.discord.servers.get(bot.getServerString(true)); final TextChannel logChannel = Main.discord.jda.getTextChannelById(channelId); @@ -107,24 +106,15 @@ public class GrepLogPlugin { final DecimalFormat formatter = new DecimalFormat("#,###"); - final Component component = Component.translatable("Found %s matches for %s. You can see the results by clicking %s or in the Discord server.") + final Component component = Component.translatable("commands.greplog.found") .color(bot.colorPalette.defaultColor) .arguments( Component.text(formatter.format(matches)).color(bot.colorPalette.number), Component.text(input).color(bot.colorPalette.string), Component - .text("here") + .translatable("commands.greplog.here") .color(NamedTextColor.GREEN) - .hoverEvent( - HoverEvent.showText( - Component - .text("Click! :D") - .color(bot.colorPalette.secondary) - ) - ) - .clickEvent( - ClickEvent.openUrl(url) - ) + .clickEvent(ClickEvent.openUrl(url)) ); context.sendOutput(component); diff --git a/src/main/java/me/chayapak1/chomens_bot/plugins/IRCPlugin.java b/src/main/java/me/chayapak1/chomens_bot/plugins/IRCPlugin.java index b21cea2e..4eac008f 100644 --- a/src/main/java/me/chayapak1/chomens_bot/plugins/IRCPlugin.java +++ b/src/main/java/me/chayapak1/chomens_bot/plugins/IRCPlugin.java @@ -6,6 +6,7 @@ import me.chayapak1.chomens_bot.Main; import me.chayapak1.chomens_bot.command.contexts.IRCCommandContext; import me.chayapak1.chomens_bot.data.listener.Listener; import me.chayapak1.chomens_bot.util.ColorUtilities; +import me.chayapak1.chomens_bot.util.I18nUtilities; import me.chayapak1.chomens_bot.util.LoggerUtilities; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.event.HoverEvent; @@ -173,7 +174,7 @@ public class IRCPlugin extends ListenerAdapter { sendMessage( bot, String.format( - "Successfully connected to: %s", + I18nUtilities.get("info.connected"), bot.getServerString() ) ); diff --git a/src/main/java/me/chayapak1/chomens_bot/plugins/LoggerPlugin.java b/src/main/java/me/chayapak1/chomens_bot/plugins/LoggerPlugin.java index 198b6e0d..2011d672 100644 --- a/src/main/java/me/chayapak1/chomens_bot/plugins/LoggerPlugin.java +++ b/src/main/java/me/chayapak1/chomens_bot/plugins/LoggerPlugin.java @@ -4,6 +4,7 @@ import me.chayapak1.chomens_bot.Bot; import me.chayapak1.chomens_bot.data.listener.Listener; import me.chayapak1.chomens_bot.data.logging.LogType; import me.chayapak1.chomens_bot.util.ExceptionUtilities; +import me.chayapak1.chomens_bot.util.I18nUtilities; import me.chayapak1.chomens_bot.util.LoggerUtilities; import net.kyori.adventure.text.Component; import org.geysermc.mcprotocollib.network.event.session.ConnectedEvent; @@ -44,14 +45,14 @@ public class LoggerPlugin implements Listener { public void onConnecting () { if (bot.connectAttempts > 10) return; else if (bot.connectAttempts == 10) { - log("Suppressing connection status messages from now on"); + log(I18nUtilities.get("info.suppressing")); return; } log( String.format( - "Connecting to: %s", + I18nUtilities.get("info.connecting"), bot.getServerString(true) ) ); @@ -61,7 +62,7 @@ public class LoggerPlugin implements Listener { public void connected (final ConnectedEvent event) { log( String.format( - "Successfully connected to: %s", + I18nUtilities.get("info.connected"), bot.getServerString(true) ) ); @@ -72,8 +73,7 @@ public class LoggerPlugin implements Listener { if (bot.connectAttempts >= 10) return; final Component message = Component.translatable( - "Disconnected from %s, reason: %s", - Component.text(bot.getServerString(true)), + I18nUtilities.get("info.disconnected"), event.getReason() ); diff --git a/src/main/java/me/chayapak1/chomens_bot/plugins/MusicPlayerPlugin.java b/src/main/java/me/chayapak1/chomens_bot/plugins/MusicPlayerPlugin.java index e05d8cb2..c5fa4153 100644 --- a/src/main/java/me/chayapak1/chomens_bot/plugins/MusicPlayerPlugin.java +++ b/src/main/java/me/chayapak1/chomens_bot/plugins/MusicPlayerPlugin.java @@ -101,7 +101,9 @@ public class MusicPlayerPlugin implements Listener { public void loadSong (final URL location, final PlayerEntry sender) { if (urlLimit >= bot.config.music.urlRatelimit.limit) { - bot.chat.tellraw(Component.text("URL loading is being rate limited!").color(NamedTextColor.RED)); + bot.chat.tellraw(bot.commandHandler.renderTranslatable( + Component.translatable("commands.music.error.url_ratelimited", NamedTextColor.RED) + )); return; } @@ -118,13 +120,13 @@ public class MusicPlayerPlugin implements Listener { this.loaderThread = loaderThread; - bot.chat.tellraw( + bot.chat.tellraw(bot.commandHandler.renderTranslatable( Component .translatable( - "Loading %s", + "commands.music.loading", Component.text(songName, bot.colorPalette.secondary) ) - .color(bot.colorPalette.defaultColor), + .color(bot.colorPalette.defaultColor)), BOTH_SELECTOR ); @@ -148,11 +150,12 @@ public class MusicPlayerPlugin implements Listener { addBossBar(); currentSong = songQueue.getFirst(); // songQueue.poll(); - bot.chat.tellraw( + bot.chat.tellraw(bot.commandHandler.renderTranslatable( Component.translatable( - "Now playing %s", + "commands.music.nowplaying", + bot.colorPalette.defaultColor, Component.empty().append(Component.text(currentSong.name)).color(bot.colorPalette.secondary) - ).color(bot.colorPalette.defaultColor), + )), BOTH_SELECTOR ); currentSong.play(); @@ -183,11 +186,12 @@ public class MusicPlayerPlugin implements Listener { return; } - bot.chat.tellraw( + bot.chat.tellraw(bot.commandHandler.renderTranslatable( Component.translatable( - "Finished playing %s", + "commands.music.finished", + bot.colorPalette.defaultColor, Component.empty().append(Component.text(currentSong.name)).color(bot.colorPalette.secondary) - ).color(bot.colorPalette.defaultColor), + )), BOTH_SELECTOR ); @@ -293,7 +297,7 @@ public class MusicPlayerPlugin implements Listener { public void removeBossBar () { final BotBossBar bossBar = bot.bossbar.get(BOSS_BAR_NAME); - if (bossBar != null) bossBar.setTitle(Component.text("No song is currently playing")); + if (bossBar != null) bossBar.setTitle(Component.translatable("commands.music.error.not_playing")); bot.bossbar.remove(BOSS_BAR_NAME); } diff --git a/src/main/java/me/chayapak1/chomens_bot/plugins/TrustedPlugin.java b/src/main/java/me/chayapak1/chomens_bot/plugins/TrustedPlugin.java index 9e523821..dd188027 100644 --- a/src/main/java/me/chayapak1/chomens_bot/plugins/TrustedPlugin.java +++ b/src/main/java/me/chayapak1/chomens_bot/plugins/TrustedPlugin.java @@ -4,6 +4,7 @@ import me.chayapak1.chomens_bot.Bot; import me.chayapak1.chomens_bot.data.listener.Listener; import me.chayapak1.chomens_bot.data.logging.LogType; import me.chayapak1.chomens_bot.data.player.PlayerEntry; +import me.chayapak1.chomens_bot.util.I18nUtilities; import me.chayapak1.chomens_bot.util.LoggerUtilities; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; @@ -87,9 +88,10 @@ public class TrustedPlugin implements Listener { broadcast( Component.translatable( - "Trusted player %s is now online", - Component.text(target.profile.getName()).color(bot.colorPalette.username) - ).color(bot.colorPalette.defaultColor), + I18nUtilities.get("trusted_broadcast.online"), + bot.colorPalette.defaultColor, + Component.text(target.profile.getName(), bot.colorPalette.username) + ), target.profile.getId() ); } @@ -100,9 +102,10 @@ public class TrustedPlugin implements Listener { broadcast( Component.translatable( - "Trusted player %s is now offline", - Component.text(target.profile.getName()).color(bot.colorPalette.username) - ).color(bot.colorPalette.defaultColor) + I18nUtilities.get("trusted_broadcast.offline"), + bot.colorPalette.defaultColor, + Component.text(target.profile.getName(), bot.colorPalette.username) + ) ); } } diff --git a/src/main/java/me/chayapak1/chomens_bot/plugins/VoiceChatPlugin.java b/src/main/java/me/chayapak1/chomens_bot/plugins/VoiceChatPlugin.java index 9d3d61b0..3e1fbf50 100644 --- a/src/main/java/me/chayapak1/chomens_bot/plugins/VoiceChatPlugin.java +++ b/src/main/java/me/chayapak1/chomens_bot/plugins/VoiceChatPlugin.java @@ -7,6 +7,7 @@ import me.chayapak1.chomens_bot.data.logging.LogType; import me.chayapak1.chomens_bot.data.voiceChat.ClientGroup; import me.chayapak1.chomens_bot.data.voiceChat.RawUdpPacket; import me.chayapak1.chomens_bot.util.FriendlyByteBuf; +import me.chayapak1.chomens_bot.util.I18nUtilities; import me.chayapak1.chomens_bot.voiceChat.InitializationData; import me.chayapak1.chomens_bot.voiceChat.NetworkMessage; import me.chayapak1.chomens_bot.voiceChat.customPayload.JoinGroupPacket; @@ -91,7 +92,7 @@ public class VoiceChatPlugin implements Listener, Runnable { try { socket.open(); } catch (final Exception e) { - bot.logger.error("Failed to create Simple Voice Chat connection!"); + bot.logger.error(I18nUtilities.get("voicechat.failed_connecting")); bot.logger.error(e); return; } @@ -135,7 +136,7 @@ public class VoiceChatPlugin implements Listener, Runnable { bot.logger.log( LogType.SIMPLE_VOICE_CHAT, Component.translatable( - "Successfully connected to Simple Voice Chat address: %s", + I18nUtilities.get("voicechat.connected"), Component.text(socketAddress.toString()) ) ); diff --git a/src/main/java/me/chayapak1/chomens_bot/util/ComponentUtilities.java b/src/main/java/me/chayapak1/chomens_bot/util/ComponentUtilities.java index 3debfb37..b223426b 100644 --- a/src/main/java/me/chayapak1/chomens_bot/util/ComponentUtilities.java +++ b/src/main/java/me/chayapak1/chomens_bot/util/ComponentUtilities.java @@ -23,7 +23,7 @@ public class ComponentUtilities { // rewritten from chipmunkbot, a lot of stuff has changed, and also ANSI and section signs support, etc... public static final Map LANGUAGE = new Object2ObjectOpenHashMap<>(); - private static final List LANGUAGES = List.of("language.json", "voiceChatLanguage.json"); + private static final List LANGUAGES = List.of("minecraftLanguage.json", "voiceChatLanguage.json"); public static final Map KEYBINDINGS = loadJsonStringMap("keybinds.json"); diff --git a/src/main/java/me/chayapak1/chomens_bot/util/I18nUtilities.java b/src/main/java/me/chayapak1/chomens_bot/util/I18nUtilities.java new file mode 100644 index 00000000..6858fc87 --- /dev/null +++ b/src/main/java/me/chayapak1/chomens_bot/util/I18nUtilities.java @@ -0,0 +1,67 @@ +package me.chayapak1.chomens_bot.util; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Collections; +import java.util.Map; + +public class I18nUtilities { + private static final Path USER_LANGUAGE_PATH = Path.of("language.json"); + + private static final Map LANGUAGE; + + static { + if (Files.exists(USER_LANGUAGE_PATH)) { + try { + LANGUAGE = loadLanguageFromFile(); + } catch (final IOException e) { + throw new RuntimeException(e); + } + } else { + LANGUAGE = loadLanguage(); + } + } + + private static Map loadLanguage () { + final Map map = new Object2ObjectOpenHashMap<>(); + + final InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("language-en_us.json"); + assert is != null; + final BufferedReader reader = new BufferedReader(new InputStreamReader(is)); + final JsonObject json = JsonParser.parseReader(reader).getAsJsonObject(); + + for (final Map.Entry entry : json.entrySet()) { + map.put(entry.getKey(), json.get(entry.getKey()).getAsString()); + } + + return Collections.unmodifiableMap(map); + } + + private static Map loadLanguageFromFile () throws IOException { + final Map map = new Object2ObjectOpenHashMap<>(); + + final InputStream output = Files.newInputStream(USER_LANGUAGE_PATH); + final BufferedReader reader = new BufferedReader(new InputStreamReader(output)); + + final JsonObject json = JsonParser.parseReader(reader).getAsJsonObject(); + + for (final Map.Entry entry : json.entrySet()) { + map.put(entry.getKey(), json.get(entry.getKey()).getAsString()); + } + + return Collections.unmodifiableMap(map); + } + + public static String get (final String key) { + return LANGUAGE.get(key); + } +} diff --git a/src/main/resources/language-en_us.json b/src/main/resources/language-en_us.json new file mode 100644 index 00000000..a7b85812 --- /dev/null +++ b/src/main/resources/language-en_us.json @@ -0,0 +1,308 @@ +{ + "auth.logger_verified": "Player has been verified", + "auth.player_verified": "You have been verified", + "auth.timed_out": "Authentication timed out", + + "arguments_parsing.hover.usages": "click for usages", + "arguments_parsing.error.expected_string": "Expected %s at position %s (%s %s)%s", + "arguments_parsing.error.unterminated_quote": "Unterminated quote at %s <-- %s", + "arguments_parsing.error.unterminated_escape": "Unterminated escape at %s <--", + "arguments_parsing.error.invalid_type": "Invalid %s", + "arguments_parsing.error.invalid_enum": "Invalid %s. Possible values are: %s", + "arguments_parsing.error.too_many_arguments": "Too many arguments, expected %s max", + + "chomens_mod.replay_attack": "Ignoring suspected replay attack payload with metadata: %s", + + "command_handler.console_only": "This command can only be run via console", + "command_handler.disabled": "ChomeNS Bot is currently disabled", + "command_handler.exception": "An error occurred while trying to execute the command, hover here for stacktrace", + "command_handler.invalid_hash": "Invalid %s hash", + "command_handler.no_hash_provided": "Please provide a hash", + "command_handler.not_enough_roles": "Your don't have enough permission to execute this command!", + "command_handler.not_enough_roles.trust_level": "Your current roles don't allow you to execute %s commands!", + "command_handler.unknown_command": "Unknown command: %s", + + "commands.generic.click_to_copy_message": "Click to copy the message to your clipboard", + "commands.generic.click_to_copy_username": "Click to copy the username to your clipboard", + "commands.generic.click_to_copy_uuid": "Click to copy the UUID to your clipboard", + "commands.generic.shift_click_to_insert_uuid": "Shift+Click to insert the UUID into your chat box", + "commands.generic.enabled": "enabled", + "commands.generic.disabled": "disabled", + "commands.generic.error.invalid_action": "Invalid action", + "commands.generic.error.invalid_player": "Invalid player name/UUID", + "commands.generic.error.invalid_index": "Invalid index", + "commands.generic.error.database_disabled": "Database is not enabled in the bot's configuration", + "commands.generic.error.discord_disabled": "The bot's Discord integration has to be enabled to use this command", + + "commands.botvisibility.description": "Changes the bot's visibility", + "commands.botvisibility.message": "The bot's visibility is now %s", + "commands.botvisibility.visible": "visible", + "commands.botvisibility.invisible": "invisible", + + "commands.bruhify.description": "RecycleBots bruhify but actionbar", + + "commands.clearchat.description": "Clears the chat for everyone or for the specified player", + "commands.clearchat.specific": "Your chat has been cleared by %s", + "commands.clearchat.everyone": "The chat has been cleared", + + "commands.clearchatqueue.description": "Clears the bot's chat queue", + "commands.clearchatqueue.output": "Cleared the bot's chat queue", + + "commands.cloop.description": "Loops commands", + "commands.cloop.add.error.too_low_nanoseconds": "Interval must not be less than 1000 nanoseconds", + "commands.cloop.add.output": "Added %s with interval %s %s to the command loops", + "commands.cloop.remove.output": "Removed command loop %s", + "commands.cloop.clear.output": "Cleared all cloops", + "commands.cloop.list.cloops_text": "Cloops ", + + "commands.cb.description": "Executes a command in the command core and return its output", + "commands.cb.info.output": "Size: %s\nLayers: %s\nFrom: %s\nTo: %s\nBlock: %s\nDimension: %s\n%s", + "commands.cb.info.size": "%s blocks", + "commands.cb.info.click_to_teleport": "Click here to teleport to the command core", + + "commands.console.description": "Controls stuff about console", + "commands.console.server.set": "Set the console server to %s", + "commands.console.server.all_servers": "all servers", + "commands.console.server.error.invalid_server": "Invalid server: %s", + "commands.console.logtoconsole.set": "Logging to console is now %s", + "commands.console.printdisconnectedreason.set": "Printing the disconnected cause is now %s", + + "commands.cowsay.description": "Moo", + + "commands.echo.description": "Makes the bot say a message", + + "commands.end.description": "Reconnects the bot", + "commands.end.disconnect_reason": "End command", + + "commands.eval.description": "Evaluate JavaScript codes on a Node.JS container running @n8n/vm2", + "commands.eval.reset": "Reset the eval worker", + "commands.eval.error.offline": "Eval server is not online", + + "commands.filter.description": "Filter players", + "commands.filter.add.no_reason": "Added %s to the filters", + "commands.filter.add.reason": "Added %s to the filters with reason %s", + "commands.filter.add.error.already_exists": "The player %s is already in the filters", + "commands.filter.add.error.invalid_regex": "Failed to parse filter regex: %s", + "commands.filter.remove.output": "Removed %s from the filters", + "commands.filter.clear.output": "Cleared the filter list", + "commands.filter.list.ignore_case": "ignore case", + "commands.filter.list.regex": "regex", + "commands.filter.list.reason": "reason: %s", + "commands.filter.list.filtered_players_text": "Filtered players ", + + "commands.findalts.description": "Finds players with the same IP address", + "commands.findalts.output": "Possible alts for the %s %s:", + "commands.findalts.ip": "IP", + "commands.findalts.player": "player", + + "commands.greplog.description": "Queries the bot's logs", + "commands.greplog.stopped": "Stopped querying the logs", + "commands.greplog.started": "Started querying the logs for %s", + "commands.greplog.found": "Found %s matches for %s. You can see the results by clicking %s or in the Discord server", + "commands.greplog.here": "here", + "commands.greplog.error.not_running": "There is no query process running", + "commands.greplog.error.already_running": "Another query is already running", + "commands.greplog.error.no_matches_found": "No matches has been found", + + "commands.help.description": "Shows a command list or usage for a command", + "commands.help.commands_text": "Commands ", + "commands.help.trust_level": "Trust level: ", + "commands.help.error.unknown_command": "Unknown command", + + "commands.info.description": "Shows an info about various things", + "commands.info.creator.output": "%s is created by %s", + "commands.info.discord.output": "The Discord invite is: %s", + "commands.info.server.output": "Hostname: %s\nWorking directory: %s\nOS architecture: %s\nOS version: %s\nOS name: %s\nCPU cores: %s\nCPU model: %s\nThreads: %s\nHeap memory usage: %s\nJVM memory usage: %s", + "commands.info.botuser.output": "The bot's username is: %s and the UUID is: %s", + "commands.info.botlogintime.output": "The bots login time is %s and has been on the server for %s", + "commands.info.uptime.output": "The bot's uptime is: %s", + "commands.info.default.main_output": "%s is an open-source utility bot and a moderation bot made for the %s Minecraft server (and its clones) but also works on vanilla Minecraft servers. It was originally made for fun but I got addicted and made it a full blown bot.", + "commands.info.default.original_repository": "Original repository: %s", + "commands.info.default.compiled_at": "Compiled at: %s", + "commands.info.default.git_commit": ", Git commit: %s (%s)", + "commands.info.default.build": "Build %s", + + "commands.ipfilter.description": "Filters IPs", + "commands.ipfilter.add.no_reason": "Added %s to the filters", + "commands.ipfilter.add.reason": "Added %s to the filters with reason %s", + "commands.ipfilter.add.error.already_exists": "The IP %s is already in the filters", + "commands.ipfilter.remove.output": "Removed %s from the filters", + "commands.ipfilter.clear.output": "Cleared the filter list", + "commands.ipfilter.list.reason": "reason: %s", + "commands.ipfilter.list.filtered_ips_text": "Filtered IPs ", + + "commands.kick.description": "Kicks a player", + "commands.kick.output": "Kicking player %s with method %s", + + "commands.list.description": "Lists all players in the server (including vanished)", + "commands.list.no_other_usernames": "No other usernames associated", + "commands.list.with_usernames": "Usernames: %s", + "commands.list.vanished": "Vanished: %s", + "commands.list.latency": "Latency: %s", + "commands.list.game_mode": "Game Mode: %s", + "commands.list.ip_address": "IP address: %s", + "commands.list.players_text": "Players ", + + "commands.mail.description": "Sends a mail", + "commands.mail.sent": "Mail sent!", + "commands.mail.sendselecteditem.error.no_item_nbt": "Player has no `message` NBT tag in their selected item's minecraft:custom_data", + "commands.mail.read.no_new_mails": "You have no new mails", + "commands.mail.read.mail_contents": " %s %s Sent by: %s %s\nContents:\n%s", + "commands.mail.read.hover_more_info": "[Hover here for more info]", + "commands.mail.read.hover_info": "Time sent: %s\nServer: %s", + "commands.mail.read.mails_text": "Mails ", + + "commands.music.description": "Plays music", + "commands.music.error.locked": "Managing music is currently locked", + "commands.music.error.no_directory": "Directory does not exist", + "commands.music.error.song_not_found": "Song not found", + "commands.music.error.invalid_url": "Invalid URL", + "commands.music.error.not_playing": "No song is currently playing", + "commands.music.error.url_ratelimited": "URL loading is being rate limited!", + "commands.music.loading": "Loading %s", + "commands.music.finished": "Finished playing %s", + "commands.music.play.error.already_loading": "Already loading a song", + "commands.music.playitem.error.no_item_nbt": "Player has no `SongItemData.SongData` NBT tag in their selected item's minecraft:custom_data", + "commands.music.playitem.error.invalid_data": "Invalid Base64 or Ascii85 in the selected item", + "commands.music.stop": "Cleared the song queue", + "commands.music.loop.off": "Looping is now %s", + "commands.music.loop.off.disabled": "disabled", + "commands.music.loop.current.with_song": "Now looping %s", + "commands.music.loop.current.without_song": "Will now loop the next song", + "commands.music.loop.all": "Now looping every song", + "commands.music.skip": "Skipping %s", + "commands.music.nowplaying": "Now playing %s", + "commands.music.queue": "Queue: %s", + "commands.music.goto": "Set the time to %s", + "commands.music.goto.error.invalid_timestamp": "Invalid timestamp", + "commands.music.pitch": "Set the pitch to %s", + "commands.music.speed": "Set the speed to %s", + "commands.music.speed.error.too_fast": "Too fast!", + "commands.music.speed.error.negative": "Invalid speed", + "commands.music.volume": "Set the volume addition to %s", + "commands.music.amplify": "Set the amplification to %s", + "commands.music.amplify.error.too_big_value": "Too big value", + "commands.music.amplify.error.negative": "Invalid amplification value", + "commands.music.noteinstrument.off": "Every notes are now using its instrument", + "commands.music.noteinstrument.set": "Set the instrument for every note to %s", + "commands.music.paused": "Paused the current song", + "commands.music.resumed": "Resumed the current song", + "commands.music.info.title": "Title/Filename: %s", + "commands.music.info.requester": "Requested by: %s", + "commands.music.info.author": "Author: %s", + "commands.music.info.original_author": "Original author: %s", + "commands.music.info.tracks": "Tracks: %s", + "commands.music.info.notes": "Notes: %s", + "commands.music.info.description": "Description: %s", + "commands.music.testsong.title": "Test Song", + "commands.music.testsong.description": "SongPlayer's test song ported to ChomeNS Bot", + "commands.music.testsong.output": "Test song has been added to the song queue", + + "commands.netcmd.description": "Runs a command on the specified server(s) and return its output", + "commands.netcmd.error.no_servers_found": "No servers have been found with your input", + + "commands.netmsg.description": "Broadcasts a message to all of the servers that the bot is connected", + "commands.netmsg.hover.copy_server_to_clipboard": "Click here to copy the server host and port to your clipboard", + + "commands.rtp.description": "Randomly teleports you", + "commands.rtp.output": "Teleporting %s to %s %s %s", + + "commands.refillcore.description": "Refills and resets the bots command core", + "commands.refillcore.output": "Refilled the command core", + + "commands.restart.description": "Gracefully restarts the bot", + "commands.restart.output": "Restarting", + + "commands.screenshare.description": "Shares my screen", + + "commands.seen.description": "Shows the last seen of a player", + "commands.seen.output": "%s was last seen at %s on %s", + "commands.seen.error.currently_online": "%s is currently online on %s", + "commands.seen.error.never_seen": "%s was never seen", + "commands.seen.error.no_last_seen_entry": "This player doesn't seem to have the last seen entry in the database for some reason.", + "commands.seen.error.no_time_entry": "This player doesn't seem to have the `lastSeen.time` entry in the database for some reason.", + + "commands.servereval.description": "Evaluate codes using LuaJ", + "commands.servereval.reset": "Reset the Lua instance", + + "commands.stop.description": "Gracefully stops the bot", + "commands.stop.output": "Stopping", + + "commands.test.description": "Tests if the bot is working", + "commands.test.output": "Hello, World! Username: %s, Sender UUID: %s, Prefix: %s, Args: %s", + + "commands.time.description": "Shows the date and time for the specified timezone", + "commands.time.output": "The current time for %s is: %s", + "commands.time.error.invalid_timezone": "Invalid timezone (case-sensitive)", + + "commands.tpsbar.description": "Shows the server's TPS using Minecraft BossBar Technology", + "commands.tpsbar.output": "TPSBar is now %s", + + "commands.translate.description": "Translates a message using Google Translate", + "commands.translate.result": "Result: %s", + + "commands.urban.description": "Urban Dictionary in Minecraft", + "commands.urban.discord_warning": "*Showing only 3 results because Discord*", + "commands.urban.hover.info": "Written by %s\nThumbs up: %s\nThumbs down: %s\nExample: %s", + "commands.urban.hover.copy": "Click here to copy the word and the definition to your clipboard", + "commands.urban.hover.run": "Click here to run %s", + "commands.urban.error.too_many_requests": "Too many requests", + "commands.urban.error.no_results": "No results found", + + "commands.uuid.description": "Shows your UUID or other player's UUID", + "commands.uuid.other": "%s's UUID: %s", + "commands.uuid.self": "Your UUID: %s", + + "commands.validate.description": "Validates/shows your trust level", + "commands.validate.discord": "You are trusted! (%s)", + "commands.validate.console": "You are the console! You have no trust level", + "commands.validate.player": "Valid hash (%s)", + + "commands.weather.description": "Shows the weather information in a place", + "commands.weather.info": "Current weather for %s, %s:\n%s (%s), feels like %s (%s)\nCondition: %s\nCloud cover: %s\nHumidity: %s\nTime: %s", + "commands.weather.error.not_found": "Weather information for \"%s\" not found", + + "commands.whitelist.description": "Manages whitelist", + "commands.whitelist.enable": "Enabled whitelist", + "commands.whitelist.disable": "Disabled whitelist", + "commands.whitelist.add": "Added %s to the whitelist", + "commands.whitelist.remove": "Removed %s from the whitelist", + "commands.whitelist.clear": "Cleared the whitelist", + "commands.whitelist.whitelisted_players_text": "Whitelisted players ", + + "commands.wikipedia.description": "Wikipedia in Minecraft", + "commands.wikipedia.error.not_found": "Cannot find page: %s", + "commands.wikipedia.error.no_contents": "No contents found", + "commands.wikipedia.error.fail_page_id_parse": "Failed parsing page ID", + + "info.connecting": "Connecting to: %s", + "info.connected": "Successfully connected to: %s", + "info.disconnected": "Disconnected: %s", + "info.suppressing": "Suppressing connection status messages from now on", + "info.stopping.generic": "%s (%s)", + "info.stopping": "Stopping..", + "info.restarting": "Restarting..", + "info.no_reason": "No reason given", + + "initialized": "Initialized all bots. Now connecting", + + "log_type.info": "Info", + "log_type.chat": "Chat", + "log_type.trusted_broadcast": "Trusted Broadcast", + "log_type.error": "Error", + "log_type.command_output": "Command Output", + "log_type.auth": "Auth", + "log_type.simple_voice_chat": "Simple Voice Chat", + "log_type.discord": "Discord", + + "trusted_broadcast.online": "Trusted player %s is now online", + "trusted_broadcast.offline": "Trusted player %s is now offline", + + "trust_level.public": "Public", + "trust_level.trusted": "Trusted", + "trust_level.admin": "Admin", + "trust_level.owner": "Owner", + + "voicechat.connected": "Successfully connected to Simple Voice Chat address: %s", + "voicechat.failed_connecting": "Failed to create Simple Voice Chat connection!" +} \ No newline at end of file diff --git a/src/main/resources/language.json b/src/main/resources/minecraftLanguage.json similarity index 100% rename from src/main/resources/language.json rename to src/main/resources/minecraftLanguage.json