/* * Copyright 2004 - 2008 Christian Sprajc. All rights reserved. * * This file is part of PowerFolder. * * PowerFolder 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. * * PowerFolder 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 PowerFolder. If not, see <http://www.gnu.org/licenses/>. * * $Id$ */ package de.dal33t.powerfolder.util; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Map.Entry; import java.util.MissingResourceException; import java.util.ResourceBundle; import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Level; import java.util.logging.Logger; import java.util.prefs.Preferences; /** * Basic class which provides accessor to tranlation files * * @author <a href="mailto:totmacher@powerfolder.com">Christian Sprajc </a> * @version $Revision: 1.13 $ */ public class Translation { private static final Logger log = Logger.getLogger(Translation.class .getName()); // Useful locales, which are not already included in Locale public static final Locale DUTCH = new Locale("nl"); public static final Locale SPANISH = new Locale("es"); public static final Locale RUSSIAN = new Locale("ru"); public static final Locale SWEDISH = new Locale("sv"); public static final Locale ARABIC = new Locale("ar"); public static final Locale POLISH = new Locale("pl"); public static final Locale PORTUGUESE = new Locale("pt"); public static final Locale HUNGARIAN = new Locale("hu"); public static final Locale TURKISCH = new Locale("tr"); /** List of all supported locales */ private static List<Locale> supportedLocales; private static Map<String, String> placeHolders = new ConcurrentHashMap<String, String>(); static { setPlaceHolder("APPNAME", "PowerFolder"); setPlaceHolder("APPDESCRIPTION", "Sync your World"); } // The resource bundle, initalized lazy private static ResourceBundle resourceBundle; /** * */ private Translation() { super(); } /** * @return the supported locales by PowerFolder */ public static synchronized List<Locale> getSupportedLocales() { if (supportedLocales == null) { supportedLocales = new ArrayList<Locale>(); supportedLocales.add(Locale.ENGLISH); // supportedLocales.add(Locale.UK); supportedLocales.add(Locale.GERMAN); supportedLocales.add(DUTCH); // supportedLocales.add(Locale.JAPANESE); supportedLocales.add(Locale.ITALIAN); supportedLocales.add(SPANISH); // supportedLocales.add(RUSSIAN); supportedLocales.add(Locale.FRENCH); // supportedLocales.add(Locale.CHINESE); // supportedLocales.add(SWEDISH); // supportedLocales.add(ARABIC); // supportedLocales.add(POLISH); // supportedLocales.add(PORTUGUESE); // supportedLocales.add(HUNGARIAN); // Not yet supported: // supportedLocales.add(TURKISCH); } Collections.sort(supportedLocales, LocaleComparator.INSTANCE); return Collections.unmodifiableList(supportedLocales); } /** * Adds a new locale to the list of supported locales. For adding a new * language dynamically. * * @param locale */ public static synchronized void addSupportedLocales(Locale locale) { Reject.ifNull(locale, "Locale"); if (!getSupportedLocales().contains(locale)) { supportedLocales.add(locale); } else { log.warning("Not adding locale. Already supported: " + locale); } } /** * @return the currently active locale of the used resource bundle */ public static Locale getActiveLocale() { Locale locale = getResourceBundle().getLocale(); if (locale == null || StringUtils.isEmpty(locale.getLanguage())) { // Workaround for english return Locale.ENGLISH; } return getResourceBundle().getLocale(); } /** * Saves/Overrides the locale setting. Next time the resource bundle is * initalized, it tries to gain bundle with that locale. Otherwise fallback * to default locale * * @param locale * the locale, or null to reset */ public static void saveLocalSetting(Locale locale) { if (locale != null) { if (locale.getCountry().length() == 0) { Preferences.userNodeForPackage(Translation.class).put("locale", locale.getLanguage()); } else { Preferences.userNodeForPackage(Translation.class).put("locale", locale.getLanguage() + '_' + locale.getCountry()); } } else { Preferences.userNodeForPackage(Translation.class).remove("locale"); } } /** * Reset the resource bundle. Next call will return a freshly initalized RB */ public static void resetResourceBundle() { resourceBundle = null; } public static void setResourceBundle(ResourceBundle newResourceBundle) { resourceBundle = newResourceBundle; } /** * @return the currently active resource bundle */ public static synchronized ResourceBundle getResourceBundle() { if (resourceBundle == null) { // Intalize bundle try { // Get language out of preferences String confLangStr = Preferences.userNodeForPackage( Translation.class).get("locale", null); Locale confLang = confLangStr != null ? new Locale(confLangStr) : null; // Take default locale if config is empty if (confLang == null) { confLang = Locale.getDefault(); } // Workaround for EN if (confLangStr != null) { if (confLangStr.equals("en_GB")) { confLang = Locale.UK; } else if (confLangStr.equals("en")) { // Normal (USA) English confLang = new Locale(""); } } resourceBundle = ResourceBundle.getBundle("Translation", confLang); log.info("Default Locale '" + Locale.getDefault() + "', using '" + resourceBundle.getLocale() + "', in config '" + confLang + '\''); } catch (MissingResourceException e) { log.log(Level.SEVERE, "Unable to load translation file", e); } } return resourceBundle; } /** * Returns translation for this id * * @param id * the id for the translation entry * @return the localized string */ public static String getTranslation(String id) { ResourceBundle rb = getResourceBundle(); if (rb == null) { return "- " + id + " -"; } try { String translation = rb.getString(id); // log.warning("Translation for '" + id + "': " + translation); if (translation.contains("{")) { for (Entry<String, String> placeHolderEntry : placeHolders .entrySet()) { if (translation.contains(placeHolderEntry.getKey())) { translation = translation.replace( placeHolderEntry.getKey(), placeHolderEntry.getValue()); } } } return translation; } catch (MissingResourceException e) { if (id != null && !id.startsWith("date_format.")) { // Only log non-date format errors. // Date format error may occur during logging, prevent // stackoverflow error. log.warning("Unable to find translation for ID '" + id + '\''); log.log(Level.FINER, "MissingResourceException", e); } return "- " + id + " -"; } } /** * Returns a paramterized translation for this id. * <p> * Use <code>{0}</code> <code>{1}</code> etc as placeholders in property * files * * @param id * @param params * the parameters to be included. * @return a paramterized translation for this id. */ public static String getTranslation(String id, String... params) { String translation = getTranslation(id); int paramCount = 0; for (String param : params) { int i; String paramSymbol = "{" + paramCount++ + '}'; while ((i = translation.indexOf(paramSymbol)) >= 0) { translation = translation.substring(0, i) + param + translation.substring(i + 3, translation.length()); } } return translation; } public static void setPlaceHolder(String id, String text) { if (text == null) { placeHolders.remove('{' + id + '}'); } else { placeHolders.put('{' + id + '}', text); } } private static final class LocaleComparator implements Comparator<Locale> { private static LocaleComparator INSTANCE = new LocaleComparator(); public int compare(Locale o1, Locale o2) { return o1.getDisplayName(o1).compareTo(o2.getDisplayName(o2)); } } }