/* // This software is subject to the terms of the Eclipse Public License v1.0 // Agreement, available at the following URL: // http://www.eclipse.org/legal/epl-v10.html. // You must accept the terms of that agreement to use this software. // // Copyright (C) 2007-2007 JasperSoft // Copyright (C) 2008-2009 Pentaho // All Rights Reserved. */ package mondrian.gui; import org.apache.log4j.Logger; import java.io.File; import java.io.IOException; import java.net.JarURLConnection; import java.net.URL; import java.text.MessageFormat; import java.util.*; import java.util.jar.JarEntry; import java.util.jar.JarFile; public class I18n { private static final Logger LOGGER = Logger.getLogger(I18n.class); // Default to english private Locale currentLocale = Locale.ENGLISH; private ResourceBundle guiBundle = null; private ResourceBundle languageBundle = null; private static String defaultIcon = "nopic"; private static List<LanguageChangedListener> languageChangedListeners = new ArrayList<LanguageChangedListener>(); public static void addOnLanguageChangedListener( LanguageChangedListener listener) { languageChangedListeners.add(listener); } public I18n(ResourceBundle guiBundle, ResourceBundle languageBundle) { this.guiBundle = guiBundle; this.languageBundle = languageBundle; } public static List<Locale> getListOfAvailableLanguages(Class cl) { List<Locale> supportedLocales = new ArrayList<Locale>(); try { Set<String> names = getResourcesInPackage(cl, cl.getName()); for (String name : names) { // From // '../../<application>_en.properties' // or // '../../<application>_en_UK.properties' // To // 'en' OR 'en_UK_' OR even en_UK_Brighton dialect String lang = name.substring(name.lastIndexOf('/') + 1); // only accept resources with extension '.properties' if (lang.indexOf(".properties") < 0) { continue; } lang = lang.substring(0, lang.indexOf(".properties")); StringTokenizer tokenizer = new StringTokenizer(lang, "_"); if (tokenizer.countTokens() <= 1) { continue; } String language = ""; String country = ""; String variant = ""; int i = 0; while (tokenizer.hasMoreTokens()) { String token = tokenizer.nextToken(); switch (i) { case 0: //the word <application> break; case 1: language = token; break; case 2: country = token; break; case 3: variant = token; break; default: // } i++; } Locale model = new Locale(language, country, variant); supportedLocales.add(model); } } catch (Exception e) { LOGGER.error("getListOfAvailableLanguages", e); } // Sort the list. Probably should use the current locale when getting // the DisplayLanguage so the sort order is correct for the user. Collections.sort( supportedLocales, new Comparator<Object>() { public int compare(Object lhs, Object rhs) { String ls = ((Locale) lhs).getDisplayLanguage(); String rs = ((Locale) rhs).getDisplayLanguage(); // TODO: this is not very nice - We should introduce a // MyLocale if (ls.equals("pap")) { ls = "Papiamentu"; } if (rs.equals("pap")) { rs = "Papiamentu"; } return ls.compareTo(rs); } }); return supportedLocales; } /** * Enumerates the resouces in a give package name. * This works even if the resources are loaded from a jar file! * * <p/>Adapted from code by mikewse * on the java.sun.com message boards. * http://forum.java.sun.com/thread.jsp?forum=22&thread=30984 * * <p>The resulting set is deterministically ordered. * * @param coreClass Class for class loader to find the resources * @param packageName The package to enumerate * @return A Set of Strings for each resouce in the package. */ public static Set<String> getResourcesInPackage( Class coreClass, String packageName) throws IOException { String localPackageName; if (packageName.endsWith("/")) { localPackageName = packageName; } else { localPackageName = packageName + '/'; } ClassLoader cl = coreClass.getClassLoader(); Enumeration<URL> dirEnum = cl.getResources(localPackageName); Set<String> names = new LinkedHashSet<String>(); // deterministic while (dirEnum.hasMoreElements()) { URL resUrl = dirEnum.nextElement(); // Pointing to filesystem directory if (resUrl.getProtocol().equals("file")) { try { File dir = new File(resUrl.getFile()); File[] files = dir.listFiles(); if (files != null) { for (int i = 0; i < files.length; i++) { File file = files[i]; if (file.isDirectory()) { continue; } names.add(localPackageName + file.getName()); } } } catch (Exception ex) { ex.printStackTrace(); } // Pointing to Jar file } else if (resUrl.getProtocol().equals("jar")) { JarURLConnection jconn = (JarURLConnection) resUrl.openConnection(); JarFile jfile = jconn.getJarFile(); Enumeration entryEnum = jfile.entries(); while (entryEnum.hasMoreElements()) { JarEntry entry = (JarEntry) entryEnum.nextElement(); String entryName = entry.getName(); // Exclude our own directory if (entryName.equals(localPackageName)) { continue; } String parentDirName = entryName.substring(0, entryName.lastIndexOf('/') + 1); if (!parentDirName.equals(localPackageName)) { continue; } names.add(entryName); } } else { // Invalid classpath entry } } return names; } public void setCurrentLocale(String language) { setCurrentLocale(language, null); } public void setCurrentLocale(String language, String country) { if (language != null && !language.equals("")) { if (country != null && !country.equals("")) { setCurrentLocale(new Locale(language, country)); } else { setCurrentLocale(new Locale(language)); } } else { setCurrentLocale(Locale.getDefault()); } } public void setCurrentLocale(Locale locale) { currentLocale = locale; languageBundle = null; for (LanguageChangedListener listener : languageChangedListeners) { try { listener.languageChanged(new LanguageChangedEvent(locale)); } catch (Exception ex) { LOGGER.error("setCurrentLocale", ex); } } } public Locale getCurrentLocale() { if (currentLocale == null) { currentLocale = Locale.getDefault(); } return currentLocale; } public String getGUIReference(String reference) { try { if (guiBundle == null) { throw new Exception("No GUI bundle"); } return guiBundle.getString(reference); } catch (MissingResourceException ex) { LOGGER.error( "Can't find the translation for key = " + reference, ex); throw ex; } catch (Exception ex) { LOGGER.error("Exception loading reference = " + reference, ex); return guiBundle.getString(defaultIcon); } } /** * Retreives a resource string using the current locale. * * @param stringId The resource string identifier * @return The locale specific string */ public String getString(String stringId) { return getString(stringId, getCurrentLocale()); } /** * Retreives a resource string using the current locale, with a default. * * @param stringId The resource string identifier * @param defaultValue If no resource for the stringID is specified, use * this default value * @return The locale specific string */ public String getString(String stringId, String defaultValue) { return getString(stringId, getCurrentLocale(), defaultValue); } /** * Retrieves a resource string using the current locale. * * @param stringId The resource string identifier * @param defaultValue The default value for the resource string * @param args arguments to be inserted into the resource string * @return The locale specific string */ public String getFormattedString( String stringId, String defaultValue, Object... args) { String pattern = getString(stringId, getCurrentLocale(), defaultValue); MessageFormat mf = new java.text.MessageFormat(pattern, getCurrentLocale()); return mf.format(args); } /** * Retreive a resource string using the given locale. The stringID is the * default. * * @param stringId The resource string identifier * @param currentLocale required Locale for resource * @return The locale specific string */ private String getString(String stringId, Locale currentLocale) { return getString(stringId, currentLocale, stringId); } /** * Retreive a resource string using the given locale. Use the default if * there is nothing for the given Locale. * * @param stringId The resource string identifier * @param currentLocale required Locale for resource * @param defaultValue The default value for the resource string * @return The locale specific string */ public String getString( String stringId, Locale currentLocale, String defaultValue) { try { if (languageBundle == null) { throw new Exception("No language bundle"); } return languageBundle.getString(stringId); } catch (MissingResourceException ex) { LOGGER.error( "Can't find the translation for key = " + stringId + ": using default (" + defaultValue + ")", ex); } catch (Exception ex) { LOGGER.error("Exception loading stringID = " + stringId, ex); } return defaultValue; } public static String getCurrentLocaleID() { return ""; } } // End I18n.java