webtier@glassfish.java.net

Re: Changing Locale Dynamically

From: <webtier_at_javadesktop.org>
Date: Tue, 15 Jun 2010 10:35:25 PDT

hi,
here is another retake on the whole issue. Since locale change is a cross cutting concern, its better that locale is set for pages without the page doing anything special for it. Plus the "do both" approach is bit bothersome. If you add a page in future,where you forget to add f:view, then again you will have locale problem for that page. Here is a clean approach to change locale,I did the following:

1)remove all f:view tags from pages(also remove f:loadBundle from pages).

2)change the swapLocale() method to:

public void swapLocale(ActionEvent event) {
        System.out.println("[swapLocale] Setting isEnglish to " + !isEnglish);
        isEnglish = !isEnglish;

        //FacesContext.getCurrentInstance().getViewRoot().setLocale(isEnglish?ENGLISH:SPANISH);
    }

notice that i commented out the last statement in the method. So now, its no longer the responsibility of a page to set locale.

3) getLocale() method as before, no changes in it:
public Locale getLocale() {
       
        if (isEnglish) {
           
            return (ENGLISH); // ENGLISH is Locale.ENGLISH
        } else {
           
            return (SPANISH);// SPANISH is Locale("es")
        }
    }

4)Here's the interesting part:
register a listener:
<lifecycle>
        <phase-listener>coreservlets.LifeCycleListener</phase-listener>
</lifecycle>

the listener code is:
import java.util.Locale;
import javax.el.ELContext;
import javax.el.ValueExpression;
import javax.faces.application.Application;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;

public class LifeCycleListener implements PhaseListener {

    public PhaseId getPhaseId() {
        return PhaseId.ANY_PHASE;
    }

    public void beforePhase(PhaseEvent event) {
        System.out.println("START PHASE " + event.getPhaseId());
        FacesContext context;

        if (event.getPhaseId() == PhaseId.RENDER_RESPONSE) {
            context = event.getFacesContext();
            Application application = context.getApplication();
            ValueExpression ve = application.getExpressionFactory().
                    createValueExpression(context.getELContext(),
                    "#{person.locale}", Locale.class);
            try {
                System.out.println("setting locale in phase listener");
                Locale localeToSet = (Locale) ve.getValue(context.getELContext());
                context.getViewRoot().setLocale(localeToSet);

            } catch (Exception e) {
                System.out.println("error in getting locale");
            }
        }

    }

    public void afterPhase(PhaseEvent event) {
        System.out.println("END PHASE " + event.getPhaseId());
    }
}

In the above code, the if block is run just before any page is rendered. Here we, take the #{person.locale} value and set it as UIViewRoot locale.

So now, no code in any page to change locale, no worry about forgetting the f:view, plus no dual setting.

Dont know, if you have read this http://balusc.blogspot.com/2006/09/debug-jsf-lifecycle.html . Its quite a informative article.

ps:am from india
[Message sent by forum member 'nash_era']

http://forums.java.net/jive/thread.jspa?messageID=474362