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

io.ultreia.java4all.i18n.I18n Maven / Gradle / Ivy

There is a newer version: 4.0-beta-27
Show newest version
package io.ultreia.java4all.i18n;

/*-
 * #%L
 * I18n :: Runtime
 * %%
 * Copyright (C) 2018 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%
 */

import io.ultreia.java4all.i18n.runtime.I18nConfiguration;
import io.ultreia.java4all.i18n.runtime.I18nFilter;
import io.ultreia.java4all.i18n.runtime.I18nLanguage;
import io.ultreia.java4all.i18n.runtime.I18nLanguageProvider;
import io.ultreia.java4all.i18n.runtime.boot.I18nBootLoader;
import io.ultreia.java4all.i18n.runtime.format.I18nMessageFormatter;
import io.ultreia.java4all.i18n.spi.I18nLocaleHelper;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

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

/**
 * Created by tchemit on 06/11/2018.
 *
 * @author Tony Chemit - [email protected]
 */
@SuppressWarnings("WeakerAccess")
public class I18n {

    private static final Logger log = LogManager.getLogger(I18n.class);
    /**
     * Optional filter.
     */
    private static I18nFilter filter;

    /**
     * Boot loader used to init I18n.
     */
    private static I18nBootLoader bootLoader;

    /**
     * Boot loader used to init I18n.
     */
    private static I18nLanguageProvider languageProvider;

    /**
     * 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 I18nConfiguration#setMessageFormatter(I18nMessageFormatter) * @since 2.4 */ private static I18nMessageFormatter messageFormatter; public static I18nFilter getFilter() { return filter; } public static void setFilter(I18nFilter filter) { I18n.filter = filter; } public static I18nMessageFormatter getMessageFormatter() { return messageFormatter; } public static I18nBootLoader getBootLoader() { return bootLoader; } public static I18nLanguageProvider getLanguageProvider() { return languageProvider; } public static void init(I18nBootLoader bootLoader, Locale locale) { if (bootLoader == null) { bootLoader = I18nBootLoader.DEFAULT_BOOT_LOADER; } if (locale == null) { locale = I18nLocaleHelper.newLocale(null, null); } initStore(bootLoader, locale); } public static void reload() { checkInit(); // get back initializer I18nBootLoader initializer = bootLoader; // get back default locale Locale locale = languageProvider.getCurrentLocale(); // close the current store close(); // reload store init(initializer, 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 languageProvider.getCurrentLocale(); } /** * 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. */ public static void setDefaultLocale(Locale locale) { checkInit(); languageProvider.setCurrentLocale(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 */ 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 == null ? message : 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 (languageProvider != null) { // languageProvider.close(); languageProvider = null; } if (messageFormatter != null) { messageFormatter = null; } } /** * 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 registred in store, use the default locale from store locale = languageProvider.getDefaultLocale(); } } // get the given language from the store return languageProvider.getLanguage(locale); } /** * 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 bootLoader 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(I18nBootLoader bootLoader, Locale locale) throws NullPointerException { I18n.bootLoader = Objects.requireNonNull(bootLoader); if (languageProvider != null) { // languageProvider.close(); languageProvider = null; } I18n.languageProvider = I18n.bootLoader.init(locale); setDefaultLocale(Objects.requireNonNull(locale)); messageFormatter = bootLoader.getConfiguration().getMessageFormatter(); } /** * 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(I18nBootLoader, Locale)} is * mandatory if you want to be safe. * * @since 2.1 */ protected static void checkInit() { if (languageProvider == null) { init(null, null); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy