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

org.nuiton.i18n.I18n Maven / Gradle / Ivy

There is a newer version: 4.2
Show newest version
/*
 * #%L
 * I18n :: Api
 * 
 * $Id$
 * $HeadURL$
 * %%
 * Copyright (C) 2004 - 2010 CodeLutin
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as 
 * published by the Free Software Foundation, either version 3 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 Lesser Public License for more details.
 * 
 * You should have received a copy of the GNU General Lesser Public 
 * License along with this program.  If not, see
 * .
 * #L%
 */

package org.nuiton.i18n;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.nuiton.i18n.format.I18nMessageFormatter;
import org.nuiton.i18n.init.ClassPathI18nInitializer;
import org.nuiton.i18n.init.DefaultI18nInitializer;
import org.nuiton.i18n.init.I18nInitializer;

import java.util.Arrays;
import java.util.Locale;

/**
 * New generation I18n class.
 *
 * Note: This class replace the previous one in project {@code
 * nuiton-utils}.
 *
 * This class is a facility for internationalization. To use it in your soft,
 * you can either : 
  • import the org.nuiton.i18n.I18n class,
  • init * the translation support with the init(String language) or init(String * language, String country), init(Localelocale) static methods in your main, ( * eg: I18n.init("fr","FR") )
  • call the translate static method for each * sentence, ( eg: I18n.l("hello you !") )
  • create a resource file for each * language following the naming convention given in the * java.util.ResourceBundle javadoc and translate all the sentence.
* * @author Tony Chemit - [email protected] * @since 1.1 */ public class I18n { /** Logger. */ private static final Log log = LogFactory.getLog(I18n.class); /** * I18n initializer, * * @deprecated since 2.1, will be removed in version 3.0, in stead use the * method {@link I18n#init(I18nInitializer, Locale)} which * will pass directly the initializer to the store. */ @Deprecated protected static I18nInitializer initializer; /** I18n store of languages */ protected static I18nStore store; /** Filtre a appliquer avant de retourner les chaines */ protected static I18nFilter filter; /** * Formatter to apply on each translation. * * This formatter can not be configured directly here, but must be setted * into the {@code initializer} used to configure the I18n system. * * @see I18nInitializer#setMessageFormatter(I18nMessageFormatter) * @since 2.4 */ protected static I18nMessageFormatter messageFormatter; /** * Change le filtre des chaines traduites * * @param filter l'objet filtre a utiliser */ public static void setFilter(I18nFilter filter) { I18n.filter = filter; } /** * Initialize I18n system. * * The {@code initializer} can be null, in that case it will use the default * implementation of it given by the method {@link I18n#getDefaultInitializer()}. * * The {@code locale} can also be null, and in that case we will use the * default locale of the system given by the method * {@link Locale#getDefault()}. * * We strongly recommand not to use the default initializer, * since this one scanq all the class-path to detects i18n files and can * NOT garantee the order of loading such files. * * Prefer use at least the {@link DefaultI18nInitializer} instead. * * In version 3.0, we will try to make the {@link DefaultI18nInitializer} the * default initializer using a convention over i18n files names. * * @param initializer the initializer to use to detect bundles * @param locale the default locale to use * @since 2.1 */ public static void init(I18nInitializer initializer, Locale locale) { if (initializer == null) { // get a default initializer initializer = getDefaultInitializer(); } if (locale == null) { // use default locale locale = I18nUtil.newLocale(null, null); } initStore(initializer, locale); } public static void reload() { checkInit(); // get back initializer I18nInitializer initializer = store.getResolver(); // get back default locale Locale locale = store.getCurrentLocale(); // close the current store close(); // reload store init(initializer, locale); } /** * Sets the default locale used by I18n for the method * {@link I18n#t(String, Object...)}. * * * As a side effect, it will also set this locale is the default locale in * the system (says the method {@link Locale#getDefault()} will return the * given locale). * * Note : The I18n system must have been initialized by one of the * {@code init} method. * * @param locale the new default locale. * @since 2.1 */ public static void setDefaultLocale(Locale locale) { checkInit(); store.setCurrentLocale(locale); } /** * Obtain the default locale setted in I18n. This very locale is used in * translation when no locale information is given * (says in method {@link I18n#t(String, Object...)}. * * Note : The I18n system must have been initialized by one of the * {@code init} method. * * @return the default locale initialized in I18n */ public static Locale getDefaultLocale() { checkInit(); Locale locale = store.getCurrentLocale(); return locale; } /** * Look into the default {@link I18nLanguage} if the given {@code message} * can be found. * * @param message the message to check presence * @return true/false whether the message is present in the default language * @see #getDefaultLocale() * @see #hasKey(java.util.Locale, String) * @since 2.4.1 */ public static boolean hasKey(String message) { boolean result = false; // if the key to find is null, just return false if (message != null) { // checkInit() will be done by 'getDefaultLocale' or 'hasKey' method // get current locale (from the language in the store) Locale locale = getDefaultLocale(); result = hasKey(locale, message); } return result; } /** * Look into the {@link I18nLanguage} associated to the {@code locale} if * the given {@code message} can be found. * * @param locale the locale to be used to get the I18nLanguage * @param message the message to check presence * @return true/false whether the message is present for the given locale * @since 2.4.1 */ public static boolean hasKey(Locale locale, String message) { boolean result = false; // if the key to find is null, just return false if (message != null) { checkInit(); // Get the language associated to this locale... I18nLanguage language = getLanguage(locale); // ... and check key presence result = language.hasRecord(message); } return result; } /** * Retourne la chaine traduite si possible dans la locale demandée. * * @param locale la locale dans lequel on souhaite la traduction * @param message message formate avec {@link I18nMessageFormatter} * @param args les parametres pour le message. * @return la traduction si possible ou la chaine passee en parametre * sinon. * @since 2.1 * @deprecated since 2.9, will be removed soon or later, prefer use now method {@link #l(Locale, String, Object...)} */ @Deprecated public static String l_(Locale locale, String message, Object... args) { return l(locale, message, args); } /** * Retourne la chaine traduite si possible dans la locale demandée. * * @param locale la locale dans lequel on souhaite la traduction * @param message message formate avec {@link I18nMessageFormatter} * @param args les parametres pour le message. * @return la traduction si possible ou la chaine passee en parametre * sinon. * @since 2.1 */ public static String l(Locale locale, String message, Object... args) { checkInit(); // if the key to translate is null, just return null if (message == null) { return null; } I18nLanguage language = getLanguage(locale); String result = language.translate(message); // Don't check the length, this will be done directly in messageFormatter if necessary. // In MessageFormat case it must format all messages even there is no args (because of '' escape case). // if (args.length == 0) { // // // no argument form translation // return applyFilter(result); // } try { if (result != null) { result = applyFilter(messageFormatter.format(locale, result, args)); } return result; } catch (Exception eee) { try { return applyFilter(messageFormatter.format(locale, message, args)); } catch (Exception zzz) { if (log.isWarnEnabled()) { log.warn( t("nuitonutil.error.i18n.untranslated.message", message), zzz); } return applyFilter(message); } } } /** * Retourne la chaine traduite si possible. * * @param message message formate avec {@link I18nMessageFormatter} * @param args les parametres pour le message. * @return la traduction si possible ou la chaine passee en parametre * sinon. * @deprecated since 2.9, will be removed soon or later (hopes before Java SE 9), as part of syntax * keyword for lambda functions. Prefer use now method {@link #t(String, Object...)} */ @Deprecated public static String _(String message, Object... args) { return t(message, args); } /** * Retourne la chaine traduite si possible. * * @param message message formate avec {@link I18nMessageFormatter} * @param args les parametres pour le message. * @return la traduction si possible ou la chaine passee en parametre * sinon. */ public static String t(String message, Object... args) { // if the key to translate is null, just return null if (message == null) { return null; } // get current locale (from the language in the store) Locale locale = getDefaultLocale(); // translate with this locale String result = l(locale, message, args); return result; } /** * Retourne la chaine passée en argument. * * Utile surtout pour collecter les chaines et ne pas les traduires à leur * apparition. * * Par exemple : *
String key = "nuitonutils.key";
     * String result = l(key)
* fonctionnera, mais la chaine n'aura pas été marquée comme devant être * internationalisé. * * Tres utile par exemple, pour crée des objets non internationnalisé, et * devant être traduit seulement à leur lecture suivant la locale du lecteur * et non du créateur. * * @param message message formate avec {@link I18nMessageFormatter} * @param args les parametres pour le message. * @return le message passe en argument mais formatté avec les parametres * @deprecated since 2.9, will be removed soon or later, prefer use now method {@link #n(String, Object...)} */ @Deprecated public static String n_(String message, Object... args) { return n(message, args); } /** * Retourne la chaine passée en argument. * * Utile surtout pour collecter les chaines et ne pas les traduires à leur * apparition. * * Par exemple : *
String key = "nuitonutils.key";
     * String result = l(key)
* fonctionnera, mais la chaine n'aura pas été marquée comme devant être * internationalisé. * * Tres utile par exemple, pour crée des objets non internationnalisé, et * devant être traduit seulement à leur lecture suivant la locale du lecteur * et non du créateur. * * @param message message formate avec {@link I18nMessageFormatter} * @param args les parametres pour le message. * @return le message passe en argument mais formatté avec les parametres */ public static String n(String message, Object... args) { if (args.length == 0) { return message; } try { // XXX-fdesbois-2011-05-05 : don't know if it's relevant to format here, // seems pretty useless because we will not use the value // corresponding to given key message return messageFormatter.format(getDefaultLocale(), message, args); } catch (Exception eee) { if (log.isWarnEnabled()) { log.warn( t("nuitonutil.error.i18n.unformated.message", message, Arrays.toString(args)), eee); } return message; } } /** * Close i18n caches, says the store if exists. * * This method should be called to reset all caches (languages, * bundles,...) */ public static void close() { if (store != null) { store.close(); store = null; } if (messageFormatter != null) { messageFormatter = null; } } /** * Get the i18n store. * * If store is not init, then instanciate it. * * @return the instanciated i18n store */ public static I18nStore getStore() { return store; } /** * Applique le filtre s'il y en a un * * @param message le message qui devrait etre retourne avant application du * filtre. * @return le message filtre */ protected static String applyFilter(String message) { if (getFilter() != null) { return getFilter().applyFilter(message); } return message; } /** * Obtain the registred language from the store. * * If no language were registred in the store, then use the language * with the default locale of the store. * * @return the current language of the store, or the default one if store is * not init. */ protected static I18nLanguage getCurrentLanguage() { I18nLanguage language = getLanguage(null); return language; } /** * Obtain the language for the given {@code locale}. * * If locale is {@code null}, it means we wants to use the language * registred in the store. * * As a fallback if this language is not defined, we use the language of * the default locale of the store. * * @param locale the required locale or {@code null} if we wants to use the * one from the store * @return the language associated with the given locale. * @since 2.1 */ protected static I18nLanguage getLanguage(Locale locale) { checkInit(); I18nLanguage language; if (locale == null) { // default locale required : means wants the one of the store locale = getDefaultLocale(); if (locale == null) { // no locale registed in store, use the default locale from store locale = store.getDefaultLocale(); } } // get the given language from the store language = store.getLanguage(locale); return language; } protected static I18nFilter getFilter() { return filter; } public static I18nMessageFormatter getMessageFormatter() { return messageFormatter; } /** * Init the store with given parameters and set the current language in the * store to the default given {@code locale}. * * All values must be none {@code null}. * * @param initializer the initializer to use to detect bundles * @param locale the default locale to set in the store * @throws NullPointerException if any parameter is {@code null} */ protected static void initStore(I18nInitializer initializer, Locale locale) throws NullPointerException { if (initializer == null) { throw new NullPointerException( "initializer parameter can not be null"); } if (locale == null) { throw new NullPointerException( "locale parameter can not be null"); } if (store != null) { store.close(); store = null; } store = new I18nStore(locale, initializer); setDefaultLocale(locale); messageFormatter = initializer.getMessageFormatter(); } protected static I18nInitializer getDefaultInitializer() { I18nInitializer initializer = new ClassPathI18nInitializer(); if (log.isWarnEnabled()) { log.warn("\n\nI18n was not initialized! will init it with " + "default initializer and default locale, it might " + "not translate anything for you...\nPlease use the " + "method I18n.init(I18nInitializer, Locale) before " + "any calling to a translation...\n\n"); } return initializer; } /** * Checks if the I18n was initialized and if not as a fall-back, init it * with default initializer and default locale. It could not works for * you... A call to the method {@link #init(I18nInitializer, Locale)} is * mandatory if you want to be safe. * * @since 2.1 */ protected static void checkInit() { if (store == null) { init(null, null); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy