/*
* The Unified Mapping Platform (JUMP) is an extensible, interactive GUI
* for visualizing and manipulating spatial features with geometry and attributes.
*
* Copyright (C) 2003 Vivid Solutions
*
* 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 2
* of the License, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* For more information, contact:
*
* Vivid Solutions
* Suite #1A
* 2328 Government Street
* Victoria BC V8T 5G5
* Canada
*
* (250)385-6040
* www.vividsolutions.com
*/
package com.vividsolutions.jump;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Locale;
import com.vividsolutions.jump.workbench.JUMPWorkbench;
import org.apache.log4j.Logger;
/**
* Singleton for the Internationalization (I18N)
*
* <pre>
* [1] HOWTO TRANSLATE JUMP IN MY OWN LANGUAGE
* Copy theses files and add the locales extension for your language and country instead of the *.
* - resources/jump_*.properties
* - com/vividsolutions/jump/workbench/ui/plugin/KeyboardPlugIn_*.html
* [2] HOWTO TRANSLATE MY PLUGIN AND GIVE THE ABILITY TO TRANSLATE IT
* Use theses methods to use your own *.properties files :
* [Michael Michaud 2007-03-23] the 3 following methods have been deactivated
* com.vividsolutions.jump.I18N#setPlugInRessource(String, String)
* com.vividsolutions.jump.I18N#get(String, String)
* com.vividsolutions.jump.I18N#getMessage(String, String, Object[])
* you still can use plugInsResourceBundle (as in Pirol's plugin)
*
* And use jump standard menus
* </pre>
*
* Code example : [Michael Michaud 2007-03-23 : the following code example is no
* more valid and has to be changed]
*
* <pre>
* public class PrintPlugIn extends AbstractPlugIn
* {
* private String name = "print";
* public void initialize(PlugInContext context) throws Exception
* {
* I18N.setPlugInRessource(name, "org.agil.core.jump.plugin.print");
* context.getFeatureInstaller().addMainMenuItem(this,
* new String[]
* {MenuNames.TOOLS,I18N.get(name, "print")},
* I18N.get(name, "print"), false, null, null);
* }
* ...
* </pre>
*
* <pre>
* TODO :I18N (1) Improve translations
* TODO :I18N (2) Separate config (customization) and I18N
* TODO :I18N (3) Explore and discuss about I18N integration and Jakarta Common Ressources
* (using it as a ressource interface)
* </pre>
*
* @author Basile Chandesris - <chandesris@pt-consulting.lu>
* @see com.vividsolutions.jump.workbench.ui.MenuNames
* @see com.vividsolutions.jump.workbench.ui.VTextIcon text rotation
*/
public final class I18N {
private static final Logger LOG = Logger.getLogger(I18N.class);
// [Michael Michaud 2007-03-23] removed SingletonHolder internal class
// 1 - getInstance is enough to guarantee I18N instance unicity
// 2 - I18N should not be instanciated as the class has only static methods
private static final I18N instance = new I18N();
// use 'jump<locale>.properties' i18n mapping file
// STanner changed the place where are stored bundles. Now are in /language
// public static ResourceBundle rb =
// ResourceBundle.getBundle("com.vividsolutions.jump.jump");
public static ResourceBundle rb = ResourceBundle.getBundle("language/jump");
// [Michael Michaud 2007-03-23] plugInsResourceBundle is deactivated because
// all the methods
// using it have been deactivated.
// [sstein] activated again since Pirol does use it
public static Hashtable plugInsResourceBundle = new Hashtable();
/** The map from category names to I18N instances. */
private static Map<String, I18N> instances = new HashMap<String, I18N>();
private static ClassLoader classLoader;
/** The resource bundle for the I18N instance. */
private ResourceBundle resourceBundle;
/** The core OpenJUMP I18N instance. */
private I18N() {
resourceBundle = rb;
}
/**
* Construct an I18N instance for the category.
*
* @param resourcePath The path to the language files.
*/
private I18N(final String resourcePath) {
resourceBundle = ResourceBundle.getBundle(resourcePath,
Locale.getDefault(), classLoader);
}
/**
* Set the class loader used to load resource bundles, must only be called by
* the plug-in loader.
*
* @param classLoader the classLoader to set
*/
public static void setClassLoader(ClassLoader classLoader) {
I18N.classLoader = classLoader;
}
/**
* Get the I18N text from the language file associated with this instance. If
* no label is defined then a default string is created from the last part of
* the key.
*
* @param key The key of the text in the language file.
* @return The I18Nized text.
*/
public String getText(final String key) {
try {
return resourceBundle.getString(key);
} catch (java.util.MissingResourceException e) {
String[] labelpath = key.split("\\.");
LOG.debug("No resource bundle or no translation found for the key : "
+ key);
return labelpath[labelpath.length - 1];
}
}
/**
* Get the I18N text from the language file associated with the specified
* category. If no label is defined then a default string is created from the
* last part of the key.
*
* @param category The category.
* @param key The key of the text in the language file.
* @return The I18Nized text.
*/
public static String getText(final String category, final String key) {
I18N i18n = getInstance(category);
return i18n.getText(key);
}
/**
* Get the I18N instance for the category. A resource file must exist in the
* resource path for language/jump for the category.
*
* @param category The category.
* @return The instance.
*/
public static I18N getInstance(final String category) {
I18N instance = instances.get(category);
if (instance == null) {
String resourcePath = category.replace('.', '/') + "/language/jump";
instance = new I18N(resourcePath);
instances.put(category, instance);
}
return instance;
}
public static I18N getInstance() {
// [Michael Michaud 2007-03-04] guarantee I18N instance unicity without
// creating a SingletonHolder inner class instance
return (instance == null) ? new I18N() : instance;
// return SingletonHolder._singleton;
}
/**
* Load file specified in command line (-i18n lang_country) (lang_country
* :language 2 letters + "_" + country 2 letters) Tries first to extract lang
* and country, and if only lang is specified, loads the corresponding
* resource bundle.
*
* @param langcountry
*/
public static void loadFile(final String langcountry) {
// [Michael Michaud 2007-03-04] handle the case where lang is the only
// variable instead of catching an ArrayIndexOutOfBoundsException
String[] lc = langcountry.split("_");
Locale locale = Locale.getDefault();
if (lc.length > 1) {
LOG.debug("lang:" + lc[0] + " " + "country:" + lc[1]);
locale = new Locale(lc[0], lc[1]);
} else if (lc.length > 0) {
LOG.debug("lang:" + lc[0]);
locale = new Locale(lc[0]);
} else {
LOG.debug(langcountry
+ " is an illegal argument to define lang [and country]");
}
rb = ResourceBundle.getBundle("language/jump", locale);
}
/**
* Process text with the locale 'jump_<locale>.properties' file
*
* @param label
* @return i18n label [Michael Michaud 2007-03-23] If no resourcebundle is
* found, returns a default string which is the last part of the label
*/
public static String get(final String label) {
try {
return rb.getString(label);
} catch (java.util.MissingResourceException e) {
String[] labelpath = label.split("\\.");
LOG.debug("No resource bundle or no translation found for the key : "
+ label);
return labelpath[labelpath.length - 1];
}
}
/**
* Get the short signature for locale (letters extension :language 2 letters +
* "_" + country 2 letters)
*
* @return string signature for locale
*/
public static String getLocale() {
return rb.getLocale().getLanguage() + "_" + rb.getLocale().getCountry();
}
/**
* Get the short signature for language (letters extension :language 2
* letters)
*
* @return string signature for language
*/
public static String getLanguage() {
if (JUMPWorkbench.I18N_SETLOCALE == "") {
// No locale has been specified at startup: choose default locale
return rb.getLocale().getLanguage();
} else {
return JUMPWorkbench.I18N_SETLOCALE.split("_")[0];
}
}
/**
* Process text with the locale 'jump_<locale>.properties' file If no
* resourcebundle is found, returns default string contained inside
* com.vividsolutions.jump.jump
*
* @param label with argument insertion : {0}
* @param objects
* @return i18n label
*/
public static String getMessage(final String label, final Object[] objects) {
try {
final MessageFormat mformat = new MessageFormat(rb.getString(label));
return mformat.format(objects);
} catch (java.util.MissingResourceException e) {
final String[] labelpath = label.split("\\.");
LOG.warn(e.getMessage() + " no default value, the resource key is used: "
+ labelpath[labelpath.length - 1]);
final MessageFormat mformat = new MessageFormat(
labelpath[labelpath.length - 1]);
return mformat.format(objects);
}
}
/**
* Get the I18N text from the language file associated with the specified
* category. If no label is defined then a default string is created from the
* last part of the key.
*
* @param category The category.
* @param label with argument insertion : {0}
* @param objects
* @return i18n label
*/
public static String getMessage(final String category, final String label, final Object[] objects) {
I18N i18n = getInstance(category);
return i18n.getMessage(label,objects);
}
}