/* * This file is part of VIUtils. * * Copyright © 2012-2015 Visual Illusions Entertainment * * VIUtils is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, * or (at your option) any later version. * * This library 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 Lesser General Public License for more details. * * You should have received a copy of the GNU General Public License along with this library. * If not, see http://www.gnu.org/licenses/lgpl.html. */ package net.visualillusionsent.utils; import java.io.File; import java.text.MessageFormat; import java.util.HashMap; import java.util.Locale; import java.util.logging.Logger; /** * Message Localization helper * <p/> * If extending this class you should include a folder called resources in your jar and in that a folder called lang.<br> * Then include a text file called languages.txt that contains keys like the language.txt included with VIUtils.<br> * You should also include a en_US.lang file with default English messages for your implementation. * <p/> * As of LocaleHelper 1.2, you can now specify an external directory as the path to the lang files.<br> * The directory should be set up the same as though it is inside the Jar file. * * @author Jason (darkdiplomat) * @version 1.5 * @since 1.0.0 */ public abstract class LocaleHelper { /* 1.5 @ VIUtils 1.4.2 */ private static final float classVersion = 1.5F; /* languages.txt quick reference */ private static final String langTXT = "languages.txt"; /** Map of supported languages */ protected final HashMap<String, UnmodifiablePropertiesFile> langs = new HashMap<String, UnmodifiablePropertiesFile>(); /** The language.txt file for knowing which languages are supported */ protected final UnmodifiablePropertiesFile utils_lang; /** Jar path container, override as needed */ protected final String jarPath; /** The System default code */ protected final String defaultLocale; /** Set to true if external files are used */ protected final boolean external; /** Path to external files */ protected final String extDir; /** Set to true to enable debugging */ protected boolean debug_enabled = false; /** Constructs a default LocaleHelper that will look in the jar for the lang files */ protected LocaleHelper() { this(false, null, (String) null); } /** * Constructs a default LocaleHelper with a default Locale specified * * @param defaultLocale * the locale to use by default */ protected LocaleHelper(String defaultLocale) { this(false, null, defaultLocale); } /** * Constructs a default LocaleHelper with a default Locale specified * * @param defaultLocale * the locale to use by default */ protected LocaleHelper(Locale defaultLocale) { this(false, null, defaultLocale.toString()); } /** * Constructs a new LocaleHelper with specifying external files and the directory for those files * * @param useExternalFiles * {@code true} for external files; {@code false} otherwise * @param externalDirectory * the path to the directory for the external files * @param defaultLocale * the default Locale to use for messages */ protected LocaleHelper(boolean useExternalFiles, String externalDirectory, Locale defaultLocale) { this(useExternalFiles, externalDirectory, defaultLocale.toString()); } /** * Constructs a new LocaleHelper with specifying external files and the directory for those files * * @param useExternalFiles * {@code true} for external files; {@code false} otherwise * @param externalDirectory * the path to the directory for the external files * @param defaultLocale * the default Locale to use for messages */ protected LocaleHelper(boolean useExternalFiles, String externalDirectory, String defaultLocale) { this.defaultLocale = defaultLocale == null ? SystemUtils.SYSTEM_LOCALE : defaultLocale; if (externalDirectory == null) { this.external = false; this.extDir = null; } else { this.external = useExternalFiles; String adjustPath = FileUtils.normalizePath(externalDirectory); this.extDir = adjustPath.endsWith(File.separator) ? adjustPath : adjustPath.concat(File.separator); } this.jarPath = JarUtils.getJarPath(getClass()); if (!external) { utils_lang = new UnmodifiablePropertiesFile(jarPath, "resources/lang/".concat(langTXT)); } else { utils_lang = new UnmodifiablePropertiesFile(extDir.concat(langTXT)); } loadLang("en_US"); if (this.defaultLocale != null && this.defaultLocale.matches("([a-z]{2,3})_([A-Z]{2,3})") && utils_lang.containsKey(defaultLocale)) { loadLang(this.defaultLocale); } } public final String localeTranslate(String key, String locale) { try { if (locale != null && locale.matches("([a-z]{2,3})_([A-Z]{2,3})") && utils_lang.containsKey(locale)) { if (!langs.containsKey(locale)) { loadLang(locale); } return langs.get(locale).getString(key); } } catch (Exception e) { if (debug_enabled) { Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).warning("[VIUtils] Exception thrown from LocaleHelper, check the viutils logs."); UtilsLogger.warning("Translate Error: ", e); } } return systemTranslate(key); } /** * Gets the translated message for the given key * * @param key * the key to the translated message * * @return translated message */ public final String systemTranslate(String key) { try { if (defaultLocale != null && langs.containsKey(defaultLocale) && langs.get(defaultLocale).containsKey(key)) { return langs.get(defaultLocale).getString(key); } } catch (Exception e) { if (debug_enabled) { Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).warning("[VIUtils] Exception thrown from LocaleHelper, check the viutils logs."); UtilsLogger.warning("Translate Error: ", e); } } return defaultTranslate(key); } /** * Gets the default English message for the given key * * @param key * the key to the translated message * * @return translated message */ public final String defaultTranslate(String key) { try { if (langs.get("en_US").containsKey(key)) { return langs.get("en_US").getString(key); } } catch (Exception e) { if (debug_enabled) { Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).warning("[VIUtils] Exception thrown from LocaleHelper, check the viutils logs."); UtilsLogger.warning("Translate Error: ", e); } } //May have forgot a translation and left a regular message, or something went wrong... return key; } public final String localeTranslate(String key, String locale, Object... form) { try { if (locale != null && locale.matches("([a-z]{2,3})_([A-Z]{2,3})") && utils_lang.containsKey(locale)) { if (!langs.containsKey(locale)) { loadLang(locale); } return MessageFormat.format(langs.get(locale).getString(key), form); } } catch (Exception e) { if (debug_enabled) { Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).warning("[VIUtils] Exception thrown from LocaleHelper, check the viutils logs."); UtilsLogger.warning("Translate Error", e); } } return systemTranslate(key, form); } /** * Gets the translated message for the given key and then formatted to include the form string * * @param key * the key to the translated message * @param form * the arguments to pass the {@link MessageFormat} * * @return translated message * * @see MessageFormat#format(String, Object...) */ public final String systemTranslate(String key, Object... form) { try { if (defaultLocale != null && langs.containsKey(defaultLocale) && langs.get(defaultLocale).containsKey(key)) { return MessageFormat.format(langs.get(defaultLocale).getString(key), form); } } catch (Exception e) { if (debug_enabled) { Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).warning("[VIUtils] Exception thrown from LocaleHelper, check the viutils logs."); UtilsLogger.warning("Translate Error", e); } } return defaultTranslate(key, form); } /** * Gets the default English message for the given key and then formatted to include the form string * * @param key * the key to the translated message * @param form * the arguments to pass the {@link MessageFormat} * * @return translated message * * @see MessageFormat#format(String, Object...) */ public final String defaultTranslate(String key, Object... form) { try { if (langs.get("en_US").containsKey(key)) { return MessageFormat.format(langs.get("en_US").getString(key), form); } } catch (Exception e) { if (debug_enabled) { Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).warning("[VIUtils] Exception thrown from LocaleHelper, check the viutils logs."); UtilsLogger.warning("Translate Error: ", e); } } //May have forgot a translation and left a regular message return MessageFormat.format(key, form); } /** * Reloads the language files. * * @see UnmodifiablePropertiesFile#reload */ public final void reloadLangFiles() { for (UnmodifiablePropertiesFile upf : langs.values()) { upf.reload(); } } private void loadLang(String locale) { if (langs.containsKey(utils_lang.getString(locale))) { // Save memory, reuse pointers UnmodifiablePropertiesFile temp = langs.get(utils_lang.getString(locale)); langs.put(locale, temp); } else { if (!external) { langs.put(locale, new UnmodifiablePropertiesFile(jarPath, "resources/lang/".concat(utils_lang.getString(locale)).concat(".lang"))); } else { langs.put(locale, new UnmodifiablePropertiesFile(extDir.concat(utils_lang.getString(locale)).concat(".lang"))); } } } /** * Gets this class's version number * * @return the class version */ public static float getClassVersion() { return classVersion; } }