Skip to content

Instantly share code, notes, and snippets.

@Braayy
Last active November 5, 2020 19:12
Show Gist options
  • Save Braayy/6027148ab6f1289c4323410eff33776f to your computer and use it in GitHub Desktop.
Save Braayy/6027148ab6f1289c4323410eff33776f to your computer and use it in GitHub Desktop.
A message provider with i18n for the bukkit plataform
package braayy.lib.provider.impl;
import braayy.lib.provider.MessageProvider;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.logging.Level;
public class DefaultMessageProvider implements MessageProvider {
private final Map<String, Map<String, String[]>> messageMap;
private String defaultLanguage;
public DefaultMessageProvider() {
this.messageMap = new HashMap<>();
this.defaultLanguage = "en_us";
}
@Override
public void enable(Plugin plugin) {
try {
long start = System.currentTimeMillis();
File i18nFolder = new File(plugin.getDataFolder(), "i18n");
if (!i18nFolder.exists()) {
if (!i18nFolder.mkdirs()) {
throw new IllegalStateException("Could not make i18n folder");
}
this.saveDefaultLangFiles(i18nFolder);
} else {
this.loadLangFiles(i18nFolder);
}
long diff = System.currentTimeMillis() - start;
for (String lang : this.messageMap.keySet()) {
plugin.getLogger().info(lang + " locale was loaded");
}
plugin.getLogger().info("Message service was enabled successfully " + diff + "ms");
} catch (Exception ex) {
plugin.getLogger().log(Level.SEVERE, "Could not load messages.yml", ex);
}
}
@Override
public String[] get(String key, Object... args) {
return this.get(this.defaultLanguage, key, args);
}
@Override
public String[] get(String locale, String key, Object... args) {
if ((args.length & 1) != 0) {
throw new IllegalArgumentException("args length must be even");
}
Map<String, String[]> localeMap = this.messageMap.get(locale);
Objects.requireNonNull(localeMap, locale + " locale was not found");
String[] messageArray = localeMap.get(key);
Objects.requireNonNull(messageArray, key + " message was not found");
String[] appliedArray = new String[messageArray.length];
for (int i = 0 ; i < messageArray.length; i++) {
appliedArray[i] = applyParameters(messageArray[i], args);
}
return appliedArray;
}
@Override
public void sendMessage(CommandSender sender, String key, Object... args) {
String locale = (sender instanceof Player) ? ((Player) sender).getLocale() : this.defaultLanguage;
String[] messageArray = this.get(locale, key, args);
sender.sendMessage(messageArray);
}
@Override
public void setDefaultLanguage(String defaultLanguage) {
this.defaultLanguage = defaultLanguage;
}
private void loadLangFiles(File i18nFolder) {
File[] langFiles = i18nFolder.listFiles();
if (langFiles == null) {
throw new IllegalStateException("Could not list i18n folder");
}
for (File langFile : langFiles) {
YamlConfiguration yaml = YamlConfiguration.loadConfiguration(langFile);
String lang = langFile.getName();
lang = lang.substring(0, lang.length() - 4);
this.searchMessages(lang, yaml);
}
}
private void saveDefaultLangFiles(File i18nFolder) throws Exception {
File ownFile = new File(MessageProvider.class.getProtectionDomain().getCodeSource().getLocation().getPath());
JarFile jarFile = new JarFile(ownFile);
Enumeration<JarEntry> enumeration = jarFile.entries();
while (enumeration.hasMoreElements()) {
JarEntry entry = enumeration.nextElement();
if (entry.getName().startsWith("i18n/") && !entry.isDirectory()) {
String fileName = entry.getName().substring(5);
File langFile = new File(i18nFolder, fileName);
FileOutputStream output = new FileOutputStream(langFile);
InputStream input = jarFile.getInputStream(entry);
byte[] buffer = new byte[2048];
int read;
while ((read = input.read(buffer)) != -1) {
output.write(buffer, 0, read);
}
output.flush();
YamlConfiguration yaml = YamlConfiguration.loadConfiguration(langFile);
String lang = langFile.getName();
lang = lang.substring(0, lang.length() - 4);
this.searchMessages(lang, yaml);
}
}
}
private void searchMessages(String locale, ConfigurationSection section) {
for (String key : section.getKeys(false)) {
String path = section.getCurrentPath() + '.' + key;
if (path.startsWith(".")) path = path.substring(1);
if (section.isConfigurationSection(key)) {
this.searchMessages(locale, section.getConfigurationSection(key));
} else if (section.isString(key)) {
String message = ChatColor.translateAlternateColorCodes('&', section.getString(key));
Map<String, String[]> localeMap = this.messageMap.getOrDefault(locale, new HashMap<>());
localeMap.put(key, new String[] { message });
this.messageMap.put(locale, localeMap);
} else if (section.isList(key)) {
List<String> messageList = section.getStringList(key);
messageList.replaceAll(string -> ChatColor.translateAlternateColorCodes('&', string));
Map<String, String[]> localeMap = this.messageMap.getOrDefault(locale, new HashMap<>());
localeMap.put(path, messageList.toArray(new String[0]));
this.messageMap.put(locale, localeMap);
}
}
}
private static String applyParameters(String string, Object... args) {
for (int i = 0; i < args.length; i += 2) {
String key = (String) args[i];
String value = args[i + 1].toString();
string = string.replace("{" + key + "}", value);
}
return string;
}
}
package braayy.lib.provider;
import org.bukkit.command.CommandSender;
import org.bukkit.plugin.Plugin;
public interface MessageProvider {
/**
* Configures the service
* @param plugin The plugin who is enabling this service
*/
void enable(Plugin plugin);
/**
* @param key The key of the message
* @param args The arguments for the message
* @return The formatted message
*/
String[] get(String key, Object... args);
/**
* @param locale The locale of the message
* @param key The key of the message
* @param args The arguments for the message
* @return The formatted message
*/
String[] get(String locale, String key, Object... args);
/**
* @param sender The sender who will receive this message
* @param key The key of the message
* @param args The arguments for the message
*/
void sendMessage(CommandSender sender, String key, Object... args);
/**
* @param defaultLanguage The default language
*/
void setDefaultLanguage(String defaultLanguage);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment