<f:loadBundle> question

Hi gurus,

Here is a question I encountered during the usage of JSF.

And I'd like to localized my JSF application. In each page,

I use <f:loadBundle> tag to Load a resource bundle localized for the Locale of the current view. But the problem is that the locale of user specified should take higher priority than the language setting in browser in my application. How to change the locale

of the current view so that <f:loadBundle> can load the right resource bundle according to user's locale instead of browser setting.

I tried the following approach:

javax.faces.context.FacesContext ctx = FacesContext.getCurrentInstance();

if (ctx!=null)

{

UIViewRoot uiRoot = ctx.getViewRoot();

if (uiRoot!=null)

{

uiRoot.setLocale(userLoclae);

}

}

I called this when user just logged in and hope other pages respect the user specified locale instead of browser langauge setting. But it seems doesn't work.

Any ideas or suggestions are highly appreciated

Thanks,

Yushui

[1086 byte] By [ydua] at [2007-10-2 16:16:56]
# 1

Hello, try

[code

FacesContext context = FacesContext.getCurrentInstance();

context.getViewRoot().setLocale(userlocale)

][/code]

i took it from the cardemo sample application that is included in server faces implementation from sun.

Hmm maybe u can take a look at it , the sample application excactly do what u decribed,

Hope it helped

H.Prausea at 2007-7-13 17:08:12 > top of Java-index,Enterprise & Remote Computing,Web Tier APIs...
# 2

Hello , another thing that got in my mind , not sure if it help

make sure that the loca u set it registered in the faces config file

<locale-config>

<default-locale>de</default-locale>

<supported-locale>de</supported-locale>

</locale-config>

and make sure that propertie file exists

H.Prausea at 2007-7-13 17:08:12 > top of Java-index,Enterprise & Remote Computing,Web Tier APIs...
# 3
Hey, Thank you very much for your help. I take a look that demo, it's really what I want to do. But I can't find the source code of that demo. Could you point me where I can download it? Thanks,Yushui
ydua at 2007-7-13 17:08:12 > top of Java-index,Enterprise & Remote Computing,Web Tier APIs...
# 4
http://java.sun.com/javaee/javaserverfaces/download.htmlafter downloading it , extract it and the source code for it can b found undersamples/cardemo/src
H.Prausea at 2007-7-13 17:08:12 > top of Java-index,Enterprise & Remote Computing,Web Tier APIs...
# 5
Thanks alot. I got it. But seems that I am using the same approach with this demo. It works in this demo, but not in my application =(
ydua at 2007-7-13 17:08:12 > top of Java-index,Enterprise & Remote Computing,Web Tier APIs...
# 6

I had the same problem and solved the issue by explicitly naming all *.properties file, especially the default one too ( like portal_en.properties where you would normally go for just portal.properties)

You can debug the whole loading of resource bundles in class

org.apache.myfaces.taglib.core.LoadBundleTag

(if you are using myfaces)

tilmanRossmya at 2007-7-13 17:08:12 > top of Java-index,Enterprise & Remote Computing,Web Tier APIs...
# 7

I'm doing something fairly similar, and I'm using a custom ViewHandler.

This

> I called this when user just logged in and hope other pages respect the user

> specified locale instead of browser langauge setting. But it seems doesn't

> work.

is likely the source of your problem. It's not clear from your post where exactly you're invoking the code you reference, so I don't know if you're already doing this, but you likely want to make a custom ViewHandler that delegates all of its methods to a base ViewHandler except Locale creation. Otherwise it's not clear how any other view than the one immediately following authentication is going to know the Locale. Something like this:

public class CustomLocaleViewHandler extends ViewHandler

{

private final ViewHandler baseViewHandler;

public CustomLocaleViewHandler(ViewHandler base)

{

baseViewHandler = base;

}

public Locale calculateLocale(FacesContext facesContext)

{

// Put override logic here

}

... explicitly delegate all the other methods to the base handler

}

and place an entry in your faces-config that looks like

<view-handler>com.yourpackage.CustomLocaleViewHandler</view-handler>

Anyway, I think this should work if I understand your situation correctly.

Regards,

Peter

petergoldsteina at 2007-7-13 17:08:12 > top of Java-index,Enterprise & Remote Computing,Web Tier APIs...
# 8

thanx Peter, that was just what I needed. For those of you who struggle with jsf in a portlet container here is the rest of what you gotta do to communicate the new locale to the rest of the portlets (views):

In the BackingBean that sets the new locale do like this:

Locale ul = new Locale(userlocale);

viewRoot.setLocale(ul);

PortletSession portletSession = getPortletSession(context);

if (portletSession!=null)

{

portletSession.setAttribute(LanguageController.USER_LOCALE,ul,PortletSession.APPLICATION_SCOPE);

}

with getPortletSession(context):

private PortletSession getPortletSession(FacesContext facesContext) {

Object request = facesContext.getExternalContext().getRequest();

if (request != null)

{

if (request instanceof ActionRequest)

{

ActionRequest actionRequest = (ActionRequest) request;

PortletSession portletSession = actionRequest.getPortletSession();

return portletSession;

}

}

return null;

}

In your CustomViewHandler:

public Locale calculateLocale(FacesContext facesContext)

{

PortletSession portletSession = getPortletSession(facesContext);

if(portletSession!=null)

{

Object attribute = portletSession.getAttribute(LanguageController.USER_LOCALE, PortletSession.APPLICATION_SCOPE);

if(attribute!=null)

{

return (Locale) attribute;

}

}

return super.calculateLocale(facesContext);

}

but this time with a different getPortletSession(context):

private PortletSession getPortletSession(FacesContext facesContext) {

Object request = facesContext.getExternalContext().getRequest();

if (request != null)

{

if (request instanceof RenderRequest)

{

RenderRequest actionRequest = (RenderRequest) request;

PortletSession portletSession = actionRequest.getPortletSession();

return portletSession;

}

}

return null;

}

Tilman

tilmanRossmya at 2007-7-13 17:08:12 > top of Java-index,Enterprise & Remote Computing,Web Tier APIs...
# 9

Thanks a lot for your reply.

I am looking at the jsf demo: cardemo. It sets its locale through

chooseLocaleFromMap and chooseLocaleFromLink. In these function,

we can see the two common lines:

FacesContext context = FacesContext.getCurrentInstance();

context.getViewRoot().setLocale((Locale) locales.get(current));

I want to use the same mechnism to reset my locale and refect it to other pages as cardemo does.

Do you have any ideas about this?

Thanks,

Yushui

ydua at 2007-7-13 17:08:12 > top of Java-index,Enterprise & Remote Computing,Web Tier APIs...
# 10

The cardemo is actually not a good example of how to do localization in JSF.

The reason that cardemo works is not because it sets the Locale on the ViewRoot - essentially that has nothing to do with why you get Strings localized in a particular locale. The ViewRoot is being used as a short-term cache in this case, not as a key piece of the JSF framework.

Instead, the key to cardemo can be found in two methods. First, the resetMaps() method, which clears out all the Collections that have references to Objects with localized Strings. This method is invoked at the end of each method that handles a Locale selection event. So at the end of the ActionListener processing, all of the Strings corresponding to the old Locale are gone.

Now during the Render Response phase both the getCustomizers() and getModels() methods are invoked. These create new CarBean. In the init method of CarBean, which is invoked from the CarBean constructor, the localized Strings are looked up and cached. The Locale is obtained from the current view root, whose Locale was set in the ActionListener method (this is the short term cache). You could easily rewrite the code so it stored the Locale on CarStore, and didn't invoke the ViewRoot at all.

To see what's actually going on here, stick a loadBundle tag and a reference to a localized String on the page. You'll see that if you change the locale (say by changing the browser settings) the String in your page will update, but the cached CarBean values won't. If you use the map to pick a locale instead, the localized String will change briefly, but then switch back.

Anyway, I would avoid the technique in cardemo - it's not a real locale change. You're not actually persisting the locale change using that technique - it just looks like you are. There are cases in which you'd want to cache localized Strings, but even in those cases you should use something like the CustomLocaleViewHandler I posted earlier to make the locale change persistent for other, non-cached, localizable entities.

Regards,

Peter

petergoldsteina at 2007-7-13 17:08:12 > top of Java-index,Enterprise & Remote Computing,Web Tier APIs...
# 11
Thanks alot for your thorough explainations!I learned a lot from you. Thanks again
ydua at 2007-7-13 17:08:12 > top of Java-index,Enterprise & Remote Computing,Web Tier APIs...
# 12
When I change something in my_en.properties file this change is not visible immediatelly. So I guess there is some sort of cache.Is there a simple way to a) clear that cacheb) make this cache dependent of .properties file (like .jsp)(BTW:I am using WAS 6)
veljaca at 2007-7-13 17:08:12 > top of Java-index,Enterprise & Remote Computing,Web Tier APIs...