package com.earth2me.essentials; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.text.MessageFormat; import java.util.*; import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Pattern; import net.ess3.api.IEssentials; import org.bukkit.Bukkit; public class I18n implements net.ess3.api.II18n { private static I18n instance; private static final String MESSAGES = "messages"; private final transient Locale defaultLocale = Locale.getDefault(); private transient Locale currentLocale = defaultLocale; private transient ResourceBundle customBundle; private transient ResourceBundle localeBundle; private final transient ResourceBundle defaultBundle; private transient Map messageFormatCache = new HashMap(); private final transient IEssentials ess; private static final Pattern NODOUBLEMARK = Pattern.compile("''"); private static final ResourceBundle NULL_BUNDLE = new ResourceBundle() { public Enumeration getKeys() { return null; } protected Object handleGetObject(String key) { return null; } }; public I18n(final IEssentials ess) { this.ess = ess; defaultBundle = ResourceBundle.getBundle(MESSAGES, Locale.ENGLISH); localeBundle = defaultBundle; customBundle = NULL_BUNDLE; } public void onEnable() { instance = this; } public void onDisable() { instance = null; } @Override public Locale getCurrentLocale() { return currentLocale; } private String translate(final String string) { try { try { return customBundle.getString(string); } catch (MissingResourceException ex) { return localeBundle.getString(string); } } catch (MissingResourceException ex) { Logger.getLogger("Essentials").log(Level.WARNING, String.format("Missing translation key \"%s\" in translation file %s", ex.getKey(), localeBundle.getLocale().toString()), ex); return defaultBundle.getString(string); } } public static String tl(final String string, final Object... objects) { if (instance == null) { return ""; } if (objects.length == 0) { return NODOUBLEMARK.matcher(instance.translate(string)).replaceAll("'"); } else { return instance.format(string, objects); } } public String format(final String string, final Object... objects) { String format = translate(string); MessageFormat messageFormat = messageFormatCache.get(format); if (messageFormat == null) { try { messageFormat = new MessageFormat(format); } catch (IllegalArgumentException e) { ess.getLogger().log(Level.SEVERE, "Invalid Translation key for '" + string + "': " + e.getMessage()); format = format.replaceAll("\\{(\\D*?)\\}", "\\[$1\\]"); messageFormat = new MessageFormat(format); } messageFormatCache.put(format, messageFormat); } return messageFormat.format(objects); } public void updateLocale(final String loc) { if (loc != null && !loc.isEmpty()) { final String[] parts = loc.split("[_\\.]"); if (parts.length == 1) { currentLocale = new Locale(parts[0]); } if (parts.length == 2) { currentLocale = new Locale(parts[0], parts[1]); } if (parts.length == 3) { currentLocale = new Locale(parts[0], parts[1], parts[2]); } } ResourceBundle.clearCache(); messageFormatCache = new HashMap(); Logger.getLogger("Essentials").log(Level.INFO, String.format("Using locale %s", currentLocale.toString())); try { localeBundle = ResourceBundle.getBundle(MESSAGES, currentLocale); } catch (MissingResourceException ex) { localeBundle = NULL_BUNDLE; } try { customBundle = ResourceBundle.getBundle(MESSAGES, currentLocale, new FileResClassLoader(I18n.class.getClassLoader(), ess)); } catch (MissingResourceException ex) { customBundle = NULL_BUNDLE; } } public static String capitalCase(final String input) { return input == null || input.length() == 0 ? input : input.toUpperCase(Locale.ENGLISH).charAt(0) + input.toLowerCase(Locale.ENGLISH).substring(1); } private static class FileResClassLoader extends ClassLoader { private final transient File dataFolder; FileResClassLoader(final ClassLoader classLoader, final IEssentials ess) { super(classLoader); this.dataFolder = ess.getDataFolder(); } @Override public URL getResource(final String string) { final File file = new File(dataFolder, string); if (file.exists()) { try { return file.toURI().toURL(); } catch (MalformedURLException ex) { } } return null; } @Override public InputStream getResourceAsStream(final String string) { final File file = new File(dataFolder, string); if (file.exists()) { try { return new FileInputStream(file); } catch (FileNotFoundException ex) { } } return null; } } }