package org.jboss.seam.international; import static org.jboss.seam.annotations.Install.BUILT_IN; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.StringTokenizer; import javax.faces.context.FacesContext; import javax.faces.event.ValueChangeEvent; import javax.faces.model.SelectItem; import javax.servlet.ServletRequest; import org.jboss.seam.Component; import org.jboss.seam.ScopeType; import org.jboss.seam.annotations.Create; import org.jboss.seam.annotations.Install; import org.jboss.seam.annotations.Name; import org.jboss.seam.annotations.Scope; import org.jboss.seam.annotations.intercept.BypassInterceptors; import org.jboss.seam.contexts.Contexts; import org.jboss.seam.core.Events; import org.jboss.seam.faces.Selector; import org.jboss.seam.util.Strings; import org.jboss.seam.web.ServletContexts; /** * Selects the current user's locale * * @author Gavin King */ @Scope(ScopeType.SESSION) @Name("org.jboss.seam.international.localeSelector") @BypassInterceptors @Install(precedence=BUILT_IN, classDependencies="javax.faces.context.FacesContext") public class LocaleSelector extends Selector { private static final long serialVersionUID = -6087667065688208261L; private String language; private String country; private String variant; @Create public void initLocale() { String localeString = getCookieValueIfEnabled(); if (localeString!=null) setLocaleString(localeString); } @Override protected String getCookieName() { return "org.jboss.seam.core.Locale"; } /** * Force the resource bundle to reload, using the current locale, * and raise the org.jboss.seam.localeSelected event. */ public void select() { FacesContext.getCurrentInstance().getViewRoot().setLocale( getLocale() ); //Contexts.removeFromAllContexts("org.jboss.seam.core.resourceBundle"); Contexts.removeFromAllContexts("org.jboss.seam.international.messages"); setCookieValueIfEnabled( getLocaleString() ); if ( Events.exists() ) { Events.instance().raiseEvent( "org.jboss.seam.localeSelected", getLocaleString() ); } } public void select(ValueChangeEvent event) { setLocaleString( (String) event.getNewValue() ); select(); } /** * Set the language and force resource bundle reload, useful for quick action links: * <tt><h:commandLink value="DE" action="#{localeSelector.selectLanguage('de')}"/>"/></tt> */ public void selectLanguage(String language) { setLanguage(language); select(); } public Locale calculateLocale(Locale jsfLocale) { if ( !Strings.isEmpty(variant) ) { return new java.util.Locale(language, country, variant); } else if ( !Strings.isEmpty(country) ) { return new java.util.Locale(language, country); } else if ( !Strings.isEmpty(language) ) { return new java.util.Locale(language); } else { return jsfLocale; } } public void setLocale(Locale locale) { language = Strings.nullIfEmpty( locale.getLanguage() ); country = Strings.nullIfEmpty( locale.getCountry() ); variant = Strings.nullIfEmpty( locale.getVariant() ); } public String getLocaleString() { return getLocale().toString(); } public void setLocaleString(String localeString) { StringTokenizer tokens = new StringTokenizer(localeString, "-_"); language = tokens.hasMoreTokens() ? tokens.nextToken() : null; country = tokens.hasMoreTokens() ? tokens.nextToken() : null; variant = tokens.hasMoreTokens() ? tokens.nextToken() : null; } public List<SelectItem> getSupportedLocales() { List<SelectItem> selectItems = new ArrayList<SelectItem>(); Iterator<Locale> locales = FacesContext.getCurrentInstance().getApplication().getSupportedLocales(); while ( locales.hasNext() ) { Locale locale = locales.next(); if ( !Strings.isEmpty( locale.getLanguage() ) ) { selectItems.add( new SelectItem( locale.toString(), locale.getDisplayName(locale) ) ); } } return selectItems; } /** * Get the selected locale */ public Locale getLocale() { FacesContext facesContext = FacesContext.getCurrentInstance(); if (facesContext!=null) { //Note: this does a double dispatch back to LocaleSelector.calculateLocale() return facesContext.getApplication().getViewHandler().calculateLocale(facesContext); } ServletContexts servletContexts = ServletContexts.getInstance(); if (servletContexts!=null) { ServletRequest request = servletContexts.getRequest(); if (request!=null) { return calculateLocale( request.getLocale() ); } } return calculateLocale( Locale.getDefault() ); } public static LocaleSelector instance() { if ( !Contexts.isSessionContextActive() ) { throw new IllegalStateException("No active session context"); } return (LocaleSelector) Component.getInstance(LocaleSelector.class, ScopeType.SESSION); } public String getCountry() { if (country==null) return getLocale().getCountry(); return country; } public void setCountry(String country) { setDirty(this.country, country); this.country = country; } public String getLanguage() { if (language==null) return getLocale().getLanguage(); return language; } public void setLanguage(String language) { setDirty(this.language, language); this.language = language; } public String getVariant() { if (variant==null) return getLocale().getVariant(); return variant; } public void setVariant(String variant) { setDirty(this.variant, variant); this.variant = variant; } }