package com.idega.core.ldap.client.cbutil;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Locale;
import java.util.MissingResourceException;
/**
* This 'International Text' static class acts as a central source of all localised
* strings. If it cannot find a localised properties file, the
* default (english) file is used. If that file can not be found, the key used to
* look up the translation is returned unchanged - hence it is useful if the keys
* are meaningful in their own right (i.e. use 'File' rather than 'String 42' as
* a key).<p>
*
* Currently the class is static to provide easy access to i18n text by
* all classes and plugins, and because it is difficult to see how
* supporting multiple different-locale languages would be helpful (note
* that multiple languages can be supported simply by using unicode).
*/
public class CBIntText
{
static Locale locale = null;
static Hashtable translations;
private static boolean errorGiven = false; // This is a 'complain once' class - usually it's either working or it's not...
/*
* If the local language is english, don't print warning messages
* about missing translation files (it confuses soooo many people)
*/
private static boolean english = true;
/**
* This initialises the international text class.
* @param bundleLocation the name of the i18n bundle (e.g. "language/JX_ja.properties").
* @param customLoader a custom class loader (may be null). JX uses a custom loader
* that auto-detects unicode and utf-8 files for ease of configuration by
* non-expert users.
*
*/
public static void init(String bundleLocation, ClassLoader customLoader)
{
locale = Locale.getDefault();
Locale def = Locale.getDefault();
CBUtility.log( "Default Locale is: "+ def.getDisplayName(), 1);
CBUtility.log("Using Locale: "+locale.getDisplayName() + " for " + locale.getDisplayCountry(), 4);
CBUtility.log("language, localized for default locale is: " + def.getDisplayLanguage( locale ), 4);
CBUtility.log("country name, localized for default locale: " + def.getDisplayCountry( locale ), 4);
CBUtility.log("Default language, localized for your locale is: " + locale.getDisplayLanguage( def ), 4);
CBUtility.log("Default country name, localized for your locale is: " + locale.getDisplayCountry( def ), 4);
translations = new Hashtable(500);
addBundle(bundleLocation, customLoader);
if (!def.getLanguage().equals("en")) {
english = false;
}
}
/**
* Once init() has been called, this method can be used to add
* multiple resource bundles to the universal 'CBIntText' list of
* translations. Note that clashes (i.e. translations of identical
* terms) are resolved with the earliest registered bundle having
* priority. (i.e. if both JX and a plugin have a translation for
* 'file', the JX one will be used). If this is a problem, remember
* that the translated string is arbitrary - e.g. a plugin could
* translate the string 'pluginFile' instead.
*/
public static void addBundle(String bundleLocation, ClassLoader customLoader)
{
CBUtility.log("adding resource bundle: " + bundleLocation + " using loader: " + customLoader.toString(), 4);
int startSize = translations.size();
if (locale == null)
{
CBUtility.log(" ERROR: - CBIntText.addBundle() has been called before CBIntText was initialised! - ignoring call.");
return;
}
try
{
// CBResourceBundle bundle = new CBResourceBundle( bundleLocation, locale, customLoader);
CBResourceBundle bundle = new CBResourceBundle( bundleLocation, locale);
String name = bundle.getString("name");
CBUtility.log(" added language localizaton set: " + ((name==null)?"(not named)":name), 1);
// Copy the new resource set into the hashtable, unless
// a value already exists in the hashtable... (earlier values have precedence).
Enumeration keys = bundle.getKeys();
while (keys.hasMoreElements())
{
Object key = keys.nextElement();
boolean debug = (CBUtility.getLogDebugLevel() >= 8);
if (translations.containsKey(key) == false)
{
if (debug) {
CBUtility.log("adding key: " + key + " trans: " + bundle.getString((String)key));
}
translations.put(key, bundle.getString((String)key));
}
}
}
catch ( MissingResourceException e)
{
CBUtility.log("unable to load resource bundle for " + locale.getDisplayLanguage( locale ) + " in country " + locale.getDisplayCountry( locale ), 1);
}
finally
{
if (startSize < translations.size()) // i.e. we added stuff...
{
CBUtility.log(" locale language is " + locale.getDisplayLanguage( locale ) + " in country " + locale.getDisplayCountry( locale ), 1);
}
else
{
CBUtility.log("Unable to load language resource bundle (couldn't even find default 'JX.properties' file)!", 1);
}
}
}
/**
* This attempts to get the localised version of a string.
* If anything goes wrong, it attempts to return the key
* string it was given - hence using a meaningfull key is
* a good harm minimization strategy.
*/
public static String get(String key)
{
if (key == null) // sanity check that a valid key has been passed.
{
return "null key";
}
if (translations==null || translations.size() == 0) // we never opened a bundle...
{
if (errorGiven == false) // only print error message once! (otherwise we'd print an
{ // error for every string in the program!)
if (!english) {
CBUtility.log("Unable to translate (" + key + ") - can't find language resource bundle.");
}
errorGiven = true;
}
return key; // try to keep on trucking using the (english) key phrase
}
//String ret = null;
try
{
String val = (String)translations.get(key); // return the translated word!
if (val == null) // this shouldn't happen, but can occur with an out-of-date (=incomplete) translation file.
{
if (!english) {
CBUtility.log("Can't find translation for (" + key + ") - returning unchanged.",3);
}
return key;
}
return val;
}
catch (MissingResourceException e)
{
return key; // couldn't find a translation, so return the keyword instead.
}
}
}