Add support for multiple locale.

This commit is contained in:
Jesse Prescott 2018-05-31 11:56:19 +01:00
parent 4f69842b74
commit 8dcf36c93f
10 changed files with 460 additions and 49 deletions

View File

@ -0,0 +1,68 @@
/*
* ItemCase is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
*/
package com.gmail.bleedobsidian.itemcase;
import net.md_5.bungee.api.ChatColor;
import org.bukkit.command.CommandSender;
/**
* Utility class used for communicating in different dialects.
*
* @author Jesse Prescott (BleedObsidian).
*/
public final class ChatLogger {
/**
* The prefix placed before all messages.
*/
private final static String PREFIX =
ChatColor.BLUE + "[ItemCase]: " + ChatColor.RESET;
/**
* Language translator.
*/
private LanguageTranslator translator;
/**
* Constructor.
*
* @param translator language translator.
*/
public ChatLogger(LanguageTranslator translator) {
// Set translator.
this.translator = translator;
}
/**
* Send given CommandSender message.
*
* @param sender CommandSender.
* @param message Message key or message.
*/
public void message(CommandSender sender, String string) {
// If string is a message key.
if(this.translator.isKey(string)) {
// Translate.
string = this.translator.getTranslation(string);
}
// Send message.
sender.sendMessage(ChatLogger.PREFIX + string);
}
}

View File

@ -17,6 +17,7 @@ package com.gmail.bleedobsidian.itemcase;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.StandardCopyOption; import java.nio.file.StandardCopyOption;
import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.FileConfiguration;
@ -45,6 +46,11 @@ public class ConfigurationFile {
*/ */
private String defaultName; private String defaultName;
/**
* If this configuration file can be copied outside of the jar.
*/
private boolean canCopy = true;
/** /**
* @param name The name of this configuration file. * @param name The name of this configuration file.
* @param defaultName The name of the default file in the jar. * @param defaultName The name of the default file in the jar.
@ -52,8 +58,8 @@ public class ConfigurationFile {
public ConfigurationFile(String name, String defaultName) { public ConfigurationFile(String name, String defaultName) {
// Set name. // Set name.
this.defaultName = defaultName;
this.name = name; this.name = name;
this.defaultName = defaultName;
} }
/** /**
@ -61,9 +67,23 @@ public class ConfigurationFile {
*/ */
public ConfigurationFile(String name) { public ConfigurationFile(String name) {
// Set name.
this.name = name;
this.defaultName = name;
}
/**
* @param name The name of this configuration file.
* @param canCopy If configuration file can be copied outside of the jar.
*/
public ConfigurationFile(String name, boolean canCopy) {
// Set name. // Set name.
this.defaultName = name; this.defaultName = name;
this.name = name; this.name = name;
// Set canCopy.
this.canCopy = canCopy;
} }
/** /**
@ -75,18 +95,32 @@ public class ConfigurationFile {
*/ */
public void load(JavaPlugin plugin) throws IOException { public void load(JavaPlugin plugin) throws IOException {
// Create file reference. // If this configuration file can be copied outside of the jar...
File fileReference = new File(plugin.getDataFolder(), this.name); if(this.canCopy) {
// If the file doesn't exist... // Create file reference.
if(!fileReference.exists()) { File fileReference = new File(plugin.getDataFolder(), this.name);
// Copy default config from jar to data folder. // If the file doesn't exist...
this.copyDefault(plugin); if(!fileReference.exists() && this.canCopy) {
// Copy default config from jar to data folder.
this.copyDefault(plugin);
}
// Attempt to load it.
this.file = YamlConfiguration.loadConfiguration(fileReference);
// Exit.
return;
} }
// Attempt to create an input stream reader of the file in the jar.
InputStreamReader inputStreamReader =
new InputStreamReader(plugin.getResource(this.name));
// Attempt to load it. // Attempt to load it.
this.file = YamlConfiguration.loadConfiguration(fileReference); this.file = YamlConfiguration.loadConfiguration(inputStreamReader);
} }
/** /**
@ -128,10 +162,38 @@ public class ConfigurationFile {
*/ */
public void save(JavaPlugin plugin) throws IOException { public void save(JavaPlugin plugin) throws IOException {
// If this configuration file can not be copied outside of the jar...
if(!this.canCopy) {
// Exit.
return;
}
// Create reference to output file. // Create reference to output file.
File outputFile = new File(plugin.getDataFolder(), this.name); File outputFile = new File(plugin.getDataFolder(), this.name);
// Attempt to save file. // Attempt to save file.
this.file.save(outputFile); this.file.save(outputFile);
} }
/**
* Check if this file contains the given key.
*
* @param key Key.
* @return Boolean.
*/
public boolean hasKey(String key) {
// Return if key exists.
return this.file.contains(key);
}
/**
* @return If file is loaded.
*/
public boolean isLoaded() {
// Return true if file is not null.
return this.file != null;
}
} }

View File

@ -29,10 +29,23 @@ import org.fusesource.jansi.Ansi;
*/ */
public final class ConsoleLogger extends Logger { public final class ConsoleLogger extends Logger {
/** /**
* The Bukkit JavaPlugin. * White color string for console.
*/ */
private JavaPlugin plugin; private static final String WHITE_COLOR =
Ansi.ansi().fg(Ansi.Color.WHITE).boldOff().toString();
/**
* Yellow color string for console.
*/
private static final String YELLOW_COLOR =
Ansi.ansi().fg(Ansi.Color.YELLOW).bold().toString();
/**
* Red color string for console.
*/
private static final String RED_COLOR =
Ansi.ansi().fg(Ansi.Color.RED).bold().toString();
/** /**
* The plugin prefix. * The plugin prefix.
@ -40,26 +53,16 @@ public final class ConsoleLogger extends Logger {
private final String prefix; private final String prefix;
/** /**
* White color string for console. * Language translator.
*/ */
private final String whiteColor; private final LanguageTranslator translator;
/**
* Yellow color string for console.
*/
private final String yellowColor;
/**
* Red color string for console.
*/
private final String redColor;
/** /**
* Constructor. * Constructor.
* *
* @param plugin The B * @param plugin The B
*/ */
public ConsoleLogger(JavaPlugin plugin) { public ConsoleLogger(JavaPlugin plugin, LanguageTranslator translator) {
// Call parent constructor. // Call parent constructor.
super(plugin.getName(), null); super(plugin.getName(), null);
@ -68,20 +71,29 @@ public final class ConsoleLogger extends Logger {
super.setParent(plugin.getServer().getLogger()); super.setParent(plugin.getServer().getLogger());
super.setLevel(Level.ALL); super.setLevel(Level.ALL);
// Set console color strings.
this.whiteColor = Ansi.ansi().fg(Ansi.Color.WHITE).boldOff().toString();
this.yellowColor = Ansi.ansi().fg(Ansi.Color.YELLOW).bold().toString();
this.redColor = Ansi.ansi().fg(Ansi.Color.RED).bold().toString();
// Set plugin prefix. // Set plugin prefix.
this.prefix = "[" + plugin.getName() + "] "; this.prefix = "[" + plugin.getName() + "] ";
// Set translator.
this.translator = translator;
} }
@Override @Override
public void log(LogRecord logRecord) { public void log(LogRecord logRecord) {
// Message.
String message = logRecord.getMessage();
// If message is a message key.
if(translator.isKey(message)) {
// Translate.
message = translator.getTranslation(message);
}
// Default white text. // Default white text.
logRecord.setMessage(this.prefix + logRecord.getMessage()); logRecord.setMessage(this.prefix + message);
// Parent. // Parent.
super.log(logRecord); super.log(logRecord);
@ -90,8 +102,17 @@ public final class ConsoleLogger extends Logger {
@Override @Override
public void warning(String message) { public void warning(String message) {
// If message is a message key.
if(translator.isKey(message)) {
// Translate.
message = translator.getTranslation(message);
}
// Add color to message. // Add color to message.
message = this.yellowColor + message + this.whiteColor; message = ConsoleLogger.YELLOW_COLOR + message +
ConsoleLogger.WHITE_COLOR;
// Log message. // Log message.
this.log(Level.WARNING, message); this.log(Level.WARNING, message);
@ -100,8 +121,17 @@ public final class ConsoleLogger extends Logger {
@Override @Override
public void severe(String message) { public void severe(String message) {
// If message is a message key.
if(translator.isKey(message)) {
// Translate.
message = translator.getTranslation(message);
}
// Add color to message. // Add color to message.
message = this.redColor + message + this.whiteColor; message = ConsoleLogger.RED_COLOR + message +
ConsoleLogger.WHITE_COLOR;
// Log message. // Log message.
this.log(Level.SEVERE, message); this.log(Level.SEVERE, message);
@ -115,8 +145,17 @@ public final class ConsoleLogger extends Logger {
*/ */
public void severe(String message, Throwable throwable) { public void severe(String message, Throwable throwable) {
// If message is a message key.
if(translator.isKey(message)) {
// Translate.
message = translator.getTranslation(message);
}
// Add color to message. // Add color to message.
message = this.redColor + message + this.whiteColor; message = ConsoleLogger.RED_COLOR + message +
ConsoleLogger.WHITE_COLOR;
// Log message. // Log message.
this.log(Level.SEVERE, message, throwable); this.log(Level.SEVERE, message, throwable);

View File

@ -39,10 +39,21 @@ public final class ItemCaseCore extends JavaPlugin {
*/ */
private final ConfigFile configFile = new ConfigFile(); private final ConfigFile configFile = new ConfigFile();
/**
* The language translator.
*/
private final LanguageTranslator translator = new LanguageTranslator();
/** /**
* Custom plugin console logger. * Custom plugin console logger.
*/ */
private final ConsoleLogger consoleLogger = new ConsoleLogger(this); private final ConsoleLogger consoleLogger = new ConsoleLogger(this,
translator);
/**
* Chat logger.
*/
private final ChatLogger chatLogger = new ChatLogger(translator);
/** /**
* ItemcaseManager. * ItemcaseManager.
@ -73,8 +84,20 @@ public final class ItemCaseCore extends JavaPlugin {
return; return;
} }
// Attempt to load translator with given locale.
if(!this.translator.load(this, this.configFile.getLocale())) {
// Failed to load, stop loading.
return;
}
// Log. // Log.
this.consoleLogger.info("Successfully loaded main configuration file."); this.consoleLogger.info("console.info.config-loaded");
// Set language placeholder and log.
this.translator.setPlaceholder("%LANGUAGE%",
this.configFile.getLocale().name());
this.consoleLogger.info("console.info.locale");
// Initialize ItemcaseManager. // Initialize ItemcaseManager.
this.itemcaseManager.registerListener(); this.itemcaseManager.registerListener();
@ -84,11 +107,12 @@ public final class ItemCaseCore extends JavaPlugin {
new ItemcaseListener(), this); new ItemcaseListener(), this);
// Log. // Log.
this.consoleLogger.info("Main event listener registered."); this.consoleLogger.info("console.info.listener-registered");
// Log. // Set version placeholder and log.
this.consoleLogger.info("ItemCase " + this.translator.setPlaceholder("%VERSION%",
this.getDescription().getVersion() + " enabled."); this.getDescription().getVersion());
this.consoleLogger.info("console.info.enabled");
} }
@Override @Override
@ -98,7 +122,7 @@ public final class ItemCaseCore extends JavaPlugin {
this.itemcaseManager.unloadItemcases(); this.itemcaseManager.unloadItemcases();
// Log. // Log.
this.consoleLogger.info("Itemcases unloaded successfully."); this.consoleLogger.info("config.info.unloaded");
} }
/** /**
@ -109,6 +133,13 @@ public final class ItemCaseCore extends JavaPlugin {
return this.configFile; return this.configFile;
} }
/**
* @return Language translator.
*/
public LanguageTranslator getTranslator() {
return this.translator;
}
/** /**
* @return Custom plugin console logger. * @return Custom plugin console logger.
*/ */

View File

@ -0,0 +1,132 @@
/*
* ItemCase is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
*/
package com.gmail.bleedobsidian.itemcase;
import com.gmail.bleedobsidian.itemcase.configurations.LanguageFile;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map.Entry;
import org.bukkit.plugin.java.JavaPlugin;
/**
* Utility class used for communicating in different dialects.
*
* @author Jesse Prescott (BleedObsidian).
*/
public final class LanguageTranslator {
/**
* Supported languages.
*/
public static enum Language {
EN
};
/**
* The language file for the chosen language.
*/
private LanguageFile file;
/**
* A hash map of placeholders.
*/
private HashMap<String, String> placeholders = new HashMap<>();
/**
* Load corresponding language file.
*
* @param plugin JavaPlugin.
* @param language Language to communicate in.
* @return If loading was successful.
*/
public boolean load(JavaPlugin plugin, Language language) {
// Create language file.
this.file = new LanguageFile(language);
// Attempt to load language file.
try {
// Load language file.
this.file.load(plugin);
} catch (IOException e) {
// Display error.
ItemCaseCore.instance.getConsoleLogger().severe(
"Failed to load configuration file.", e);
// Failed to load.
return false;
}
// Successfully loaded.
return true;
}
/**
* Get translation.
*
* @param key Message key.
* @return String.
*/
public String getTranslation(String key) {
// Get raw translation.
String translation = this.file.getRawTranslation(key);
// For every placeholder.
for(Entry<String, String> entry : this.placeholders.entrySet()) {
// Replace the placeholder with given value if placeholder is
// present in string.
translation = translation.replace(entry.getKey(), entry.getValue());
}
// Return translation.
return translation;
}
/**
* Set the value of a given placeholder.
*
* @param placeholder Placeholder.
* @param value Value.
*/
public void setPlaceholder(String placeholder, String value) {
// Update HashMap.
this.placeholders.put(placeholder, value);
}
/**
* If given string is a valid message key.
*
* @param string String.
* @return Boolean.
*/
public boolean isKey(String string) {
// If the file is not loaded yet.
if(!this.file.isLoaded()) {
// Return false as we cant do translations yet.
return false;
}
// Check if key exists and return result.
return this.file.hasKey(string);
}
}

View File

@ -15,6 +15,7 @@
package com.gmail.bleedobsidian.itemcase.configurations; package com.gmail.bleedobsidian.itemcase.configurations;
import com.gmail.bleedobsidian.itemcase.ConfigurationFile; import com.gmail.bleedobsidian.itemcase.ConfigurationFile;
import com.gmail.bleedobsidian.itemcase.LanguageTranslator.Language;
import java.util.ArrayList; import java.util.ArrayList;
import org.bukkit.Material; import org.bukkit.Material;
@ -35,10 +36,18 @@ public class ConfigFile extends ConfigurationFile {
} }
/** /**
* @return The chosen locale to use. * @return The chosen Language to use.
*/ */
public String getLocale() { public Language getLocale() {
return this.file.getString("Locale");
// Get set locale string.
String locale = this.file.getString("Locale");
// Convert to uppercase just in case.
locale = locale.toUpperCase();
// Return equivalent language.
return Language.valueOf(locale);
} }
/** /**

View File

@ -0,0 +1,48 @@
/*
* ItemCase is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/gpl.html>.
*/
package com.gmail.bleedobsidian.itemcase.configurations;
import com.gmail.bleedobsidian.itemcase.ConfigurationFile;
import com.gmail.bleedobsidian.itemcase.LanguageTranslator.Language;
/**
* A configuration file that holds the translations for a specific dialect.
*
* @author Jesse Prescott (BleedObsidian)
*/
public class LanguageFile extends ConfigurationFile {
/**
* Constructor.
*
* @param Language The language this file is for.
*/
public LanguageFile(Language language) {
// Give config file name and prevent file being copied outside of jar.
super("languages/" + language.name() + ".yml", false);
}
/**
* Get the raw translation for the given message key.
*
* @param key Key.
* @return String.
*/
public String getRawTranslation(String key) {
return this.file.getString(key);
}
}

View File

@ -154,9 +154,11 @@ public final class ItemcaseManager {
return; return;
} }
// Log. // Set world name placeholder and log.
ItemCaseCore.instance.getTranslator().setPlaceholder(
"%WORLD_NAME%", world.getName());
ItemCaseCore.instance.getConsoleLogger().info( ItemCaseCore.instance.getConsoleLogger().info(
"Loaded itemcases for world: " + world.getName()); "console.info.loaded");
} }
} }

View File

@ -4,8 +4,8 @@
#---------------------------------------------------------------------# #---------------------------------------------------------------------#
# Locale: # Locale:
# - en-us # - EN
Locale: en-us Locale: EN
# General Options # General Options
Options: Options:

View File

@ -0,0 +1,20 @@
#--------------------------- Language File ---------------------------#
# This file contains all of the english translations for ItemCase. #
#---------------------------------------------------------------------#
# Console based messages.
console:
# Non erroneous messages.
info:
# Shown during plugin loading.
#
# %LANGUAGE% = The language as set in the main config.
# %VERSION% = The version of ItemCase in use.
locale: "Using locale: %LANGUAGE%"
config-loaded: "Successfully loaded main configuration file."
listener-registered: "Main event listener registered."
enabled: "ItemCase v%VERSION% enabled."
unloaded: "Itemcases unloaded successfully."
loaded: "Loaded itemcases for world: %WORLD_NAME%"