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;
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
super();
// Init list
- this.supportedLocales = new LinkedList<>();
+ this.supportedLocales = new LinkedHashMap<>(2);
}
/**
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;
}
* @param locale Locale
*/
public void setLocale (final Locale locale) {
+ System.out.println("Setting locale=" + locale);
this.locale = locale;
}
* @return Language code
*/
public String getLocaleCode () {
+ System.out.println("Getting this.localeCode=" + this.localeCode);
return this.localeCode;
}
* @param localeCode Language code
*/
public void setLocaleCode (final String localeCode) {
+ System.out.println("Setting localeCode=" + localeCode);
this.localeCode = localeCode;
}
* @return Selectable localizations
*/
@SuppressWarnings ("ReturnOfCollectionOrArrayField")
- public List<Locale> getSupportedLocales () {
+ public Map<String, Locale> getSupportedLocales () {
// Return full list
return this.supportedLocales;
}
*/
@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();
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);
<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>