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

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

/*
 * #%L
 * I18n :: Api
 * %%
 * Copyright (C) 2004 - 2017 Code Lutin, Ultreia.io
 * %%
 * 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 java.util.Arrays;
import java.util.Locale;
import java.util.Objects;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import org.nuiton.i18n.format.I18nMessageFormatter;
import org.nuiton.i18n.init.ClassPathI18nInitializer;
import org.nuiton.i18n.init.DefaultI18nInitializer;
import org.nuiton.i18n.init.I18nInitializer;

/**
 * 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 Logger log = LogManager.getLogger(I18n.class); /** 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 */ private 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(); return store.getCurrentLocale(); } /** * 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 */ 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); 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. */ 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 return l(locale, 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() { return getLanguage(null); } /** * 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 { Objects.requireNonNull(initializer, "initializer parameter can not be null"); Objects.requireNonNull(locale, "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