4

Situation: I have a vaadin-spring application in which I have to let the user change the language at login. I use a combo box at the login page to switch between locales. The spring locale resolver implementation is CookieLocaleResolver because I'd like to store the selected option for the next visit in a cookie.

@Bean
public LocaleResolver localeResolver() {
    CookieLocaleResolver localeResolver = new CookieLocaleResolver();
    localeResolver.setDefaultLocale(new Locale("de", "DE"));
    localeResolver.setCookieName("locale");
    localeResolver.setCookieMaxAge( 60 * 60 * 24 * 31);
    return localeResolver;
}

View:

@SpringView(name = "login")
public class LoginView implements View {
    @Autowired
    private HttpServletRequest request;

    @Autowired
    private HttpServletResponse response;

    @Autowired
    private LocaleResolver localeResolver;

    ComboBox<LanguageOption> languageField;
    // ...
    languageField.addValueChangeListener(option -> {
        localeResolver.setLocale(request, response, option.getValue().getLocale());
    });
    // ...
}

Changing the combobox sets a cookie called locale to the desired language locale (for example de_DE). The default language in the locale resolver is de_DE. At the login, I can change between two options: de_DE and en_US.

The caption and text translation in the vaadin views is done by spring messageSource:

someCompoenent.setCaption(messageSource.getMessage("someComponent.caption", args, LocaleContextHolder.getLocale()));

In the Vaadin UI, I call the following to set the locale on the session and on the UI:

public class MyUI extends UI implements ViewDisplay, ViewAccessControl {
    @Autowired
    private HttpServletRequest httpServletRequest;

    // ...
    @Override
    protected void init(VaadinRequest request) {
        // ...
        Locale currentLocale = localeResolver.resolveLocale(httpServletRequest);
        LocaleContextHolder.setLocale(currentLocale);

        setLocale(currentLocale);
        VaadinSession.getCurrent().setLocale(currentLocale);

        // ...
    }

}

My problem is: when I choose the de_DE locale in the language combobox on the login page and I login, the LocaleContextHolder.getLocale() returns en_US and the UI is in english. However, if I hit F5 on the browser and refresh the page, the UI becomes de_DE.

Why?

A note: I noticed that before login and after login the JSESSONID cookie changes. I don't know if it matters in resolving the locale while the locale cookie is present and it's the same before and after login.

kruzexx
  • 131
  • 6

2 Answers2

1

The problem was that there is a RequestContextFilter in the filter chain which overwrites the locale resolved by the localeResolver with a default value in every request.

The quick solution is to resolve the locale manually in the message service:

Locale locale = localeResolver.resolveLocale(SpringVaadinServletRequest.getCurrent());

And use this locale for translation.

kruzexx
  • 131
  • 6
0

Your problem is that - once the Vaadin UI is created - you do not change the locale on the UI object. You only change it on the LocaleResolver which is a Spring component. Hitting F5 for refresh page in browser creates a new UI and therefore applies the new language.

I am not 100% sure but I think it doesn't help to invoke additionally yourUi.setLocale(currentLocale) when your language selection changes. This is because Vaadin components like Label are already created and set with translated text. So, if you really want to change the language in-place without recreating the whole UI, you must update all Vaadin components to show texts in new language. However, this is a lot of effort I guess.

My solution was to inform user and recreate the session:

Page.getCurrent().setLocation("");
VaadinSession.getCurrent().close();

Anyway, when the user visits your site the first time (without cookie), the browser sends the preferred language of the user which is picked up by Vaadin as default language. This will be sufficient for most of the users.

Steffen Harbich
  • 2,639
  • 2
  • 37
  • 71
  • I tried to refresh the page, set the page's location to "" and close the Vaadin session but the UI still appears in the wrong language at first. – kruzexx Feb 07 '18 at 15:08
  • I also set the UI locale. I have a `setLocale(currentLocale);` call before the Vaadin session setLocale call. It look like that my problem is the `LocaleContextHolder.getLocale()`. It returns en_US, but if i refresh the page, it returns de_DE correctly. The login page appears on the correct langauge (on the one I set in the cookie). – kruzexx Feb 07 '18 at 15:10
  • Can you try `msgSource.getMessage("someComponent.caption", args, UI.getCurrent().getLocale())` please? Does it change anything? – Steffen Harbich Feb 08 '18 at 09:35
  • There was a filter which overwrote the locale in every request. Explained in my answer. Thanks for your help! – kruzexx Feb 19 '18 at 10:31