diff --git a/src/main/java/nl/pim16aap2/armoredElytra/ArmoredElytra.java b/src/main/java/nl/pim16aap2/armoredElytra/ArmoredElytra.java index ca2f888..c640436 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/ArmoredElytra.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/ArmoredElytra.java @@ -9,8 +9,9 @@ import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor; import nl.pim16aap2.armoredElytra.util.ArmorTier; import nl.pim16aap2.armoredElytra.util.ArmorTierName; import nl.pim16aap2.armoredElytra.util.ConfigLoader; -import nl.pim16aap2.armoredElytra.util.Messages; import nl.pim16aap2.armoredElytra.util.UpdateManager; +import nl.pim16aap2.armoredElytra.util.messages.Message; +import nl.pim16aap2.armoredElytra.util.messages.Messages; import org.bstats.bukkit.Metrics; import org.bukkit.Bukkit; import org.bukkit.ChatColor; @@ -21,9 +22,7 @@ import org.bukkit.plugin.java.JavaPlugin; import java.util.EnumMap; import java.util.Map; -import java.util.Objects; import java.util.logging.Level; -import java.util.regex.Pattern; // TODO: Figure out if the config really does read the list of enchantments accurately. A bug report with a customized config seemed to load the default settings... // TODO: Verify enchantments on startup. Remove them from the list if they're invalid. @@ -37,9 +36,6 @@ public class ArmoredElytra extends JavaPlugin implements Listener private ConfigLoader config; private final Map armorTierNames = new EnumMap<>(ArmorTier.class); - private String elytraReceivedMessage; - private String usageDeniedMessage; - private String elytraLore; private boolean upToDate; private boolean is1_9; private UpdateManager updateManager; @@ -112,35 +108,19 @@ public class ArmoredElytra extends JavaPlugin implements Listener return messages; } - private final String getColorCodedStringFromConfig(final String configEntry) - { - return getMyMessages().getString(configEntry).replaceAll("&((?i)[0-9a-fk-or])", "\u00A7$1"); - } - private void readMessages() { - // Replace color codes by the corresponding colors. - usageDeniedMessage = getColorCodedStringFromConfig("MESSAGES.UsageDenied"); - elytraReceivedMessage = getColorCodedStringFromConfig("MESSAGES.ElytraReceived"); - elytraLore = getColorCodedStringFromConfig("MESSAGES.Lore"); - armorTierNames.put(ArmorTier.NONE, new ArmorTierName("NONE", "NONE")); // Shouldn't be used. - armorTierNames.put(ArmorTier.LEATHER, new ArmorTierName(getColorCodedStringFromConfig("TIER.Leather"), - getColorCodedStringFromConfig("TIER.SHORT.Leather"))); - armorTierNames.put(ArmorTier.GOLD, new ArmorTierName(getColorCodedStringFromConfig("TIER.Gold"), - getColorCodedStringFromConfig("TIER.SHORT.Gold"))); - armorTierNames.put(ArmorTier.CHAIN, new ArmorTierName(getColorCodedStringFromConfig("TIER.Chain"), - getColorCodedStringFromConfig("TIER.SHORT.Chain"))); - armorTierNames.put(ArmorTier.IRON, new ArmorTierName(getColorCodedStringFromConfig("TIER.Iron"), - getColorCodedStringFromConfig("TIER.SHORT.Iron"))); - armorTierNames.put(ArmorTier.DIAMOND, new ArmorTierName(getColorCodedStringFromConfig("TIER.Diamond"), - getColorCodedStringFromConfig("TIER.SHORT.Diamond"))); - - // Change the string to null if it says "NONE". - usageDeniedMessage = (Objects.equals(usageDeniedMessage, new String("NONE")) ? null : usageDeniedMessage); - elytraReceivedMessage = (Objects.equals(elytraReceivedMessage, new String("NONE")) ? null : - elytraReceivedMessage); - elytraLore = (Objects.equals(elytraLore, new String("NONE")) ? null : elytraLore); + armorTierNames.put(ArmorTier.LEATHER, new ArmorTierName(messages.getString(Message.TIER_LEATHER), + messages.getString(Message.TIER_SHORT_LEATHER))); + armorTierNames.put(ArmorTier.GOLD, new ArmorTierName(messages.getString(Message.TIER_GOLD), + messages.getString(Message.TIER_SHORT_GOLD))); + armorTierNames.put(ArmorTier.CHAIN, new ArmorTierName(messages.getString(Message.TIER_CHAIN), + messages.getString(Message.TIER_SHORT_CHAIN))); + armorTierNames.put(ArmorTier.IRON, new ArmorTierName(messages.getString(Message.TIER_IRON), + messages.getString(Message.TIER_SHORT_IRON))); + armorTierNames.put(ArmorTier.DIAMOND, new ArmorTierName(messages.getString(Message.TIER_DIAMOND), + messages.getString(Message.TIER_SHORT_DIAMOND))); } public boolean playerHasCraftPerm(Player player, ArmorTier armorTier) @@ -185,41 +165,41 @@ public class ArmoredElytra extends JavaPlugin implements Listener messagePlayer(player, ChatColor.WHITE, str); } + private String getMessageWithTierNames(final Message message, final ArmorTier armorTier) + { + ArmorTierName tierName = armorTierNames.get(armorTier); + return getMyMessages().getString(message, + tierName.getLongName(), + tierName.getShortName()); + } + // Send the usageDeniedMessage message to the player. public void usageDeniedMessage(Player player, ArmorTier armorTier) { - if (usageDeniedMessage != null) - { - final String message = fillInArmorTierInStringNoColor(usageDeniedMessage, armorTier); + final String message = getMessageWithTierNames(Message.MESSAGES_USAGEDENIED, armorTier); + if (!message.equals("NONE")) messagePlayer(player, ChatColor.RED, message); - } } // Send the elytraReceivedMessage message to the player. public void elytraReceivedMessage(Player player, ArmorTier armorTier) { - if (elytraReceivedMessage != null) - { - final String message = fillInArmorTierInStringNoColor(elytraReceivedMessage, armorTier); + final String message = getMessageWithTierNames(Message.MESSAGES_ELYTRARECEIVED, armorTier); + if (!message.equals("NONE")) messagePlayer(player, ChatColor.GREEN, message); - } } - private static final Pattern ARMOR_TIER = Pattern.compile("%ARMOR_TIER%"); - private static final Pattern ARMOR_TIER_SHORT = Pattern.compile("%ARMOR_TIER_SHORT%"); - - // Replace %ARMOR_TIER% by the name of that armor tier in a string, but strip %ARMOR_TIER% of its color. - public String fillInArmorTierInStringNoColor(String string, ArmorTier armorTier) + public void sendNoGivePermissionMessage(Player player, ArmorTier armorTier) { - if (armorTier == null) - { - getLogger().log(Level.INFO, "ArmorTier was null! Failed to obtain proper string!"); - return string; - } - final ArmorTierName tierName = armorTierNames.get(armorTier); - return ARMOR_TIER_SHORT - .matcher(ARMOR_TIER.matcher(string).replaceAll(ChatColor.stripColor(tierName.getLongName()))) - .replaceAll(ChatColor.stripColor(tierName.getShortName())); + final String message = getMessageWithTierNames(Message.MESSAGES_NOGIVEPERMISSION, armorTier); + messagePlayer(player, ChatColor.RED, message); + } + + public String getElytraLore(ArmorTier armorTier) + { + final String message = getMessageWithTierNames(Message.MESSAGES_LORE, armorTier); + Bukkit.broadcastMessage(message); + return message.equals("NONE") ? null : message; } // Print a string to the log. @@ -258,11 +238,6 @@ public class ArmoredElytra extends JavaPlugin implements Listener return instance; } - public String getElytraLore() - { - return elytraLore; - } - public String getArmoredElytraName(ArmorTier tier) { if (tier == null) diff --git a/src/main/java/nl/pim16aap2/armoredElytra/handlers/CommandHandler.java b/src/main/java/nl/pim16aap2/armoredElytra/handlers/CommandHandler.java index 6839111..f75f3d2 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/handlers/CommandHandler.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/handlers/CommandHandler.java @@ -3,6 +3,7 @@ package nl.pim16aap2.armoredElytra.handlers; import nl.pim16aap2.armoredElytra.ArmoredElytra; import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor; import nl.pim16aap2.armoredElytra.util.ArmorTier; +import nl.pim16aap2.armoredElytra.util.messages.Message; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Material; @@ -34,7 +35,7 @@ public class CommandHandler implements CommandExecutor if (plugin.getConfigLoader().uninstallMode()) { - plugin.messagePlayer(player, plugin.getMyMessages().getString("MESSAGES.UninstallMode")); + plugin.messagePlayer(player, plugin.getMyMessages().getString(Message.MESSAGES_UNINSTALLMODE)); return true; } @@ -67,7 +68,8 @@ public class CommandHandler implements CommandExecutor allowed = player.hasPermission("armoredelytra.give." + ArmorTier.getName(armorTier)); else { - plugin.messagePlayer(player, plugin.getMyMessages().getString("MESSAGES.UnsupportedTier")); + plugin.messagePlayer(player, plugin.getMyMessages() + .getString(Message.MESSAGES_UNSUPPORTEDTIER)); return false; } @@ -79,8 +81,7 @@ public class CommandHandler implements CommandExecutor plugin.giveArmoredElytraToPlayer(receiver, newElytra); } else - plugin.messagePlayer(player, plugin.fillInArmorTierInStringNoColor( - plugin.getMyMessages().getString("MESSAGES.NoGivePermission"), armorTier)); + plugin.sendNoGivePermissionMessage(player, armorTier); return true; } } @@ -94,7 +95,7 @@ public class CommandHandler implements CommandExecutor if (args.length == 2) { - ItemStack newElytra = null; + ItemStack newElytra; final String tier = args[1]; if (Bukkit.getPlayer(args[0]) != null) { diff --git a/src/main/java/nl/pim16aap2/armoredElytra/handlers/EventHandlers.java b/src/main/java/nl/pim16aap2/armoredElytra/handlers/EventHandlers.java index b1ebf54..cb56134 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/handlers/EventHandlers.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/handlers/EventHandlers.java @@ -11,6 +11,7 @@ import nl.pim16aap2.armoredElytra.util.AllowedToWearEnum; import nl.pim16aap2.armoredElytra.util.ArmorTier; import nl.pim16aap2.armoredElytra.util.Util; import nl.pim16aap2.armoredElytra.util.XMaterial; +import nl.pim16aap2.armoredElytra.util.messages.Message; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.enchantments.Enchantment; @@ -525,7 +526,7 @@ public class EventHandlers implements Listener case ALLOWED: break; case BROKEN: - plugin.messagePlayer(e.getPlayer(), plugin.getMyMessages().getString("MESSAGES.RepairNeeded")); + plugin.messagePlayer(e.getPlayer(), plugin.getMyMessages().getString(Message.MESSAGES_REPAIRNEEDED)); e.setCancelled(true); break; case NOPERMISSION: diff --git a/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/NBTEditor.java b/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/NBTEditor.java index b98bf00..dab6f46 100644 --- a/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/NBTEditor.java +++ b/src/main/java/nl/pim16aap2/armoredElytra/nbtEditor/NBTEditor.java @@ -3,6 +3,7 @@ package nl.pim16aap2.armoredElytra.nbtEditor; import nl.pim16aap2.armoredElytra.ArmoredElytra; import nl.pim16aap2.armoredElytra.util.ArmorTier; import org.bukkit.Bukkit; +import org.bukkit.ChatColor; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; @@ -145,10 +146,9 @@ public class NBTEditor int armorToughness = ArmorTier.getToughness(armorTier); itemmeta.setDisplayName(ArmoredElytra.getInstance().getArmoredElytraName(armorTier)); - if (ArmoredElytra.getInstance().getElytraLore() != null) - itemmeta - .setLore(Arrays.asList(ArmoredElytra.getInstance().fillInArmorTierInStringNoColor( - ArmoredElytra.getInstance().getElytraLore(), armorTier))); + final String message = ChatColor.stripColor(ArmoredElytra.getInstance().getElytraLore(armorTier)); + if (message != null) + itemmeta.setLore(Arrays.asList(message)); item.setItemMeta(itemmeta); diff --git a/src/main/java/nl/pim16aap2/armoredElytra/util/Messages.java b/src/main/java/nl/pim16aap2/armoredElytra/util/Messages.java deleted file mode 100644 index df4188f..0000000 --- a/src/main/java/nl/pim16aap2/armoredElytra/util/Messages.java +++ /dev/null @@ -1,97 +0,0 @@ -package nl.pim16aap2.armoredElytra.util; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.IOException; -import java.util.HashMap; -import java.util.Map; -import java.util.logging.Level; - -import nl.pim16aap2.armoredElytra.ArmoredElytra; - -public class Messages -{ - private Map messageMap = new HashMap<>(); - private ArmoredElytra plugin; - private File textFile; - - public Messages(ArmoredElytra plugin) - { - this.plugin = plugin; - textFile = new File(plugin.getDataFolder(), plugin.getConfigLoader().languageFile() + ".txt"); - if (!textFile.exists()) - { - plugin.myLogger(Level.WARNING, "Failed to load language file: \"" + textFile + "\": File not found! Using default file instead!"); - textFile = new File(plugin.getDataFolder(), "en_US.txt"); - } - readFile(); - } - - private void writeDefaultFile() - { - File defaultFile = new File(plugin.getDataFolder(), "en_US.txt"); - if (!defaultFile.setWritable(true)) - plugin.myLogger(Level.SEVERE, "Failed to make file \"" + defaultFile + "\" writable!"); - - // Load the default en_US from the resources. - plugin.saveResource("en_US.txt", true); - if (!defaultFile.setWritable(false)) - { - plugin.myLogger(Level.WARNING, "Could not set default language file to read-only!"); - plugin.myLogger(Level.WARNING, "This is not a big problem. Just remember not to edit the file!"); - } - } - - // Read locale file. - private void readFile() - { - writeDefaultFile(); - - try (BufferedReader br = new BufferedReader(new FileReader(textFile))) - { - String sCurrentLine; - - while ((sCurrentLine = br.readLine()) != null) - { - // Ignore comments. - if (sCurrentLine.startsWith("#") || sCurrentLine.isEmpty()) - continue; - String key, value; - String[] parts = sCurrentLine.split("=", 2); - key = parts[0]; - value = parts[1].replaceAll("&((?i)[0-9a-fk-or])", "\u00A7$1"); - String[] newLineSplitter = value.split("\\\\n"); - - String values = newLineSplitter[0]; - - for (int idx = 1; idx < newLineSplitter.length; ++idx) - values += "\n" + newLineSplitter[idx]; - - messageMap.put(key, values); - } - br.close(); - } - catch (FileNotFoundException e) - { - plugin.myLogger(Level.SEVERE, "Locale file \"" + textFile + "\" does not exist!"); - } - catch (IOException e) - { - plugin.myLogger(Level.SEVERE, "Could not read locale file: \"" + textFile + "\""); - e.printStackTrace(); - } - } - - // Get a string from a key. Returns "null" if null. - public String getString(String key) - { - String value = messageMap.get(key); - if (value != null) - return value; - - plugin.myLogger(Level.WARNING, "Failed to get the translation for key " + key); - return "Translation for key \"" + key + "\" not found! Contact server admin!"; - } -} diff --git a/src/main/java/nl/pim16aap2/armoredElytra/util/messages/IMessageVariable.java b/src/main/java/nl/pim16aap2/armoredElytra/util/messages/IMessageVariable.java new file mode 100644 index 0000000..126e6d9 --- /dev/null +++ b/src/main/java/nl/pim16aap2/armoredElytra/util/messages/IMessageVariable.java @@ -0,0 +1,12 @@ +package nl.pim16aap2.armoredElytra.util.messages; + +/** + * Represents supported variables in localizable messages. + * + * @author Pim + */ +public interface IMessageVariable +{ + String VAR_TIER_NAME = "%ARMOR_TIER%"; + String VAR_TIER_NAME_SHORT = "%ARMOR_TIER_SHORT%"; +} diff --git a/src/main/java/nl/pim16aap2/armoredElytra/util/messages/Message.java b/src/main/java/nl/pim16aap2/armoredElytra/util/messages/Message.java new file mode 100644 index 0000000..ea03158 --- /dev/null +++ b/src/main/java/nl/pim16aap2/armoredElytra/util/messages/Message.java @@ -0,0 +1,85 @@ +package nl.pim16aap2.armoredElytra.util.messages; + +/** + * Represents a localizable message. + * + * @author Pim + */ +public enum Message implements IMessageVariable +{ + EMPTY(), + + TIER_LEATHER(), + TIER_GOLD(), + TIER_CHAIN(), + TIER_IRON(), + TIER_DIAMOND(), + + TIER_SHORT_LEATHER(), + TIER_SHORT_GOLD(), + TIER_SHORT_CHAIN(), + TIER_SHORT_IRON(), + TIER_SHORT_DIAMOND(), + + MESSAGES_UNINSTALLMODE(), + MESSAGES_UNSUPPORTEDTIER(), + + MESSAGES_REPAIRNEEDED(), + MESSAGES_LORE(VAR_TIER_NAME, VAR_TIER_NAME_SHORT), + MESSAGES_NOGIVEPERMISSION(VAR_TIER_NAME, VAR_TIER_NAME_SHORT), + MESSAGES_USAGEDENIED(VAR_TIER_NAME, VAR_TIER_NAME_SHORT), + MESSAGES_ELYTRARECEIVED(VAR_TIER_NAME, VAR_TIER_NAME_SHORT), + + ; + + /** + * The list of names that can be used as variables in this message. + *

+ * For example: "This door will move %BLOCKSTOMOVE% blocks." Would contain at least "%BLOCKSTOMOVE%". + */ + private final String[] variableNames; + + /** + * Constructs a message. + * + * @param variableNames The names of the variables in the value that can be replaced. + */ + Message(final String... variableNames) + { + this.variableNames = variableNames; + } + + /** + * Gets the name of the variable at the given position for the given message. + * + * @param msg The message for which to retrieve the variable name. + * @param idx The index of the variable name. + * @return The name of the variable at the given position of this message. + */ + public static String getVariableName(final Message msg, final int idx) + { + return msg.variableNames[idx]; + } + + /** + * Gets the names of the variables for the given message.. + * + * @param msg The message for which to retrieve the variable names. + * @return The names of the variables of this message. + */ + public static String[] getVariableNames(final Message msg) + { + return msg.variableNames; + } + + /** + * Gets the number of variables in this message that can be substituted. + * + * @param msg The message to retrieve the variable count for. + * @return The number of variables in this message that can be substituted. + */ + public static int getVariableCount(final Message msg) + { + return msg.variableNames.length; + } +} diff --git a/src/main/java/nl/pim16aap2/armoredElytra/util/messages/Messages.java b/src/main/java/nl/pim16aap2/armoredElytra/util/messages/Messages.java new file mode 100644 index 0000000..16ee82c --- /dev/null +++ b/src/main/java/nl/pim16aap2/armoredElytra/util/messages/Messages.java @@ -0,0 +1,250 @@ +package nl.pim16aap2.armoredElytra.util.messages; + +import nl.pim16aap2.armoredElytra.ArmoredElytra; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.URL; +import java.net.URLConnection; +import java.nio.file.StandardCopyOption; +import java.util.EnumMap; +import java.util.Map; +import java.util.Objects; +import java.util.function.BiConsumer; +import java.util.logging.Level; +import java.util.regex.Pattern; + +public class Messages +{ + private static final String DEFAULTFILENAME = "en_US.txt"; + + /** + * The map of all messages. + *

+ * Key: The {@link Message} enum entry. + *

+ * Value: The translated message. + */ + private Map messageMap = new EnumMap<>(Message.class); + + private final ArmoredElytra plugin; + private File textFile; + + private static final Pattern matchDots = Pattern.compile("\\."); + private static final Pattern matchNewLines = Pattern.compile("\\\\n"); + private static final Pattern matchColorCodes = Pattern.compile("&((?i)[0-9a-fk-or])"); + + public Messages(final ArmoredElytra plugin) + { + this.plugin = plugin; + textFile = new File(plugin.getDataFolder(), plugin.getConfigLoader().languageFile() + ".txt"); + if (!textFile.exists()) + { + plugin.myLogger(Level.WARNING, "Failed to load language file: \"" + textFile + + "\": File not found! Using default file instead!"); + textFile = new File(plugin.getDataFolder(), DEFAULTFILENAME); + } + populateMessageMap(); + } + + private void writeDefaultFile() + { + File defaultFile = new File(plugin.getDataFolder(), DEFAULTFILENAME); + + InputStream in = null; + try + { + URL url = getClass().getClassLoader().getResource(DEFAULTFILENAME); + if (url == null) + plugin.myLogger(Level.SEVERE, "Failed to read resources file from the jar! " + + "The default translation file cannot be generated! Please contact pim16aap2"); + else + { + URLConnection connection = url.openConnection(); + connection.setUseCaches(false); + in = connection.getInputStream(); + java.nio.file.Files.copy(in, defaultFile.toPath(), StandardCopyOption.REPLACE_EXISTING); + } + } + catch (Exception e) + { + plugin.myLogger(Level.SEVERE, "Failed to write default file to \"" + textFile + "\"."); + e.printStackTrace(); + } + finally + { + try + { + if (in != null) + in.close(); + } + catch (IOException e) + { + e.printStackTrace(); + } + } + } + + /** + * Processes the contents of a file. Each valid line will be split up in the message key and the message value. It + * then + * + * @param br The {@link BufferedReader} that supplies the text. + * @param action The action to take for every message and value combination that is encountered. + * @throws IOException + */ + private void processFile(final BufferedReader br, final BiConsumer action) + throws IOException + { + String sCurrentLine; + + while ((sCurrentLine = br.readLine()) != null) + { + // Ignore comments. + if (sCurrentLine.startsWith("#") || sCurrentLine.isEmpty()) + continue; + + String[] parts = sCurrentLine.split("=", 2); + try + { + final Message msg = Message.valueOf(matchDots.matcher(parts[0]).replaceAll("_").toUpperCase()); + final String value = matchNewLines.matcher(matchColorCodes.matcher(parts[1]).replaceAll("\u00A7$1")) + .replaceAll("\n"); + action.accept(msg, value); + } + catch (IllegalArgumentException e) + { + plugin.myLogger(Level.WARNING, "Failed to identify Message corresponding to key: \"" + parts[0] + + "\". Its value will be ignored!"); + + System.out.println( + "Trying to find enum value of: " + matchDots.matcher(parts[0]).replaceAll("_").toUpperCase()); + } + } + } + + /** + * Adds a message to the {@link #messageMap}. + * + * @param message The {@link Message}. + * @param value The value of the message. + */ + private void addMessage(final Message message, final String value) + { + messageMap.put(message, value); + } + + /** + * Adds a message to the {@link #messageMap} if it isn't on the map already. + * + * @param message The {@link Message}. + * @param value The value of the message. + */ + private void addBackupMessage(final Message message, final String value) + { + if (messageMap.containsKey(message)) + return; + + plugin.myLogger(Level.WARNING, + "Could not find translation of key: \"" + message.name() + "\". Using default value instead!"); + addMessage(message, value); + } + + /** + * Reads the translations from the provided translations file. + *

+ * Missing translations will use their default value. + */ + private void populateMessageMap() + { + try (BufferedReader br = new BufferedReader(new FileReader(textFile))) + { + processFile(br, this::addMessage); + } + catch (FileNotFoundException e) + { + plugin.myLogger(Level.SEVERE, "Locale file \"" + textFile + "\" does not exist!"); + e.printStackTrace(); + } + catch (IOException e) + { + plugin.myLogger(Level.SEVERE, "Could not read locale file! \"" + textFile + "\""); + e.printStackTrace(); + } + + + try (BufferedReader br = new BufferedReader( + new InputStreamReader( + Objects.requireNonNull(getClass().getClassLoader().getResource(DEFAULTFILENAME)).openStream()))) + { + processFile(br, this::addBackupMessage); + } + catch (FileNotFoundException e) + { + plugin.myLogger(Level.SEVERE, "Failed to load internal locale file!"); + e.printStackTrace(); + } + catch (IOException e) + { + plugin.myLogger(Level.SEVERE, "Could not read internal locale file!"); + e.printStackTrace(); + } + + for (final Message msg : Message.values()) + if (!msg.equals(Message.EMPTY) && !messageMap.containsKey(msg)) + { + plugin.myLogger(Level.WARNING, "Could not find translation of key: " + msg.name()); + messageMap.put(msg, getFailureString(msg.name())); + } + } + + /** + * Gets the default String to return in case a value could not be found for a given String. + * + * @param key The key that could not be resolved. + * @return The default String to return in case a value could not be found for a given String. + */ + private String getFailureString(final String key) + { + return "Translation for key \"" + key + "\" not found! Contact server admin!"; + } + + /** + * Gets the translated message of the provided {@link Message} and substitutes its variables for the provided + * values. + * + * @param msg The {@link Message} to translate. + * @param values The values to substitute for the variables in the message. + * @return The translated message of the provided {@link Message} and substitutes its variables for the provided + * values. + */ + public String getString(final Message msg, final String... values) + { + if (msg.equals(Message.EMPTY)) + return ""; + + if (values.length != Message.getVariableCount(msg)) + { + plugin.myLogger(Level.SEVERE, + "Expected " + Message.getVariableCount(msg) + " variables for key " + msg.name() + + " but only got " + values.length + ". This is a bug. Please contact pim16aap2!"); + return getFailureString(msg.name()); + } + + String value = messageMap.get(msg); + if (value != null) + { + for (int idx = 0; idx != values.length; ++idx) + value = value.replaceAll(Message.getVariableName(msg, idx), values[idx]); + return value; + } + + plugin.myLogger(Level.WARNING, "Failed to get the translation for key " + msg.name()); + return getFailureString(msg.name()); + } +} diff --git a/src/main/resources/en_US.txt b/src/main/resources/en_US.txt index 1761d36..b8915e0 100644 --- a/src/main/resources/en_US.txt +++ b/src/main/resources/en_US.txt @@ -1,5 +1,4 @@ # This file contains all the (partial) sentences used in this plugin. -# If you want to modify anything, make sure to do so in a copy, as this file will be regenerated on startup! # You can change which file will be used in the config.yml. # The format is "key=value" (without quotation marks). You can modify the values, but not the keys. # Order doesn't matter and you can use comments if you so desire. @@ -25,4 +24,4 @@ MESSAGES.RepairNeeded=&cYou cannot equip this elytra! Please repair it in an anv MESSAGES.Lore=Elytra with %ARMOR_TIER_SHORT% level protection. MESSAGES.NoGivePermission=&cYou do not have the required permission node to give a(n) %ARMOR_TIER%s. MESSAGES.UsageDenied=You do not have the required permissions to wear a(n) %ARMOR_TIER%! -MESSAGES.ElytraReceived=&2A(n) %ARMOR_TIER% has been bestowed upon you! \ No newline at end of file +MESSAGES.ElytraReceived=&2A(n) %ARMOR_TIER% has been bestowed upon you!