All Downloads are FREE. Search and download functionalities are using the official Maven repository.

edu.mines.jtk.util.Localize Maven / Gradle / Ivy

There is a newer version: 1.1.0
Show newest version
/****************************************************************************
Copyright 2003, Landmark Graphics and others.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
 ****************************************************************************/
package edu.mines.jtk.util;

import java.util.*;
import java.util.logging.Logger;
import java.util.regex.*;

/**
 * Localize messages for end users, using a Formatter pattern and a
 * localized resource bundle.
 *
 * In a class like MyPanel.java you might have lines like this:
 * 
 * double value = 3.14;
 * String msg = "The value "+value+" is too large";
 * 
* Instead, in the same package as MyPanel.java, create a file * MyPanel.properties, with this line: *
 * too_large = The value %g is too large.
 * 
* Then you can replace the original lines by this. *
 * private static Localize local = new Localize(MyPanel.class);
 * ...
 *
 * double value = 3.14;
 * String msg = local.format("too_large", value);
 * 
* * If you create an additional file called MyPanel_es.properties, then * that file will be used automatically in Spanish-speaking locales. * * @author W.S. Harlan, Landmark Graphics */ public class Localize { private static final Logger LOG = Logger.getLogger(Localize.class.getName()); private static final Pattern s_tokens = Pattern.compile("[$][{](.+?)[}]"); private static final Map s_rb = new HashMap(); private final ResourceBundle resourceBundle; private final Locale locale; private final Class clazz; private final String resourceBundleName; /** * Construct for localized messages. * * @param clazz Name of client class that requires localization * Class<Foo> is assumed to have property files Foo.properties, * Foo_es.properties, etc. Uses default Locale. */ public Localize(final Class clazz) { this(clazz, null); } /** * Construct for localized messages. * * @param clazz Name of client class that requires localization * @param resourceBundleName Name of ResourceBundle to be used for * localizing messages. If null, then Class<Foo> is assumed to have * property files Foo.properties, Foo_es.properties, etc. Uses default * Locale. */ public Localize(final Class clazz, final String resourceBundleName) { this(clazz, resourceBundleName, null); } /** * Construct for localized messages. * * @param clazz Name of client class that requires localization * @param resourceBundleName Name of ResourceBundle to be used for * localizing messages. If null, then Class<Foo> is assumed to have * property files Foo.properties, Foo_es.properties, etc. * @param locale Locale to use for localization. If null, then will use * default Locale. */ public Localize(final Class clazz, final String resourceBundleName, final Locale locale) { this.clazz = clazz; this.resourceBundleName = resourceBundleName; resourceBundle = getResourceBundle(clazz, resourceBundleName, locale); this.locale = locale; } /** * Format a localized message, with java.util.Formatter and the appropriate * resource. * * @param key used to specify format string in properties file. If not * found, then will be used as the format. * @param args Optional arguments to be passed to Formatter.format method. * @return formatted localized String */ public String format(final String key, final Object... args) { if (key == null) { return null; } String format; try { if (resourceBundle != null) { format = resourceBundle.getString(key); } else { format = key; } } catch (final MissingResourceException mre) { format = key; } final Formatter formatter = new Formatter(locale); String s = formatter.format(format, args).out().toString().trim(); formatter.close(); return s; } /** * Get a resource bundle associated with a class. * * @param clazz Name of client class that requires resource bundle. * @param resourceBundleName Name of ResourceBundle to be used for * localizing messages. If null, then Class<Foo> is assumed to have * property files Foo.properties, Foo_es.properties, etc. * @param locale Locale to use for localization. If null, then will use * default Locale. * @return ResourceBundle for this locale. */ public static ResourceBundle getResourceBundle(final Class clazz, String resourceBundleName, Locale locale) { if (locale == null) { locale = Locale.getDefault(); } final String key = clazz.getName() + ";" + resourceBundleName + ";" + locale.toString(); synchronized (s_rb) { ResourceBundle resourceBundle = s_rb.get(key); if (resourceBundle == null) { if (resourceBundleName == null) { String cn = clazz.getName(); if (cn == null) { final Class c2 = clazz.getEnclosingClass(); if (c2 != null) { cn = c2.getName(); } } if (cn == null) { throw new IllegalArgumentException("Specify top-level class. " + "This class does not have a canonical name: " + clazz.getName()); } resourceBundleName = cn; } else { resourceBundleName = clazz.getPackage().getName() + "." + resourceBundleName; } try { // see if throws MissingResourceException resourceBundle = ResourceBundle.getBundle(resourceBundleName, locale, clazz.getClassLoader()); s_rb.put(key, resourceBundle); } catch (final MissingResourceException e) { // No resource file provided. Plan to return null. } } return s_rb.get(key); } } /** * Get the best localized message from a Throwable that may contain other Throwables as a cause. * * @param throwable a Throwable that may contain other Throwables as a cause. * @return best localized message, unwrapping as necessary. */ public static String getMessage(final Throwable throwable) { if (throwable.getCause() == null) { final String localizedMessage = throwable.getLocalizedMessage(); if (localizedMessage != null) { return localizedMessage; } final String message = throwable.getMessage(); if (message != null) { return message; } return throwable.toString(); } final String causeToString = throwable.getCause().toString(); final String localized = throwable.getLocalizedMessage(); if (localized == null || localized.equals(causeToString)) { return getMessage(throwable.getCause()); } return localized; } @Override public String toString() { return "Localize{" + ", locale=" + locale + ", clazz=" + clazz + ", resourceBundleName='" + resourceBundleName + '\'' + '}'; } /** Filter the specified string with the specified resource bundle. First the entire string is filtered, then substrings delimited as ${key} are filtered. @param message Filter this string @param catalog Get keys and values from this. @return Filtered string. */ public static String filter(String message, ResourceBundle catalog) { if (catalog == null) return message; // see if entire string is a key try { message = catalog.getString(message); } catch (MissingResourceException ex) {/*no substitution*/} // see if substrings are keys Matcher matcher = s_tokens.matcher(message); int numberMatches = 0; while (matcher.find()) {++numberMatches;} // substitute from end backwards for (int match=numberMatches; match>0; --match) { matcher.reset(); for (int i=0; i resourceClass) { ClassLoader cl = resourceClass.getClassLoader(); if (cl == null) { LOG.warning("Could not get ClassLoader from "+resourceClass.getName()); cl = ClassLoader.getSystemClassLoader(); } Locale currentLocale = Locale.getDefault(); String name = resourceClass.getName(); ResourceBundle catalog = ResourceBundle.getBundle(name, currentLocale, cl); if (catalog == null) { LOG.warning("Could not get ResourceBundle "+name+" for "+ currentLocale+" from "+cl); } return filter(message, catalog); } /** Convert a number of seconds into words @param seconds Number of seconds @return Localized words describing the number of seconds. */ public static String timeWords(long seconds) { if (seconds == 0) { return filter("0 ${seconds}", Localize.class); } String result = ""; long minutes = seconds/60; long hours = minutes/60; long days = hours/24; seconds %= 60; minutes %= 60; hours %= 24; if (days >= 10) { if (hours >=12) ++days; hours = minutes = seconds = 0; } else if (hours >= 10 || days > 0) { if (minutes >=30) { ++hours; days += hours/24; hours %= 24; } minutes = seconds = 0; } else if (minutes >= 10 || hours > 0) { if (seconds >=30) { ++minutes; hours += minutes/60; minutes %= 60; } seconds = 0; } if (seconds != 0) result = " " + seconds + " ${second"+ ((seconds>1)?"s}":"}") + result; if (minutes != 0) result = " " + minutes + " ${minute"+ ((minutes>1)?"s}":"}") + result; if (hours != 0) result = " " + hours + " ${hour" + ((hours>1)?"s}":"}") + result; if (days != 0) result = " " + days + " ${day" + ((days>1)?"s}":"}") + result; return filter(result.trim(), Localize.class); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy