Improve localization framework.
[lgpl/argeo-commons.git] / org.argeo.cms / src / org / argeo / cms / LocaleUtils.java
index c6c932bf8c08c3cb7d0665f2dd2f6e53aff944ba..8101563d95e9fee6bbe3c4c6d51510206e5c0cc1 100644 (file)
 package org.argeo.cms;
 
+import java.security.AccessController;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Locale;
 import java.util.ResourceBundle;
 
+import javax.security.auth.Subject;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.argeo.cms.auth.CurrentUser;
 
 /** Utilities simplifying the development of localization enums. */
 public class LocaleUtils {
-       public static Object local(Enum<?> en) {
-               return local(en, getCurrentLocale(), "/OSGI-INF/l10n/bundle");
+       final static String DEFAULT_OSGI_l10N_BUNDLE = "/OSGI-INF/l10n/bundle";
+
+       private final static Log log = LogFactory.getLog(LocaleUtils.class);
+
+       private final static ThreadLocal<Locale> threadLocale = new ThreadLocal<>();
+
+       public static void setThreadLocale(Locale locale) {
+               threadLocale.set(locale);
+       }
+
+       public static String local(Localized localized) {
+               return local(localized.name(), localized.getClass().getClassLoader());
        }
 
-       public static Object local(Enum<?> en, Locale locale) {
-               return local(en, locale, "/OSGI-INF/l10n/bundle");
+       public static String local(Localized localized, Locale locale) {
+               if (localized.name() == null) // untranslated
+                       return localized.local(locale);
+               return local(localized.name(), locale, localized.getClass().getClassLoader());
        }
 
-       public static Object local(Enum<?> en, Locale locale, String resource) {
+       @Deprecated
+       public static String local(Enum<?> en) {
+               return local(en, getCurrentLocale(), DEFAULT_OSGI_l10N_BUNDLE);
+       }
+
+       @Deprecated
+       public static String local(Enum<?> en, Locale locale) {
+               return local(en, locale, DEFAULT_OSGI_l10N_BUNDLE);
+       }
+
+       @Deprecated
+       public static String local(Enum<?> en, Locale locale, String resource) {
                return local(en, locale, resource, en.getClass().getClassLoader());
        }
 
-       public static Object local(Enum<?> en, Locale locale, String resource, ClassLoader classLoader) {
+       @Deprecated
+       public static String local(Enum<?> en, Locale locale, String resource, ClassLoader classLoader) {
+               return local(en.name(), locale, resource, classLoader);
+       }
+
+       public static String local(String key, ClassLoader classLoader) {
+               return local(key, getCurrentLocale(), DEFAULT_OSGI_l10N_BUNDLE, classLoader);
+       }
+
+       public static String local(String key, Locale locale, ClassLoader classLoader) {
+               return local(key, locale, DEFAULT_OSGI_l10N_BUNDLE, classLoader);
+       }
+
+       /** Where the search for a message is actually performed. */
+       public static String local(String key, Locale locale, String resource, ClassLoader classLoader) {
                ResourceBundle rb = ResourceBundle.getBundle(resource, locale, classLoader);
-               return rb.getString(en.name());
+               assert key.length() > 2;
+               if (isLocaleKey(key))
+                       key = key.substring(1);
+               if (rb.containsKey(key))
+                       return rb.getString(key);
+               else // for simple cases, the key will actually be the English word
+                       return key;
        }
 
-       public static String lead(String raw, Locale locale) {
+       public static boolean isLocaleKey(String str) {
+               if (str.length() > 2 && ('%' == str.charAt(0)))
+                       return true;
+               else
+                       return false;
+       }
+
+       /** Lead transformation on the translated string. */
+       public static String toLead(String raw, Locale locale) {
                return raw.substring(0, 1).toUpperCase(locale) + raw.substring(1);
        }
 
+       public static String lead(Localized localized, ClassLoader classLoader) {
+               Locale locale = getCurrentLocale();
+               if (localized.name() == null)// untranslated
+                       return toLead(localized.local(locale), locale);
+               return toLead(local(localized.name(), getCurrentLocale(), DEFAULT_OSGI_l10N_BUNDLE, classLoader), locale);
+       }
+
        public static String lead(Localized localized) {
                return lead(localized, getCurrentLocale());
        }
 
        public static String lead(Localized localized, Locale locale) {
-               return lead(localized.local(locale).toString(), locale);
+               return toLead(local(localized, locale), locale);
        }
 
        static Locale getCurrentLocale() {
-               return CurrentUser.locale();
+               Locale currentLocale = null;
+               if (Subject.getSubject(AccessController.getContext()) != null)
+                       currentLocale = CurrentUser.locale();
+               else if (threadLocale.get() != null) {
+                       currentLocale = threadLocale.get();
+               }
+               if (log.isTraceEnabled())
+                       log.trace("Thread #" + Thread.currentThread().getId() + " " + Thread.currentThread().getName() + " locale: "
+                                       + currentLocale);
+               if (currentLocale == null)
+                       throw new IllegalStateException("No locale found");
+               return currentLocale;
                // return UiContext.getLocale();
                // FIXME look into Subject or settings
                // return Locale.getDefault();