Package yalp.i18n

Source Code of yalp.i18n.Lang

package yalp.i18n;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Locale;

import yalp.Logger;
import yalp.Yalp;
import yalp.mvc.Http;
import yalp.mvc.Http.Request;
import yalp.mvc.Http.Response;

/**
* Language support
*/
public class Lang {

    public static ThreadLocal<String> current = new ThreadLocal<String>();

    /**
     * Retrieve the current language or null
     *
     * @return The current language (fr, ja, it ...) or null
     */
    public static String get() {
        String locale = current.get();
        if (locale == null) {
            // don't have current locale for this request - must try to resolve it
            Http.Request currentRequest = Http.Request.current();
            if (currentRequest != null) {
                // we have a current request - lets try to resolve language from it
                resolvefrom(currentRequest);
            } else {
                // don't have current request - just use default
                setDefaultLocale();
            }
            // get the picked locale
            locale = current.get();
        }
        return locale;
    }


    /**
     * Force the current language
     *
     * @param locale (fr, ja, it ...)
     * @return false if the language is not supported by the application
     */
    public static boolean set(String locale) {
        if (locale.equals("") || Yalp.langs.contains(locale)) {
            current.set(locale);
            return true;
        } else {
            Logger.warn("Locale %s is not defined in your application.conf", locale);
            return false;
        }
    }

    /**
     * Clears the current language - This wil trigger resolving language from request
     * if not manually set.
     */
    public static void clear() {
        current.remove();
    }


    /**
     * Change language for next requests
     *
     * @param locale (e.g. "fr", "ja", "it", "en_ca", "fr_be", ...)
     */
    public static void change(String locale) {
        String closestLocale = findClosestMatch(Collections.singleton(locale));
        if (closestLocale == null) {
            // Give up
            return;
        }
        if (set(closestLocale)) {
            Response response = Response.current();
            if (response != null) {
                // We have a current response in scope - set the language-cookie to store the selected language for the next requests
                response.setCookie(Yalp.configuration.getProperty("application.lang.cookie", "YALP_LANG"), locale);
            }
        }

    }

    /**
     * Given a set of desired locales, searches the set of locales supported by this Yalp application and returns the closest match.
     *
     * @param desiredLocales a collection of desired locales. If the collection is ordered, earlier locales are preferred over later ones.
     *                       Locales should be of the form "[language]_[country" or "[language]", e.g. "en_CA" or "en".
     *                       The locale strings are case insensitive (e.g. "EN_CA" is considered the same as "en_ca").
     *                       Locales can also be of the form "[language]-[country", e.g. "en-CA" or "en".
     *                       They are still case insensitive, though (e.g. "EN-CA" is considered the same as "en-ca").
     * @return the closest matching locale. If no closest match for a language/country is found, null is returned
     */
    private static String findClosestMatch(Collection<String> desiredLocales) {
        ArrayList<String> cleanLocales = new ArrayList<String>(desiredLocales.size());
        //look for an exact match
        for (String a : desiredLocales) {
            a = a.replace("-", "_");
            cleanLocales.add(a);
            for (String locale : Yalp.langs) {
                if (locale.equalsIgnoreCase(a)) {
                    return locale;
                }
            }
        }
        // Exact match not found, try language-only match.
        for (String a : cleanLocales) {
            int splitPos = a.indexOf("_");
            if (splitPos > 0) {
                a = a.substring(0, splitPos);
            }
            for (String locale : Yalp.langs) {
                String langOnlyLocale;
                int localeSplitPos = locale.indexOf("_");
                if (localeSplitPos > 0) {
                    langOnlyLocale = locale.substring(0, localeSplitPos);
                } else {
                    langOnlyLocale = locale;
                }
                if (langOnlyLocale.equalsIgnoreCase(a)) {
                    return locale;
                }
            }
        }

        // We did not find a anything
        return null;
    }

    /**
     * Guess the language for current request in the following order:
     * <ol>
     * <li>if a <b>YALP_LANG</b> cookie is set, use this value</li>
     * <li>if <b>Accept-Language</b> header is set, use it only if the Yalp application allows it.<br/>supported language may be defined in application configuration, eg : <em>yalp.langs=fr,en,de)</em></li>
     * <li>otherwise, server's locale language is assumed
     * </ol>
     *
     * @param request
     */
    private static void resolvefrom(Request request) {
        // Check a cookie
        String cn = Yalp.configuration.getProperty("application.lang.cookie", "YALP_LANG");
        if (request.cookies.containsKey(cn)) {
            String localeFromCookie = request.cookies.get(cn).value;
            if (localeFromCookie != null && localeFromCookie.trim().length() > 0) {
                if (set(localeFromCookie)) {
                    // we're using locale from cookie
                    return;
                }
                // could not use locale from cookie - clear the locale-cookie
                Response.current().setCookie(cn, "");

            }

        }
        String closestLocaleMatch = findClosestMatch(request.acceptLanguage());
        if (closestLocaleMatch != null) {
            set(closestLocaleMatch);
        } else {
            // Did not find anything - use default
            setDefaultLocale();
        }

    }

    public static void setDefaultLocale() {
        if (Yalp.langs.isEmpty()) {
            set("");
        } else {
            set(Yalp.langs.get(0));
        }
    }

    /**
     * @return the default locale if the Locale cannot be found otherwise the locale
     *         associated to the current Lang.
     */
    public static Locale getLocale() {
        String localeStr = get();
        Locale locale = getLocale(localeStr);
        if (locale != null) {
            return locale;
        }
        return Locale.getDefault();
    }

    public static Locale getLocale(String localeStr) {
        Locale langMatch = null;
        for (Locale locale : Locale.getAvailableLocales()) {
            String lang = localeStr;
            int splitPos = lang.indexOf("_");
            if (splitPos > 0) {
                lang = lang.substring(0, splitPos);
            }
            if (locale.toString().equalsIgnoreCase(localeStr)) {
                return locale;
            } else if (locale.getLanguage().equalsIgnoreCase(lang)) {
                langMatch = locale;
            }
        }
        return langMatch;
    }

}
TOP

Related Classes of yalp.i18n.Lang

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.