/*
// 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