Adds possibility for message customization and translation #5
This commit is contained in:
@ -0,0 +1,23 @@
|
||||
package net.knarcraft.blacksmith.formatting;
|
||||
|
||||
/**
|
||||
* An enum representing all item types used in messages
|
||||
*/
|
||||
public enum ItemType {
|
||||
|
||||
ENCHANTMENT,
|
||||
MATERIAL;
|
||||
|
||||
/**
|
||||
* Gets the name of this item type
|
||||
*
|
||||
* @return <p>The name of this item type</p>
|
||||
*/
|
||||
public String getItemTypeName() {
|
||||
return switch (this) {
|
||||
case MATERIAL -> Translator.getTranslatedMessage(TranslatableMessage.ITEM_TYPE_MATERIAL);
|
||||
case ENCHANTMENT -> Translator.getTranslatedMessage(TranslatableMessage.ITEM_TYPE_ENCHANTMENT);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,118 @@
|
||||
package net.knarcraft.blacksmith.formatting;
|
||||
|
||||
import net.citizensnpcs.api.npc.NPC;
|
||||
import net.knarcraft.blacksmith.BlacksmithPlugin;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* A formatter for formatting displayed messages
|
||||
*/
|
||||
public final class StringFormatter {
|
||||
|
||||
private final static String pluginName = BlacksmithPlugin.getInstance().getDescription().getName();
|
||||
|
||||
private StringFormatter() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a message from a blacksmith NPC to a player
|
||||
*
|
||||
* @param npc <p>The NPC sending the message</p>
|
||||
* @param player <p>The player to send the message to</p>
|
||||
* @param message <p>The message to send</p>
|
||||
*/
|
||||
public static void sendNPCMessage(NPC npc, Player player, String message) {
|
||||
player.sendMessage(ChatColor.GREEN + "[" + npc.getName() + "] -> You:" + ChatColor.RESET + " " +
|
||||
translateColors(message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a message signifying a successful action
|
||||
*
|
||||
* @param sender <p>The command sender to display the message to</p>
|
||||
* @param message <p>The raw message to display</p>
|
||||
*/
|
||||
public static void displaySuccessMessage(CommandSender sender, String message) {
|
||||
sender.sendMessage(ChatColor.GREEN + getFormattedMessage(message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a message signifying an unsuccessful action
|
||||
*
|
||||
* @param sender <p>The command sender to display the message to</p>
|
||||
* @param message <p>The raw message to display</p>
|
||||
*/
|
||||
public static void displayErrorMessage(CommandSender sender, String message) {
|
||||
sender.sendMessage(ChatColor.DARK_RED + getFormattedMessage(message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the formatted version of any chat message
|
||||
*
|
||||
* @param message <p>The message to format</p>
|
||||
* @return <p>The formatted message</p>
|
||||
*/
|
||||
private static String getFormattedMessage(String message) {
|
||||
return "[" + pluginName + "] " + ChatColor.RESET + translateColors(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates & color codes to proper colors
|
||||
*
|
||||
* @param input <p>The input string to translate colors for</p>
|
||||
* @return <p>The input with color codes translated</p>
|
||||
*/
|
||||
private static String translateColors(String input) {
|
||||
return ChatColor.translateAlternateColorCodes('&', input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces a placeholder in a string
|
||||
*
|
||||
* @param input <p>The input string to replace in</p>
|
||||
* @param placeholder <p>The placeholder to replace</p>
|
||||
* @param replacement <p>The replacement value</p>
|
||||
* @return <p>The input string with the placeholder replaced</p>
|
||||
*/
|
||||
public static String replacePlaceholder(String input, String placeholder, String replacement) {
|
||||
return input.replace(placeholder, replacement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces placeholders in a string
|
||||
*
|
||||
* @param input <p>The input string to replace in</p>
|
||||
* @param placeholders <p>The placeholders to replace</p>
|
||||
* @param replacements <p>The replacement values</p>
|
||||
* @return <p>The input string with placeholders replaced</p>
|
||||
*/
|
||||
public static String replacePlaceholders(String input, String[] placeholders, String[] replacements) {
|
||||
for (int i = 0; i < Math.min(placeholders.length, replacements.length); i++) {
|
||||
input = replacePlaceholder(input, placeholders[i], replacements[i]);
|
||||
}
|
||||
return input;
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates all found color codes to formatting in a string
|
||||
*
|
||||
* @param message <p>The string to search for color codes</p>
|
||||
* @return <p>The message with color codes translated</p>
|
||||
*/
|
||||
public static String translateAllColorCodes(String message) {
|
||||
message = ChatColor.translateAlternateColorCodes('&', message);
|
||||
Pattern pattern = Pattern.compile("(#[a-fA-F0-9]{6})");
|
||||
Matcher matcher = pattern.matcher(message);
|
||||
while (matcher.find()) {
|
||||
message = message.replace(matcher.group(), "" + ChatColor.of(matcher.group()));
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,95 @@
|
||||
package net.knarcraft.blacksmith.formatting;
|
||||
|
||||
import static net.knarcraft.blacksmith.formatting.StringFormatter.replacePlaceholders;
|
||||
|
||||
/**
|
||||
* An enum containing all translatable global messages
|
||||
*
|
||||
* <p>This does not include NPC messages as they are configurable per-npc, and can be translated by changing the
|
||||
* default message values in the main config file.</p>
|
||||
*/
|
||||
public enum TranslatableMessage {
|
||||
|
||||
VALUE_CHANGED,
|
||||
VALUE_FOR_ITEM_CHANGED,
|
||||
CURRENT_VALUE,
|
||||
CURRENT_VALUE_FOR_ITEM,
|
||||
ITEM_TYPE_ENCHANTMENT,
|
||||
ITEM_TYPE_MATERIAL,
|
||||
RAW_VALUE,
|
||||
NO_NPC_SELECTED,
|
||||
DEFAULT_REFORGE_ABLE_ITEMS_UNCHANGEABLE,
|
||||
INPUT_STRING_LIST_REQUIRED,
|
||||
INPUT_PERCENTAGE_REQUIRED,
|
||||
INPUT_STRING_REQUIRED,
|
||||
INPUT_POSITIVE_DOUBLE_REQUIRED,
|
||||
INPUT_POSITIVE_INTEGER_REQUIRED,
|
||||
PERMISSION_DENIED,
|
||||
PLUGIN_RELOADED;
|
||||
|
||||
/**
|
||||
* Gets the message to display when displaying the raw value of messages
|
||||
*
|
||||
* @param rawValue <p>The raw value to display</p>
|
||||
* @return <p>The message to display</p>
|
||||
*/
|
||||
public static String getRawValueMessage(String rawValue) {
|
||||
return StringFormatter.replacePlaceholder(Translator.getTranslatedMessage(TranslatableMessage.RAW_VALUE),
|
||||
"{rawValue}", rawValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the message to display when a value has been changed
|
||||
*
|
||||
* @param setting <p>The setting whose value has been changed</p>
|
||||
* @param newValue <p>The new value of the setting</p>
|
||||
* @return <p>The string to display to a user</p>
|
||||
*/
|
||||
public static String getValueChangedMessage(String setting, String newValue) {
|
||||
return replacePlaceholders(Translator.getTranslatedMessage(TranslatableMessage.VALUE_CHANGED),
|
||||
new String[]{"{setting}", "{newValue}"}, new String[]{setting, newValue});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the message to display when a value has been changed for an item
|
||||
*
|
||||
* @param setting <p>The setting whose value has been changed</p>
|
||||
* @param itemType <p>The type of item changed ("material" or "enchantment")</p>
|
||||
* @param item <p>The item the setting was changed for (a material or an enchantment name)</p>
|
||||
* @param newValue <p>The new value of the setting</p>
|
||||
* @return <p>The string to display to a user</p>
|
||||
*/
|
||||
public static String getItemValueChangedMessage(String setting, ItemType itemType, String item, String newValue) {
|
||||
return replacePlaceholders(Translator.getTranslatedMessage(TranslatableMessage.VALUE_FOR_ITEM_CHANGED),
|
||||
new String[]{"{setting}", "{itemType}", "{item}", "{newValue}"},
|
||||
new String[]{setting, itemType.getItemTypeName(), item, newValue});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the message to display when displaying a setting's current value
|
||||
*
|
||||
* @param setting <p>The setting whose value is shown</p>
|
||||
* @param currentValue <p>The current value of the setting</p>
|
||||
* @return <p>The string to display to a user</p>
|
||||
*/
|
||||
public static String getCurrentValueMessage(String setting, String currentValue) {
|
||||
return replacePlaceholders(Translator.getTranslatedMessage(TranslatableMessage.CURRENT_VALUE),
|
||||
new String[]{"{setting}", "{currentValue}"}, new String[]{setting, currentValue});
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the message to display when displaying a setting's current value for an item
|
||||
*
|
||||
* @param setting <p>The setting whose value is shown</p>
|
||||
* @param itemType <p>The type of item shown ("material" or "enchantment")</p>
|
||||
* @param item <p>The item the setting is shown for (a material or an enchantment name)</p>
|
||||
* @param currentValue <p>The current value of the setting</p>
|
||||
* @return <p>The string to display to a user</p>
|
||||
*/
|
||||
public static String getItemCurrentValueMessage(String setting, ItemType itemType, String item, String currentValue) {
|
||||
return replacePlaceholders(Translator.getTranslatedMessage(TranslatableMessage.CURRENT_VALUE_FOR_ITEM),
|
||||
new String[]{"{setting}", "{itemType}", "{item}", "{currentValue}"},
|
||||
new String[]{setting, itemType.getItemTypeName(), item, currentValue});
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,120 @@
|
||||
package net.knarcraft.blacksmith.formatting;
|
||||
|
||||
import net.knarcraft.blacksmith.BlacksmithPlugin;
|
||||
import net.knarcraft.blacksmith.util.FileHelper;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
|
||||
/**
|
||||
* A tool to get strings translated to the correct language
|
||||
*/
|
||||
public final class Translator {
|
||||
|
||||
private static Map<TranslatableMessage, String> translatedMessages;
|
||||
private static Map<TranslatableMessage, String> backupTranslatedMessages;
|
||||
|
||||
private Translator() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the languages used by this translator
|
||||
*/
|
||||
public static void loadLanguages(String selectedLanguage) {
|
||||
backupTranslatedMessages = loadTranslatedMessages("en");
|
||||
translatedMessages = loadCustomTranslatedMessages(selectedLanguage);
|
||||
if (translatedMessages == null) {
|
||||
translatedMessages = loadTranslatedMessages(selectedLanguage);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a translated version of the given translatable message
|
||||
*
|
||||
* @param translatableMessage <p>The message to translate</p>
|
||||
* @return <p>The translated message</p>
|
||||
*/
|
||||
public static String getTranslatedMessage(TranslatableMessage translatableMessage) {
|
||||
if (translatedMessages == null) {
|
||||
return "Translated strings not loaded";
|
||||
}
|
||||
String translatedMessage;
|
||||
if (translatedMessages.containsKey(translatableMessage)) {
|
||||
translatedMessage = translatedMessages.get(translatableMessage);
|
||||
} else if (backupTranslatedMessages.containsKey(translatableMessage)) {
|
||||
translatedMessage = backupTranslatedMessages.get(translatableMessage);
|
||||
} else {
|
||||
translatedMessage = translatableMessage.toString();
|
||||
}
|
||||
return StringFormatter.translateAllColorCodes(translatedMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads all translated messages for the given language
|
||||
*
|
||||
* @param language <p>The language chosen by the user</p>
|
||||
* @return <p>A mapping of all strings for the given language</p>
|
||||
*/
|
||||
public static Map<TranslatableMessage, String> loadTranslatedMessages(String language) {
|
||||
try {
|
||||
BufferedReader reader = FileHelper.getBufferedReaderForInternalFile("/strings.yml");
|
||||
return loadTranslatableMessages(language, reader);
|
||||
} catch (FileNotFoundException e) {
|
||||
BlacksmithPlugin.getInstance().getLogger().log(Level.SEVERE, "Unable to load translated messages");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to load translated messages from a custom strings.yml file
|
||||
*
|
||||
* @param language <p>The selected language</p>
|
||||
* @return <p>The loaded translated strings, or null if no custom language file exists</p>
|
||||
*/
|
||||
public static Map<TranslatableMessage, String> loadCustomTranslatedMessages(String language) {
|
||||
BlacksmithPlugin instance = BlacksmithPlugin.getInstance();
|
||||
|
||||
File strings = new File(instance.getDataFolder(), "strings.yml");
|
||||
if (!strings.exists()) {
|
||||
instance.getLogger().log(Level.FINEST, "Strings file not found");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
instance.getLogger().log(Level.INFO, "Loading custom strings...");
|
||||
return loadTranslatableMessages(language, new BufferedReader(new InputStreamReader(new FileInputStream(strings))));
|
||||
} catch (FileNotFoundException e) {
|
||||
instance.getLogger().log(Level.WARNING, "Unable to load custom messages");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads translatable messages from the given reader
|
||||
*
|
||||
* @param language <p>The selected language</p>
|
||||
* @param reader <p>The buffered reader to read from</p>
|
||||
* @return <p>The loaded translated strings</p>
|
||||
*/
|
||||
private static Map<TranslatableMessage, String> loadTranslatableMessages(String language, BufferedReader reader) {
|
||||
Map<TranslatableMessage, String> translatedMessages = new HashMap<>();
|
||||
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(reader);
|
||||
|
||||
for (TranslatableMessage message : TranslatableMessage.values()) {
|
||||
String translated = configuration.getString(language + "." + message.toString());
|
||||
if (translated != null) {
|
||||
translatedMessages.put(message, translated);
|
||||
}
|
||||
}
|
||||
return translatedMessages;
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user