package play.i18n; import java.util.Locale; import play.Logger; import play.Play; import play.mvc.Http; import play.mvc.Http.Request; import play.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("") || Play.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 (fr, ja, it ...) */ public static void change(String locale) { if (set(locale)) { Response.current().setCookie(Play.configuration.getProperty("application.lang.cookie", "PLAY_LANG"), locale); } } /** * Guess the language for current request in the following order: * <ol> * <li>if a <b>PLAY_LANG</b> cookie is set, use this value</li> * <li>if <b>Accept-Language</b> header is set, use it only if the Play! application allows it.<br/>supported language may be defined in application configuration, eg : <em>play.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 = Play.configuration.getProperty("application.lang.cookie", "PLAY_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, ""); } } // Try from accept-language - look for an exact match for (String a: request.acceptLanguage()) { a = a.replace("-", "_").toLowerCase(); for (String locale: Play.langs) { if (locale.toLowerCase().equals(a)) { set(locale); return; } } } // now see if we have a country-only match for (String a: request.acceptLanguage()) { if (a.indexOf("-") > 0) { a = a.substring(0, a.indexOf("-")); } for (String locale: Play.langs) { if (locale.equals(a)) { set(locale); return; } } } // Use default setDefaultLocale(); } public static void setDefaultLocale() { if (Play.langs.isEmpty()) { set(""); } else { set(Play.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 lang = get(); Locale locale = getLocale(lang); if (locale != null) { return locale; } return Locale.getDefault(); } public static Locale getLocale(String lang) { for (Locale locale : Locale.getAvailableLocales()) { if (locale.getLanguage().equals(lang)) { return locale; } } return null; } }