]> git.mxchange.org Git - jfinancials-war.git/commitdiff
Please cherry-pick:
authorRoland Häder <roland@mxchange.org>
Sat, 19 Aug 2017 11:18:04 +0000 (13:18 +0200)
committerRoland Häder <roland@mxchange.org>
Sat, 19 Aug 2017 11:20:20 +0000 (13:20 +0200)
- changed List to Map to have locale name (e.g. de_DE) as key and the locale
  itself as value stored in a map for a quick lookup
- this map is also being used to handle browser's language-only locales, like
  "de" and not "de_AT" or other equivalents
- there is now a submit button for JS-less users to change locale

Signed-off-by: Roland Häder <roland@mxchange.org>
src/java/org/mxchange/jfinancials/beans/localization/FinancialsLocalizationSessionBean.java
src/java/org/mxchange/localization/bundle_de_DE.properties
src/java/org/mxchange/localization/bundle_en_US.properties
web/WEB-INF/templates/base.tpl
web/WEB-INF/templates/generic/locale_selection_box.tpl

index a290f39cc53436e85a8cf1e0a73b23e3f4a96613..24bf5bd74038a5f55784e236cf7bab832dfa1cf7 100644 (file)
@@ -18,16 +18,16 @@ package org.mxchange.jfinancials.beans.localization;
 
 import java.text.MessageFormat;
 import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
+import java.util.LinkedHashMap;
 import java.util.Locale;
+import java.util.Map;
+import java.util.Objects;
 import javax.annotation.PostConstruct;
 import javax.enterprise.context.SessionScoped;
 import javax.enterprise.event.Event;
 import javax.enterprise.event.Observes;
 import javax.enterprise.inject.Any;
 import javax.faces.context.FacesContext;
-import javax.faces.event.ValueChangeEvent;
 import javax.inject.Inject;
 import javax.inject.Named;
 import org.mxchange.jcoreee.events.locale.LocaleChangeEvent;
@@ -71,9 +71,9 @@ public class FinancialsLocalizationSessionBean extends BaseFinancialsController
        private String localeCode;
 
        /**
-        * A list of all supported locales
+        * A map of all supported locales, using language code as key
         */
-       private final List<Locale> supportedLocales;
+       private final Map<String, Locale> supportedLocales;
 
        /**
         * Default constructor
@@ -83,7 +83,7 @@ public class FinancialsLocalizationSessionBean extends BaseFinancialsController
                super();
 
                // Init list
-               this.supportedLocales = new LinkedList<>();
+               this.supportedLocales = new LinkedHashMap<>(2);
        }
 
        /**
@@ -142,12 +142,56 @@ public class FinancialsLocalizationSessionBean extends BaseFinancialsController
                this.clear();
        }
 
+       /**
+        * Changes locale in application
+        */
+       public void doChangeLocale () {
+               // Is locale code set?
+               if (this.getLocaleCode() == null) {
+                       // Throw NPE
+                       throw new NullPointerException("this.localeCode is null");
+               } else if (this.getLocaleCode().isEmpty()) {
+                       // Throw IAE
+                       throw new IllegalArgumentException("this.localeCode is empty");
+               }
+
+               // Default new locale is null, will be handled later
+               Locale newLocale = null;
+
+               // Iterate over whole map
+               for (Map.Entry<String, Locale> entry : this.getSupportedLocales().entrySet()) {
+                       Locale foundLocale = entry.getValue();
+                       System.out.println(MessageFormat.format("foundLocale={0},this.localeCode={1}", foundLocale, this.getLocaleCode()));
+
+                       // Does the language match?
+                       if (Objects.equals(foundLocale.toString(), this.getLocaleCode())) {
+                               // Is found, take it as request locale
+                               newLocale = foundLocale;
+                               break;
+                       }
+               }
+
+               // Clear locale code field
+               this.clear();
+
+               // Has a matching locale
+               System.out.println("newLocale=" + newLocale);
+               if (null == newLocale) {
+                       // Throw NPE
+                       throw new NullPointerException("this.localeCode=" + this.getLocaleCode() + " cannot be found.");
+               }
+
+               // Then change it
+               this.changeLocale(newLocale);
+       }
+
        /**
         * Getter for locale
         * <p>
         * @return Locale
         */
        public Locale getLocale () {
+               System.out.println("Getting this.locale=" + this.locale);
                return this.locale;
        }
 
@@ -157,6 +201,7 @@ public class FinancialsLocalizationSessionBean extends BaseFinancialsController
         * @param locale Locale
         */
        public void setLocale (final Locale locale) {
+               System.out.println("Setting locale=" + locale);
                this.locale = locale;
        }
 
@@ -166,6 +211,7 @@ public class FinancialsLocalizationSessionBean extends BaseFinancialsController
         * @return Language code
         */
        public String getLocaleCode () {
+               System.out.println("Getting this.localeCode=" + this.localeCode);
                return this.localeCode;
        }
 
@@ -175,6 +221,7 @@ public class FinancialsLocalizationSessionBean extends BaseFinancialsController
         * @param localeCode Language code
         */
        public void setLocaleCode (final String localeCode) {
+               System.out.println("Setting localeCode=" + localeCode);
                this.localeCode = localeCode;
        }
 
@@ -184,7 +231,7 @@ public class FinancialsLocalizationSessionBean extends BaseFinancialsController
         * @return Selectable localizations
         */
        @SuppressWarnings ("ReturnOfCollectionOrArrayField")
-       public List<Locale> getSupportedLocales () {
+       public Map<String, Locale> getSupportedLocales () {
                // Return full list
                return this.supportedLocales;
        }
@@ -194,17 +241,12 @@ public class FinancialsLocalizationSessionBean extends BaseFinancialsController
         */
        @PostConstruct
        public void init () {
-               // Get locale instance from context
-               Locale currentLocale = FacesContext.getCurrentInstance().getExternalContext().getRequestLocale();
-
-               // Change locale, may set same back in faces context, but triggers event
-               this.changeLocale(currentLocale);
-
                // Get default locale
                Locale defaultLocale = FacesContext.getCurrentInstance().getApplication().getDefaultLocale();
+               System.out.println("defaultLocale=" + defaultLocale);
 
                // Add it to list
-               this.getSupportedLocales().add(defaultLocale);
+               this.getSupportedLocales().put(defaultLocale.toString(), defaultLocale);
 
                // Get iterator from faces context
                Iterator<Locale> iterator = FacesContext.getCurrentInstance().getApplication().getSupportedLocales();
@@ -213,71 +255,72 @@ public class FinancialsLocalizationSessionBean extends BaseFinancialsController
                while (iterator.hasNext()) {
                        // Get next locale
                        Locale supportedLocale = iterator.next();
+                       System.out.println("supportedLocale=" + supportedLocale);
 
                        // Add it
-                       this.getSupportedLocales().add(supportedLocale);
+                       this.getSupportedLocales().put(supportedLocale.toString(), supportedLocale);
                }
-       }
-
-       /**
-        * Listens on value-change event and changes locale accordingly, if found in
-        * list.
-        * <p>
-        * This method has been taken from
-        * https://www.mkyong.com/jsf2/jsf-2-internationalization-example/ and has
-        * been customized, e.g. checked parameter deeply. If the selected locale
-        * does not exist (someone changed the value in HTML form) then a proper
-        * exception is thrown.
-        * <p>
-        * @param event Event being triggered by JSF view/template
-        *
-        * @throws NullPointerException If event or newValue field is empty
-        * @throws IllegalArgumentException If newValue is empty or the locale does
-        * not exist
-        */
-       public void localeCodeChanged (final ValueChangeEvent event) {
-               // Validate event
-               if (null == event) {
-                       // Abort here
-                       throw new NullPointerException("event is null"); //NOI18N
-               } else if (event.getNewValue() == null) {
-                       // Abort again
-                       throw new NullPointerException("event.newValue is null"); //NOI18N
-               }
-
-               // First, get new value from event
-               String newCountryCode = event.getNewValue().toString();
 
-               // Is it valid?
-               if (null == newCountryCode) {
-                       // Abort here
-                       throw new NullPointerException("newCountryCode is null"); //NOI18N
-               } else if (newCountryCode.isEmpty()) {
-                       // Is empty
-                       throw new IllegalArgumentException("newCountryCode is empty"); //NOI18N
+               // Get locale instance from request (e.g. browser)
+               Locale requestLocale = FacesContext.getCurrentInstance().getExternalContext().getRequestLocale();
+
+               // Is no country code found?
+               if (requestLocale.getCountry().isEmpty()) {
+                       // Then try to find one
+                       System.out.println("Request locale is without country information, looking up in map ...");
+
+                       // Get language from it
+                       String language = requestLocale.getLanguage();
+                       Boolean found = Boolean.FALSE;
+
+                       // Iterate over whole map
+                       for (Map.Entry<String, Locale> entry : this.getSupportedLocales().entrySet()) {
+                               String languageCode = entry.getKey();
+                               Locale foundLocale = entry.getValue();
+                               System.out.println(MessageFormat.format("languageCode={0},language={1}", languageCode, language));
+
+                               // Does the language match?
+                               if (languageCode.startsWith(language)) {
+                                       // Is found, take it as request locale
+                                       requestLocale = foundLocale;
+                                       found = Boolean.TRUE;
+                                       break;
+                               }
+                       }
+
+                       // Nothing found?
+                       if (!found) {
+                               // Then set default locale
+                               requestLocale = defaultLocale;
+                       }
                }
 
-               // Generate locale from new value (which is the 2-letter country code)
-               Locale newLocale = new Locale(newCountryCode);
-
-               // Lookup locale in list, very easy
-               if (!this.getSupportedLocales().contains(newLocale)) {
-                       // Locale is not in supportedLocales list
-                       throw new IllegalArgumentException(MessageFormat.format("Country code {0} is not supported.", newCountryCode)); //NOI18N
-               }
-
-               // All fine, then change locale
-               this.changeLocale(newLocale);
+               // Change locale, may set same back in faces context, but triggers event
+               this.changeLocale(requestLocale);
        }
 
        /**
-        * Changes current locale in this controller and faces context to given
+        * Changes current locale in this controller and faces context to given.
+        * This method makes sure that locales with at least language and country
+        * information are being changed to.
         * <p>
         * @param locale New locale to set
         */
        private void changeLocale (final Locale locale) {
-               // Set locale here
+               // Is the locale language_country at least?
+               if (null == locale) {
+                       // Throw NPE
+                       throw new NullPointerException("locale is null");
+               } else if (!locale.toString().contains("_")) {
+                       // Throw IAE
+                       throw new IllegalArgumentException(MessageFormat.format("locale={0} does not have country information set.", locale));
+               }
+
+               System.out.println("Changing locale to " + locale + " ...");
+
+               // Set locale + code here
                this.setLocale(locale);
+               this.setLocaleCode(locale.toString());
 
                // Inform faces context
                FacesContext.getCurrentInstance().getViewRoot().setLocale(locale);
index b624c2901877d3a991c9e52ecc3298a25b923ef9..eedf9d20867ac420b0996e545137beb24a8482c2 100644 (file)
@@ -864,3 +864,7 @@ ADMIN_BUSINESS_DATA_COMPANY_EMAIL_ADDRESS=Haupt-Email-Adresse:
 #@TODO Please fix German umlauts!
 BUTTON_ADMIN_CONTINUE_BUSINESS_CONTACT_PERSON=Basisdaten hinzufuegen
 ERROR_GUEST_REGISTRATION_IN_INDEX_ENABLED=Fehler: Falscher Aufruf der Anmeldeseite, da die Eingangsseite als Anmeldeseite fungiert.
+#@TODO Please fix German umlauts!
+BUTTON_CHANGE_LOCALE=Aendern
+#@TODO Please fix German umlauts!
+BUTTON_CHANGE_LOCALE_TITLE=Aendern Sie hier in der aktuellen Sitzung die angezeigte Sprache.
index 02360c17da97b1fa784395494517cfbbf4043b8e..4118bf176f9149f9bc56d2f3c7745d66afe0b3d1 100644 (file)
@@ -831,3 +831,5 @@ ADMIN_BUSINESS_DATA_COMPANY_EMAIL_ADDRESS=Main email address:
 BUTTON_ADMIN_CONTINUE_BUSINESS_CONTACT_PERSON=Add basic data
 #Fehler: Falscher Aufruf der Anmeldeseite, da die Eingangsseite als Anmeldeseite fungiert.
 ERROR_GUEST_REGISTRATION_IN_INDEX_ENABLED=Error: Wrong request on registration page as the index page serves as registration page.
+BUTTON_CHANGE_LOCALE=Change
+BUTTON_CHANGE_LOCALE_TITLE=Change here in your current session the used language for text output.
index 4f96022dd821684c68100358fbf4c72fda3781c8..3c24222dfa40b167ea9dcbf57511d900bcd4207e 100644 (file)
@@ -6,27 +6,27 @@
 
        <h:doctype rootElement="html" public="-//W3C//DTD XHTML 1.0 Transitional//EN" system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"/>
        <html lang="#{localizationController.locale.language}" xml:lang="#{localizationController.locale.language}" xmlns="http://www.w3.org/1999/xhtml">
-               <ui:insert name="metadata" />
+               <f:view locale="#{localizationController.locale}" contentType="text/html">
+                       <h:head>
+                               <ui:insert name="metadata" />
 
-               <h:head>
-                       <meta http-equiv="Content-Type" content="text/htmlcharset=UTF-8" />
+                               <meta http-equiv="Content-Type" content="text/htmlcharset=UTF-8" />
 
-                       <f:loadBundle var="msg" basename="org.mxchange.localization.bundle" />
+                               <f:loadBundle var="msg" basename="org.mxchange.localization.bundle" />
 
-                       <h:outputStylesheet name="/css/default.css" />
-                       <h:outputStylesheet name="/css/cssLayout.css" />
+                               <h:outputStylesheet name="/css/default.css" />
+                               <h:outputStylesheet name="/css/cssLayout.css" />
 
-                       <title>
-                               <h:outputText value="JFinancials" />
-                               <h:outputText value=" - " />
-                               <ui:insert name="title">
-                                       <h:outputText value="Default title" />
-                               </ui:insert>
-                       </title>
-               </h:head>
+                               <title>
+                                       <h:outputText value="JFinancials" />
+                                       <h:outputText value=" - " />
+                                       <ui:insert name="title">
+                                               <h:outputText value="Default title" />
+                                       </ui:insert>
+                               </title>
+                       </h:head>
 
-               <h:body>
-                       <f:view locale="#{localizationController.locale}" contentType="text/html">
+                       <h:body>
                                <div id="top">
                                        <div id="page_header">
                                                <div id="page_title">
 
                                <h:panelGroup id="menu_content" layout="block">
                                        <div id="left">
-                                               <ui:insert name="menu">Default menu</ui:insert>
+                                               <ui:insert name="menu">
+                                                       <h:outputText value="Default menu" />
+                                               </ui:insert>
                                                <ui:include src="/WEB-INF/templates/generic/locale_selection_box.tpl" />
                                        </div>
 
                                        <h:panelGroup id="content_outer" class="left_content" layout="block">
                                                <div id="content_header">
-                                                       <ui:insert name="content_header">Default content header</ui:insert>
+                                                       <ui:insert name="content_header">
+                                                               <h:outputText value="Default content header" />
+                                                       </ui:insert>
                                                </div>
 
                                                <div id="content">
-                                                       <ui:insert name="content">Default content</ui:insert>
+                                                       <ui:insert name="content">
+                                                               <h:outputText value="Default content" />
+                                                       </ui:insert>
                                                </div>
                                        </h:panelGroup>
 
                                </h:panelGroup>
 
                                <h:panelGroup id="page_footer" layout="block">
-                                       <ui:insert name="footer">Default footer</ui:insert>
+                                       <ui:insert name="footer">
+                                               <h:outputText value="Default footer" />
+                                       </ui:insert>
                                </h:panelGroup>
 
                                <h:panelGroup styleClass="error_container" layout="block">
                                        <h:messages showDetail="true" errorClass="errors" fatalClass="errors" warnClass="errors" />
                                </h:panelGroup>
-                       </f:view>
-               </h:body>
+                       </h:body>
+               </f:view>
        </html>
 </ui:composition>
index b956a276dea9ab13e5cc1bb1588842c1bd54f2b1..c4b41bc668387043f64e8beed4a3707de2551906 100644 (file)
@@ -5,10 +5,16 @@
        xmlns:h="http://java.sun.com/jsf/html"
        xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
 
-       <h:form id="form_locale_selection">
-               <h:selectOneMenu id="language_selection" styleClass="select" value="#{localizationController.localeCode}" onchange="submit()" valueChangeListener="#{localizationController.localeCodeChanged}">
-                       <f:selectItem itemLabel="#{msg.SELECT_LANGUAGE}" noSelectionOption="true" />
-                       <f:selectItems value="#{localizationController.supportedLocales}" var="locale" itemValue="#{locale}" itemLabel="#{msg[locale.toString().toUpperCase()]}" />
-               </h:selectOneMenu>
+       <h:form>
+               <h:panelGroup layout="block" styleClass="locale_selection_container">
+                       <h:panelGroup layout="block">
+                               <h:selectOneMenu styleClass="select" value="#{localizationController.localeCode}" onchange="submit()">
+                                       <f:selectItem itemLabel="#{msg.SELECT_LANGUAGE}" noSelectionOption="true" itemDisabled="true" />
+                                       <f:selectItems value="#{localizationController.supportedLocales}" var="locale" itemValue="#{locale}" itemLabel="#{msg[locale.toString().toUpperCase()]}" />
+                               </h:selectOneMenu>
+                       </h:panelGroup>
+
+                       <h:commandButton styleClass="submit" type="submit" action="#{localizationController.doChangeLocale()}" value="#{msg.BUTTON_CHANGE_LOCALE}" title="#{msg.BUTTON_CHANGE_LOCALE_TITLE}" />
+               </h:panelGroup>
        </h:form>
 </ui:composition>