/* * jMemorize - Learning made easy (and fun) - A Leitner flashcards tool * Copyright(C) 2004-2008 Riad Djemili and contributors * * This program 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 1, 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, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ package jmemorize.gui; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.text.DateFormat; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import jmemorize.core.Main; import jmemorize.core.Settings; /** * This class is used to query language/locale related strings and date * formatters. * * @author djemili */ public class Localization { static { Locale.setDefault(Settings.loadLocale()); } public static final DateFormat SHORT_DATE_FORMATER = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT); public static final DateFormat LONG_DATE_FORMATER = DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.MEDIUM); public static final DateFormat SHORT_TIME_FORMATER = DateFormat.getTimeInstance(DateFormat.SHORT); // just hours:minutes private static final String RESOURCE_FORMAT = "/resource/text/translation_{0}.properties"; private static final String LANGS_FILE = "/resource/text/langs.txt"; private static Map<?, ?> m_defaultBundle = getBundleOrNull(Locale.getDefault()); private static Map<? ,?> m_fallbackBundle = getBundleOrNull(Locale.ENGLISH); /** * Return the string translation that belongs to the key. */ public static String get(String key) { if (m_defaultBundle != null) { String val = (String)m_defaultBundle.get(key); if (val != null) return val; } if (m_fallbackBundle != null) { String val = (String)m_fallbackBundle.get(key); return val != null ? val : '!' + key + '!'; } return '#' + key + '#'; } /** * @return the string associated with key in the default or child bundle or * an empty string if no such string available. */ public static String getEmpty(String key) { if (m_defaultBundle != null) { String val = (String)m_defaultBundle.get(key); return val != null ? val : ""; } return '#' + key + '#'; } /** * @return the string associated with given key1 or the string assoiated * with given key2 if no string is associated with key1 in the sub bundle or * the string associated with given key in the default bundle or a debug * string when no string is available for any of the two given keys. */ public static String get(String key, String alternateKey) { if (m_defaultBundle != null) { String val = (String)m_defaultBundle.get(key); if (val != null) return val; val = (String)m_defaultBundle.get(alternateKey); if (val != null) return val; } if (m_fallbackBundle != null) { String val = (String)m_fallbackBundle.get(key); return val != null ? val : '!' + key + '!'; } return '#' + key + '#'; } public static void setBundles(Map defaultBundle, Map fallbackBundle) { m_fallbackBundle = fallbackBundle; m_defaultBundle = defaultBundle; } /** * The list of available languages is stored in the file * <tt>/resource/text/langs.txt</tt>. Every line holds a string that * represents the language (and optionally the country) code. * * @return A list of all available locales/translations. */ public static List<Locale> getAvailableLocales() { List<Locale> locales = new ArrayList<Locale>(); BufferedReader in = null; try { // load available locales from file in = new BufferedReader(new InputStreamReader( Localization.class.getResourceAsStream(LANGS_FILE))); Pattern p = Pattern.compile("([a-z]{2})(?:_([A-Z]{2,3}))?"); //$NON-NLS-1$ String line; while ((line = in.readLine()) != null) { Matcher m = p.matcher(line); if (m.matches()) { String language = m.group(1); String country = m.group(2); locales.add(country != null ? new Locale(language, country) : new Locale(language)); } } // sort locales by display language Collections.sort(locales, new Comparator<Locale>() { public int compare(Locale l1, Locale l2) { String ls1 = l1.getDisplayLanguage(); String ls2 = l2.getDisplayLanguage(); return ls1.compareTo(ls2); } }); } catch (IOException e) { Main.logThrowable("failed loading available locales", e); //$NON-NLS-1$ } finally { try { if (in != null) in.close (); } catch (IOException e) { Main.logThrowable("failed loading available locales", e); //$NON-NLS-1$ } } return locales; } /** * Compares the machines default locale with all available translations. If * the default locale is available as translation the machines locale is * returned. Otherwise the english language locale is returned as default. */ public static Locale getDefaultLocale() { Locale defaultLocale = Locale.getDefault(); for (Locale locale : getAvailableLocales()) { if (defaultLocale.getLanguage().equals(locale.getLanguage())) { return locale; } } return Locale.ENGLISH; } public static void main(String[] args) { Map<?, ?> defaultBundle = getBundleOrNull(Locale.ENGLISH); List<Locale> locales = getAvailableLocales(); for (Locale locale : locales) { Map<?, ?> bundle = getBundleOrNull(locale); Set<?> bundleKeys = bundle.keySet(); List defaultKeys = new ArrayList(defaultBundle.keySet()); defaultKeys.removeAll(bundleKeys); Collections.sort(defaultKeys); System.out.print("Locale: "+locale.getLanguage()+ " --> "); if (defaultKeys.isEmpty()) { System.out.println("OK"); } else { System.out.println(defaultKeys.size() + " missing Keys"); for (Iterator it2 = defaultKeys.iterator(); it2.hasNext();) { String key = (String)it2.next(); System.out.println(key + " = " + defaultBundle.get(key)); } System.out.println(); } System.out.println(); } } /** * Tries to load ResourceBundle from given baseName. * * @param baseName the name of the bundle to load. * @return the ResourceBundle if found. <code>null</code> otherwise. */ private static Properties getBundleOrNull(Locale locale) { try { Object[] args = new Object[]{locale.getLanguage()}; String path = MessageFormat.format(RESOURCE_FORMAT, args); Properties properties = new Properties(); properties.load(Localization.class.getResourceAsStream(path)); return properties; } catch (IOException e) { return null; } } private Localization() // should not be called { } }