Localis(z)ation support
authorMathieu Baudier <mbaudier@argeo.org>
Wed, 14 Oct 2015 16:12:05 +0000 (16:12 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Wed, 14 Oct 2015 16:12:05 +0000 (16:12 +0000)
git-svn-id: https://svn.argeo.org/commons/trunk@8483 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

18 files changed:
demo/argeo_node_cms.properties
demo/argeo_node_rap.properties
org.argeo.cms/src/org/argeo/cms/CmsMsg.java
org.argeo.cms/src/org/argeo/cms/CmsMsg_fr.properties
org.argeo.cms/src/org/argeo/cms/i18n/Msg.java
org.argeo.cms/src/org/argeo/cms/internal/auth/ConsoleCallbackHandler.java
org.argeo.cms/src/org/argeo/cms/internal/kernel/Kernel.java
org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelConstants.java
org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelHeader.java
org.argeo.cms/src/org/argeo/cms/widgets/auth/CmsLogin.java
org.argeo.security.ui.rap/OSGI-INF/l10n/bundle.properties [new file with mode: 0644]
org.argeo.security.ui.rap/OSGI-INF/l10n/bundle_fr.properties [new file with mode: 0644]
org.argeo.security.ui.rap/build.properties
org.argeo.security.ui.rap/plugin.xml
org.argeo.security.ui.rap/src/org/argeo/security/ui/rap/SecureEntryPoint.java
org.argeo.security.ui/src/org/argeo/security/ui/commands/OpenChangePasswordDialog.java
org.argeo.util/src/org/argeo/util/LocaleChoice.java
org.argeo.util/src/org/argeo/util/LocaleUtils.java [deleted file]

index fcc210955c029b7b1eac447af84a4a23468b19fe..31b71106872e7f54d2a35485a72387da63e27128 100644 (file)
@@ -24,5 +24,10 @@ org.eclipse.equinox.http.jetty.log.stderr.threshold=info
 org.osgi.framework.security=osgi
 java.security.policy=file:../../all.policy
 
+# i18n
+argeo.i18n.defaultLocale=fr
+argeo.i18n.locales=en,fr
+eclipse.registry.MultiLanguage=true
+
 log4j.configuration=file:../../log4j.properties
 org.eclipse.rap.workbenchAutostart=false
\ No newline at end of file
index 818fc76bf3f39a60cba5f162512c9e8e4ad19df6..22a4283a1e42443f848fa3c2bb244446f44a84b0 100644 (file)
@@ -41,7 +41,7 @@ org.eclipse.equinox.http.jetty.log.stderr.threshold=info
 # cd ssl; sh ./ssl.sh;
 
 # i18n
-argeo.i18n.availableLocales=en,fr,de
+argeo.i18n.locales=en,fr,de
 eclipse.registry.MultiLanguage=true
 
 # Logging
index d6172a9006324bd122543598274a2cea43b4e5f7..6d118db078d1ad7df2a87913fd71a1e29fa89aa6 100644 (file)
@@ -11,6 +11,12 @@ public class CmsMsg extends DefaultsResourceBundle {
        public final static Msg login = new Msg("sign in");
        public final static Msg register = new Msg("register");
 
+       public final static Msg changePassword = new Msg("change password");
+       public final static Msg currentPassword = new Msg("current password");
+       public final static Msg newPassword = new Msg("new password");
+       public final static Msg repeatNewPassword = new Msg("repeat new password");
+       public final static Msg passwordChanged = new Msg("password changed");
+
        static {
                Msg.init(CmsMsg.class);
        }
index 23817233dd014fc663d0919d011d4cae9938c5eb..dc25d31a12d2ffa5c7c2c0b05c76b9db3b671aa6 100644 (file)
@@ -2,4 +2,10 @@ username=identifiant
 password=mot de passe
 logout=déconnexion
 login=connexion
-register=créer un compte
\ No newline at end of file
+register=créer un compte
+
+changePassword=changement de mot de passe
+currentPassword=mot de passe actuel
+newPassword=nouveau mot de passe
+repeatNewPassword=répéter le nouveau mot de passe
+passwordChanged=mot de passe changé
index 64982f6c7ce0131fad298f14afa20a2c0cb7448a..bbbd590cd97356f6365edad5962e261d3ad6d7b1 100644 (file)
@@ -48,9 +48,20 @@ public class Msg {
 
        /** When used as the first word of a sentence. */
        public String lead() {
-               String raw = toString();
-               return raw.substring(0, 1).toUpperCase(UiContext.getLocale())
-                               + raw.substring(1);
+               return lead(UiContext.getLocale());
+       }
+
+       public String lead(Locale locale) {
+               return lead(this, locale);
+       }
+
+       private static String lead(Msg msg, Locale locale) {
+               String raw = msg.local(locale).toString();
+               return lead(raw, locale);
+       }
+
+       public static String lead(String raw, Locale locale) {
+               return raw.substring(0, 1).toUpperCase(locale) + raw.substring(1);
        }
 
        public Object local() {
@@ -62,12 +73,25 @@ public class Msg {
                return local;
        }
 
+       public Object local(Locale locale) {
+               Object local = local(this, locale);
+               if (local == null)
+                       local = getDefault();
+               if (local == null)
+                       throw new CmsException("No translation found for " + id);
+               return local;
+       }
+
        private static Object local(Msg msg) {
+               Locale locale = UiContext.getLocale();
+               return local(msg, locale);
+       }
+
+       private static Object local(Msg msg, Locale locale) {
                String key = msg.getId();
                int lastDot = key.lastIndexOf('.');
                String className = key.substring(0, lastDot);
                String fieldName = key.substring(lastDot + 1);
-               Locale locale = UiContext.getLocale();
                ResourceBundle rb = ResourceBundle.getBundle(className, locale,
                                msg.getClassLoader());
                return rb.getString(fieldName);
index d5c6f002473a622da76d295b4194c6bb304d863e..acb75d1e52b0d57655d85b785a4cca9d8a2f14c4 100644 (file)
@@ -53,8 +53,8 @@ public class ConsoleCallbackHandler implements CallbackHandler {
                                LocaleChoice callback = (LocaleChoice) callbacks[i];
                                writer.write("Language");
                                writer.write("\n");
-                               for (int j = 0; j < callback.getAvailableLocales().size(); j++) {
-                                       Locale locale = callback.getAvailableLocales().get(j);
+                               for (int j = 0; j < callback.getLocales().size(); j++) {
+                                       Locale locale = callback.getLocales().get(j);
                                        writer.print(j + " : " + locale.getDisplayName() + "\n");
                                }
                                writer.write("(" + callback.getDefaultIndex() + ") : ");
index b95c195584d3986734efcef3b81f8fca50453819..b66140e31e1de8274d3f0a3c3206dbecd962bf3a 100644 (file)
@@ -2,10 +2,12 @@ package org.argeo.cms.internal.kernel;
 
 import static bitronix.tm.TransactionManagerServices.getTransactionManager;
 import static bitronix.tm.TransactionManagerServices.getTransactionSynchronizationRegistry;
+import static java.util.Locale.ENGLISH;
 import static org.argeo.cms.internal.kernel.KernelUtils.getFrameworkProp;
 import static org.argeo.cms.internal.kernel.KernelUtils.getOsgiInstancePath;
 import static org.argeo.jcr.ArgeoJcrConstants.ALIAS_NODE;
 import static org.argeo.jcr.ArgeoJcrConstants.JCR_REPOSITORY_ALIAS;
+import static org.argeo.util.LocaleChoice.asLocaleList;
 import static org.osgi.framework.Constants.FRAMEWORK_UUID;
 
 import java.io.File;
@@ -13,6 +15,8 @@ import java.lang.management.ManagementFactory;
 import java.security.PrivilegedAction;
 import java.util.HashMap;
 import java.util.Hashtable;
+import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 
 import javax.jcr.Repository;
@@ -84,6 +88,9 @@ final class Kernel implements KernelHeader, KernelConstants, ServiceListener {
        private DataHttp dataHttp;
        private KernelThread kernelThread;
 
+       private Locale defaultLocale = null;
+       private List<Locale> locales = null;
+
        public Kernel() {
                nodeSecurity = new NodeSecurity();
        }
@@ -108,11 +115,13 @@ final class Kernel implements KernelHeader, KernelConstants, ServiceListener {
                Thread.currentThread().setContextClassLoader(
                                Kernel.class.getClassLoader());
                // KernelUtils.logFrameworkProperties(log);
+               defaultLocale = new Locale(getFrameworkProp(I18N_DEFAULT_LOCALE,
+                               ENGLISH.getLanguage()));
+               locales = asLocaleList(getFrameworkProp(I18N_LOCALES));
 
                try {
                        // Initialise services
                        logger = new NodeLogger();
-                       // transactionManager = new SimpleTransactionManager();
                        initBitronixTransactionManager();
                        repository = new NodeRepository(bc);
                        repositoryFactory = new OsgiJackrabbitRepositoryFactory();
@@ -279,23 +288,16 @@ final class Kernel implements KernelHeader, KernelConstants, ServiceListener {
                                        + (httpsPort != null ? " - HTTPS " + httpsPort : ""));
        }
 
-       // private ExtendedHttpService waitForHttpService() {
-       // final ServiceTracker<ExtendedHttpService, ExtendedHttpService> st = new
-       // ServiceTracker<ExtendedHttpService, ExtendedHttpService>(
-       // bc, ExtendedHttpService.class, null);
-       // st.open();
-       // ExtendedHttpService httpService;
-       // try {
-       // httpService = st.waitForService(1000);
-       // } catch (InterruptedException e) {
-       // httpService = null;
-       // }
-       //
-       // if (httpService == null)
-       // throw new CmsException("Could not find "
-       // + ExtendedHttpService.class + " service.");
-       // return httpService;
-       // }
+       @Override
+       public Locale getDefaultLocale() {
+               return defaultLocale;
+       }
+
+       /** Can be null. */
+       @Override
+       public List<Locale> getLocales() {
+               return locales;
+       }
 
        final private static void directorsCut(long initDuration) {
                // final long ms = 128l + (long) (Math.random() * 128d);
index 9f45edb7fc662cd07859e0f68d771f9310674f1c..0fe5b3ae90787cdaa3b65cb7f3081d70e6d355b1 100644 (file)
@@ -18,7 +18,8 @@ public interface KernelConstants {
 
        final static String TRANSACTIONS_HOME = "argeo.node.transactions.home";
 
-       final static String I18N_AVAILABLE_LOCALES = "argeo.i18n.availableLocales";
+       final static String I18N_DEFAULT_LOCALE = "argeo.i18n.defaultLocale";
+       final static String I18N_LOCALES = "argeo.i18n.locales";
 
        // Node Security
        final static String ROLES_URI = "argeo.node.roles.uri";
index f4d4d843abf14dc172dfb6d563523ae845bf511e..f82f6b1d13a2a594c0f8b9ad22cb86d0e6cc6fba 100644 (file)
@@ -1,5 +1,10 @@
 package org.argeo.cms.internal.kernel;
 
+import java.util.List;
+import java.util.Locale;
+
 public interface KernelHeader {
+       public Locale getDefaultLocale();
 
+       public List<Locale> getLocales();
 }
index 04e4f3c9f551e67fd8094066a6c95ab39ba9b4b2..53a23a3243a995b3ee705f7adce589dc24a921a1 100644 (file)
@@ -1,9 +1,14 @@
 package org.argeo.cms.widgets.auth;
 
+import static org.argeo.cms.CmsMsg.password;
+import static org.argeo.cms.CmsMsg.username;
 import static org.argeo.cms.auth.AuthConstants.LOGIN_CONTEXT_ANONYMOUS;
 import static org.argeo.cms.auth.AuthConstants.LOGIN_CONTEXT_USER;
+import static org.argeo.cms.internal.kernel.Activator.getKernelHeader;
 
 import java.io.IOException;
+import java.util.List;
+import java.util.Locale;
 
 import javax.security.auth.Subject;
 import javax.security.auth.callback.Callback;
@@ -21,16 +26,21 @@ import org.argeo.cms.CmsStyles;
 import org.argeo.cms.CmsView;
 import org.argeo.cms.auth.CurrentUser;
 import org.argeo.cms.auth.HttpRequestCallback;
+import org.argeo.cms.i18n.Msg;
 import org.argeo.cms.util.CmsUtils;
 import org.argeo.util.LocaleChoice;
 import org.eclipse.rap.rwt.RWT;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.events.MouseAdapter;
 import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
 import org.eclipse.swt.events.TraverseEvent;
 import org.eclipse.swt.events.TraverseListener;
 import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.Label;
@@ -38,14 +48,20 @@ import org.eclipse.swt.widgets.Shell;
 import org.eclipse.swt.widgets.Text;
 
 public class CmsLogin implements CmsStyles, CallbackHandler {
-       private Text username, password;
+       private Text usernameT, passwordT;
        private Composite credentialsBlock;
+
+       private final Locale defaultLocale;
        private LocaleChoice localeChoice = null;
 
        private final CmsView cmsView;
 
        public CmsLogin(CmsView cmsView) {
                this.cmsView = cmsView;
+               defaultLocale = getKernelHeader().getDefaultLocale();
+               List<Locale> locales = getKernelHeader().getLocales();
+               if (locales != null)
+                       localeChoice = new LocaleChoice(locales, defaultLocale);
        }
 
        protected boolean isAnonymous() {
@@ -116,20 +132,20 @@ public class CmsLogin implements CmsStyles, CallbackHandler {
                parent.setData(RWT.CUSTOM_VARIANT, CMS_USER_MENU);
 
                // new Label(this, SWT.NONE).setText(CmsMsg.username.lead());
-               username = new Text(credentialsBlock, SWT.BORDER);
-               username.setMessage(CmsMsg.username.lead());
-               username.setData(RWT.CUSTOM_VARIANT, CMS_LOGIN_DIALOG_USERNAME);
+               usernameT = new Text(credentialsBlock, SWT.BORDER);
+               usernameT.setMessage(username.lead(defaultLocale));
+               usernameT.setData(RWT.CUSTOM_VARIANT, CMS_LOGIN_DIALOG_USERNAME);
                GridData gd = CmsUtils.fillWidth();
                gd.widthHint = textWidth;
-               username.setLayoutData(gd);
+               usernameT.setLayoutData(gd);
 
                // new Label(this, SWT.NONE).setText(CmsMsg.password.lead());
-               password = new Text(credentialsBlock, SWT.BORDER | SWT.PASSWORD);
-               password.setMessage(CmsMsg.password.lead());
-               password.setData(RWT.CUSTOM_VARIANT, CMS_LOGIN_DIALOG_PASSWORD);
+               passwordT = new Text(credentialsBlock, SWT.BORDER | SWT.PASSWORD);
+               passwordT.setMessage(password.lead(defaultLocale));
+               passwordT.setData(RWT.CUSTOM_VARIANT, CMS_LOGIN_DIALOG_PASSWORD);
                gd = CmsUtils.fillWidth();
                gd.widthHint = textWidth;
-               password.setLayoutData(gd);
+               passwordT.setLayoutData(gd);
 
                TraverseListener tl = new TraverseListener() {
                        private static final long serialVersionUID = -1158892811534971856L;
@@ -140,14 +156,48 @@ public class CmsLogin implements CmsStyles, CallbackHandler {
                        }
                };
                credentialsBlock.addTraverseListener(tl);
-               username.addTraverseListener(tl);
-               password.addTraverseListener(tl);
+               usernameT.addTraverseListener(tl);
+               passwordT.addTraverseListener(tl);
                parent.setTabList(new Control[] { credentialsBlock });
-               credentialsBlock.setTabList(new Control[] { username, password });
+               credentialsBlock.setTabList(new Control[] { usernameT, passwordT });
                credentialsBlock.setFocus();
+
+               if (localeChoice != null)
+                       createLocalesBlock(credentialsBlock);
                return credentialsBlock;
        }
 
+       protected Composite createLocalesBlock(final Composite parent) {
+               Composite c = new Composite(parent, SWT.NONE);
+               c.setLayout(CmsUtils.noSpaceGridLayout());
+               c.setLayoutData(CmsUtils.fillAll());
+
+               SelectionListener selectionListener = new SelectionAdapter() {
+                       private static final long serialVersionUID = 4891637813567806762L;
+
+                       public void widgetSelected(SelectionEvent event) {
+                               localeChoice.setSelectedIndex((Integer) event.widget.getData());
+                               Locale selectedLocale = localeChoice.getSelectedLocale();
+                               usernameT.setMessage(username.lead(selectedLocale));
+                               passwordT.setMessage(password.lead(selectedLocale));
+                       };
+               };
+
+               List<Locale> locales = localeChoice.getLocales();
+               for (Integer i = 0; i < locales.size(); i++) {
+                       Locale locale = locales.get(i);
+                       Button button = new Button(c, SWT.RADIO);
+                       button.setData(i);
+                       button.setText(Msg.lead(locale.getDisplayName(locale), locale)
+                                       + " (" + locale + ")");
+                       // button.addListener(SWT.Selection, listener);
+                       button.addSelectionListener(selectionListener);
+                       if (i == localeChoice.getDefaultIndex())
+                               button.setSelection(true);
+               }
+               return c;
+       }
+
        protected void login() {
                Subject subject = cmsView.getSubject();
                LoginContext loginContext;
@@ -174,9 +224,9 @@ public class CmsLogin implements CmsStyles, CallbackHandler {
                        UnsupportedCallbackException {
                for (Callback callback : callbacks) {
                        if (callback instanceof NameCallback)
-                               ((NameCallback) callback).setName(username.getText());
+                               ((NameCallback) callback).setName(usernameT.getText());
                        else if (callback instanceof PasswordCallback)
-                               ((PasswordCallback) callback).setPassword(password
+                               ((PasswordCallback) callback).setPassword(passwordT
                                                .getTextChars());
                        else if (callback instanceof HttpRequestCallback)
                                ((HttpRequestCallback) callback).setRequest(RWT.getRequest());
diff --git a/org.argeo.security.ui.rap/OSGI-INF/l10n/bundle.properties b/org.argeo.security.ui.rap/OSGI-INF/l10n/bundle.properties
new file mode 100644 (file)
index 0000000..4dff7af
--- /dev/null
@@ -0,0 +1 @@
+changePassword=Change password
\ No newline at end of file
diff --git a/org.argeo.security.ui.rap/OSGI-INF/l10n/bundle_fr.properties b/org.argeo.security.ui.rap/OSGI-INF/l10n/bundle_fr.properties
new file mode 100644 (file)
index 0000000..158d6fa
--- /dev/null
@@ -0,0 +1 @@
+changePassword=Changer de mot de passe
\ No newline at end of file
index 30f715358d984db427238bb1984c0d19b6ca4004..ae37429d82729c1cf4b48a77ffc1b6ae2a2730dd 100644 (file)
@@ -1 +1,2 @@
 source.. = src/
+bin.includes = OSGI-INF/
index f2fae3c50bf31b8347441495d3af080c02943c1d..693a4ddf0cdf003a7f49d67f40a71da9c463bee3 100644 (file)
@@ -33,7 +33,7 @@
                <command
                        id="org.argeo.security.ui.rap.openChangePasswordDialog"
                        defaultHandler="org.argeo.eclipse.spring.SpringCommandHandler"
-                       name="Change Password">
+                       name="%changePassword">
                </command>
                <!-- Enable an "open file" action in a single sourced application  -->  
                <command
@@ -87,7 +87,7 @@
                <command
                                commandId="org.argeo.security.ui.rap.openChangePasswordDialog"
                                icon="icons/password.gif"
-                               label="Change password"/>
+                               label="%changePassword"/>
                        <separator
                                name="org.argeo.security.ui.rap.beforeFile"
                                visible="true">
index c176ba62b59fc4d4e13372cfc50e870a140b2046..5ff76a9ea6156e795c945f81df62f2aca7bcf869 100644 (file)
@@ -34,7 +34,6 @@ import org.argeo.ArgeoException;
 import org.argeo.cms.auth.AuthConstants;
 import org.argeo.cms.widgets.auth.DefaultLoginDialog;
 import org.argeo.eclipse.ui.dialogs.ErrorFeedback;
-import org.argeo.util.LocaleUtils;
 import org.eclipse.jface.dialogs.MessageDialog;
 import org.eclipse.rap.rwt.RWT;
 import org.eclipse.rap.rwt.application.EntryPoint;
@@ -104,9 +103,9 @@ public class SecureEntryPoint implements EntryPoint {
                                                throw new ArgeoException("Login succeeded but no auth");// fatal
 
                                        // add thread locale to RWT session
-                                       if (log.isTraceEnabled())
-                                               log.trace("Locale " + LocaleUtils.threadLocale.get());
-                                       RWT.setLocale(LocaleUtils.threadLocale.get());
+                                       // if (log.isTraceEnabled())
+                                       // log.trace("Locale " + LocaleUtils.threadLocale.get());
+                                       // RWT.setLocale(LocaleUtils.threadLocale.get());
 
                                        // once the user is logged in, longer session timeout
                                        RWT.getRequest().getSession()
index 560cc8bc9f3de093a340288e192dc5ad7ffabdc5..12cae7fb36716d8b45e307c83d11da865fa9eb95 100644 (file)
  */
 package org.argeo.security.ui.commands;
 
+import static org.argeo.cms.CmsMsg.changePassword;
+import static org.argeo.cms.CmsMsg.currentPassword;
+import static org.argeo.cms.CmsMsg.newPassword;
+import static org.argeo.cms.CmsMsg.passwordChanged;
+import static org.argeo.cms.CmsMsg.repeatNewPassword;
+import static org.eclipse.jface.dialogs.IMessageProvider.INFORMATION;
+
 import java.security.AccessController;
 
 import javax.naming.InvalidNameException;
@@ -30,7 +37,6 @@ import org.eclipse.core.commands.AbstractHandler;
 import org.eclipse.core.commands.ExecutionEvent;
 import org.eclipse.core.commands.ExecutionException;
 import org.eclipse.jface.dialogs.Dialog;
-import org.eclipse.jface.dialogs.IMessageProvider;
 import org.eclipse.jface.dialogs.MessageDialog;
 import org.eclipse.jface.dialogs.TitleAreaDialog;
 import org.eclipse.swt.SWT;
@@ -58,7 +64,7 @@ public class OpenChangePasswordDialog extends AbstractHandler {
                                HandlerUtil.getActiveShell(event), userAdmin);
                if (dialog.open() == Dialog.OK) {
                        MessageDialog.openInformation(HandlerUtil.getActiveShell(event),
-                                       "Password changed", "Password changed.");
+                                       passwordChanged.lead(), passwordChanged.lead());
                }
                return null;
        }
@@ -103,7 +109,7 @@ public class OpenChangePasswordDialog extends AbstractHandler {
 
        class ChangePasswordDialog extends TitleAreaDialog {
                private static final long serialVersionUID = -6963970583882720962L;
-               private Text currentPassword, newPassword1, newPassword2;
+               private Text oldPassword, newPassword1, newPassword2;
 
                public ChangePasswordDialog(Shell parentShell, UserAdmin securityService) {
                        super(parentShell);
@@ -121,11 +127,11 @@ public class OpenChangePasswordDialog extends AbstractHandler {
                        composite.setLayout(new GridLayout(2, false));
                        composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
                                        false));
-                       currentPassword = createLP(composite, "Current password");
-                       newPassword1 = createLP(composite, "New password");
-                       newPassword2 = createLP(composite, "Repeat new password");
+                       oldPassword = createLP(composite, currentPassword.lead());
+                       newPassword1 = createLP(composite, newPassword.lead());
+                       newPassword2 = createLP(composite, repeatNewPassword.lead());
 
-                       setMessage("Change password", IMessageProvider.INFORMATION);
+                       setMessage(changePassword.lead(), INFORMATION);
                        parent.pack();
                        return composite;
                }
@@ -135,7 +141,7 @@ public class OpenChangePasswordDialog extends AbstractHandler {
                        if (!newPassword1.getText().equals(newPassword2.getText()))
                                throw new ArgeoException("Passwords are different");
                        try {
-                               changePassword(currentPassword.getTextChars(),
+                               changePassword(oldPassword.getTextChars(),
                                                newPassword1.getTextChars());
                                close();
                        } catch (Exception e) {
@@ -156,7 +162,7 @@ public class OpenChangePasswordDialog extends AbstractHandler {
 
                protected void configureShell(Shell shell) {
                        super.configureShell(shell);
-                       shell.setText("Change password");
+                       shell.setText(changePassword.lead());
                }
 
        }
index aaf719db4c437b84bf53501fde2ead0e3021b1e5..4b4db0eca257ac6e1c78f84a775f7e26d98462e6 100644 (file)
 package org.argeo.util;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.Locale;
 
 import javax.security.auth.callback.LanguageCallback;
 
+import org.argeo.ArgeoException;
+
 /** Choose in a list of locales. TODO: replace with {@link LanguageCallback} */
 public class LocaleChoice {
-       private List<Locale> availableLocales = new ArrayList<Locale>();
+       private final List<Locale> locales;
 
        private Integer selectedIndex = null;
-       private Integer defaultIndex = null;
+       private final Integer defaultIndex;
+
+       public LocaleChoice(List<Locale> locales, Locale defaultLocale) {
+               Integer defaultIndex = null;
+               this.locales = Collections.unmodifiableList(locales);
+               for (int i = 0; i < locales.size(); i++)
+                       if (locales.get(i).equals(defaultLocale))
+                               defaultIndex = i;
 
-       // public LocaleCallback(Integer defaultIndex, List<Locale>
-       // availableLocales) {
-       // this.availableLocales = Collections
-       // .unmodifiableList(new ArrayList<Locale>(availableLocales));
-       // this.defaultIndex = defaultIndex;
-       // this.selectedIndex = defaultIndex;
-       // }
+               // based on language only
+               if (defaultIndex == null)
+                       for (int i = 0; i < locales.size(); i++)
+                               if (locales.get(i).getLanguage()
+                                               .equals(defaultLocale.getLanguage()))
+                                       defaultIndex = i;
+
+               if (defaultIndex == null)
+                       throw new ArgeoException("Default locale " + defaultLocale
+                                       + " is not in available locales " + locales);
+               this.defaultIndex = defaultIndex;
+
+               this.selectedIndex = defaultIndex;
+       }
 
        /**
         * Convenience constructor based on a comma separated list of iso codes (en,
         * en_US, fr_CA, etc.). Default selection is default locale.
         */
        public LocaleChoice(String locales, Locale defaultLocale) {
-               if (locales == null || locales.trim().equals(""))
-                       return;
-               String[] codes = locales.split(",");
-               for (int i = 0; i < codes.length; i++) {
-                       String code = codes[i];
-                       // variant not supported
-                       int indexUnd = code.indexOf("_");
-                       Locale locale;
-                       if (indexUnd > 0) {
-                               String language = code.substring(0, indexUnd);
-                               String country = code.substring(indexUnd + 1);
-                               locale = new Locale(language, country);
-                       } else {
-                               locale = new Locale(code);
-                       }
-                       availableLocales.add(locale);
-                       if (locale.equals(defaultLocale))
-                               defaultIndex = i;
-               }
-
-               if (defaultIndex == null)
-                       defaultIndex = 0;
-
-               this.selectedIndex = defaultIndex;
+               this(asLocaleList(locales), defaultLocale);
        }
 
        public String[] getSupportedLocalesLabels() {
-               String[] labels = new String[availableLocales.size()];
-               for (int i = 0; i < availableLocales.size(); i++) {
-                       Locale locale = availableLocales.get(i);
+               String[] labels = new String[locales.size()];
+               for (int i = 0; i < locales.size(); i++) {
+                       Locale locale = locales.get(i);
                        if (locale.getCountry().equals(""))
                                labels[i] = locale.getDisplayLanguage(locale) + " ["
                                                + locale.getLanguage() + "]";
@@ -87,7 +81,7 @@ public class LocaleChoice {
        public Locale getSelectedLocale() {
                if (selectedIndex == null)
                        return null;
-               return availableLocales.get(selectedIndex);
+               return locales.get(selectedIndex);
        }
 
        public void setSelectedIndex(Integer selectedIndex) {
@@ -98,12 +92,35 @@ public class LocaleChoice {
                return defaultIndex;
        }
 
-       public List<Locale> getAvailableLocales() {
-               return availableLocales;
+       public List<Locale> getLocales() {
+               return locales;
        }
 
        public Locale getDefaultLocale() {
-               return availableLocales.get(getDefaultIndex());
+               return locales.get(getDefaultIndex());
+       }
+
+       /** Returns null if argument is null. */
+       public static List<Locale> asLocaleList(String locales) {
+               if (locales == null)
+                       return null;
+               ArrayList<Locale> availableLocales = new ArrayList<Locale>();
+               String[] codes = locales.split(",");
+               for (int i = 0; i < codes.length; i++) {
+                       String code = codes[i];
+                       // variant not supported
+                       int indexUnd = code.indexOf("_");
+                       Locale locale;
+                       if (indexUnd > 0) {
+                               String language = code.substring(0, indexUnd);
+                               String country = code.substring(indexUnd + 1);
+                               locale = new Locale(language, country);
+                       } else {
+                               locale = new Locale(code);
+                       }
+                       availableLocales.add(locale);
+               }
+               return availableLocales;
        }
 
        public static void main(String[] args) {
diff --git a/org.argeo.util/src/org/argeo/util/LocaleUtils.java b/org.argeo.util/src/org/argeo/util/LocaleUtils.java
deleted file mode 100644 (file)
index bc04afa..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Argeo GmbH
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *         http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.argeo.util;
-
-import java.util.Locale;
-
-import org.argeo.ArgeoException;
-
-/** Utilities around internationalization. */
-public class LocaleUtils {
-       /**
-        * The locale of the current thread and its children. Allows to deal with
-        * internationalisation as a cross cutting aspect. Never null.
-        */
-       public final static InheritableThreadLocal<Locale> threadLocale = new InheritableThreadLocal<Locale>() {
-               @Override
-               protected Locale initialValue() {
-                       return Locale.getDefault();
-               }
-
-               @Override
-               public void set(Locale value) {
-                       if (value == null)
-                               throw new ArgeoException("Thread local cannot be null.");
-                       super.set(value);
-               }
-
-       };
-}