Using Localization with Vaadin Flow v24

Hello,

I am using Vaadin Flow version 24.4.4. I am trying to use localization in my Spring Boot app. I have followed the link i18n-localization. I have created a spring class component extending DefaultI18NProvider. I am using a language select so that the user can switch the language and setting the selected locale as shown below:

languageSelect.addValueChangeListener(e -> {
			selectedLanguage = languageSelect.getValue();

			if (selectedLanguage.getCode().equals(LocaleValues.LANG_EN)) {
				UI.getCurrent().setLocale(LOCALE_EN);
				UI.getCurrent().getSession().setLocale(LOCALE_EN);
			} else if (selectedLanguage.getCode().equals(LocaleValues.LANG_AR)) {
				UI.getCurrent().setLocale(LOCALE_AR);
				UI.getCurrent().getSession().setLocale(LOCALE_AR);
			}
			UI.getCurrent().refreshCurrentRoute(true);
		});

The translations don’t take affect unless I refresh the UI using this line: UI.getCurrent().refreshCurrentRoute(true);
Is there a better/correct way to do this?

Thanks in advance

1 Like

Try it.

languageSelect.addValueChangeListener(e -> {
    String selectedLanguage = e.getValue();

    getUI().ifPresent(ui -> {
        if ("English".equals(selectedLanguage)) {
            ui.setLocale(Locale.of("en", "GB"));
        } else if ("Arabic".equals(selectedLanguage)) {
            ui.setLocale(Locale.of("ar", "SA"));
        }
    });
});

Additionally, it must implement LocaleChangeObserver.

When you change the language using UI.setLocale, all components that implement LocaleChangeObserver will receive the event and can dynamically update their content without the need to refresh the page.

Using getUI().ifPresent is an improvement in terms of safety and readability. Furthermore, combining it with LocaleChangeObserver will make your application more responsive and efficient in managing translations.

Example

import com.vaadin.flow.component.combobox.ComboBox;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.i18n.LocaleChangeEvent;
import com.vaadin.flow.i18n.LocaleChangeObserver;

import java.util.Locale;

public class MyView extends VerticalLayout implements LocaleChangeObserver {

    private final Label translatedLabel = new Label();
    private final ComboBox<String> languageSelect = new ComboBox<>("Select Language");

    public MyView() {

        updateTexts(); // Initialize with default language

        // ComboBox for language selection
        languageSelect.setItems("English", "Arabic");
        languageSelect.addValueChangeListener(e -> {
            String selectedLanguage = e.getValue();

            getUI().ifPresent(ui -> {
                if ("English".equals(selectedLanguage)) {
                    ui.setLocale(Locale.of("en", "GB"));
                } else if ("Arabic".equals(selectedLanguage)) {
                    ui.setLocale(Locale.of("ar", "SA"));
                }
            });
        });

        add(languageSelect, translatedLabel);
    }

    @Override
    public void localeChange(LocaleChangeEvent event) {
        // Update texts when language changes
        updateTexts();
    }

    private void updateTexts() {
        // Translate the label based on the current locale
        translatedLabel.setText(getTranslation("welcome.label"));
    }
}

5 Likes

As @fred_pena already suggested, the LocaleChangeObserver should be used, then you don’t need to care about page reload/refresh.

Also, if you want to set a locale to a session, you don’t need to update a locale for a UI instance, because updating the session does automatically update all connected UIs.

Secondly, you can skip creating your own I18nProvider if you use Spring and don’t need customisations, Vaadin creates DefaultI18nProvider bean automatically that uses ResourceBundle under the hood.

Finally, I’d recommend to take a look into this example project for insights GitHub - vaadin/vaadin-localization-example: Example for Vaadin 14 how make a multilingual application.

By the way, cool that you found this new method refreshCurrentRoute, it helps to refresh the route (and it’s layouts) without reloading the entire browser page.

2 Likes

@fred_pena and @mikhail.21 Thank you so much for your quick response.

I was already using the LocaleChangeObserver and updating the direction of the components from left to right and vice versa which is by the way a wonderful feature.

I applied the code snippet “getUI().ifPresent…” and the updateTexts method then the localization worked like a charm.

I also, skipped using my own I18nProvider as I am using Spring.

I am new to Vaadin Flow and I am loving it.

Thank you so much guys!

2 Likes

I’m on the fence about recommending LocaleChangeObserver. It got in the way for us, where we have pages with reference data (think comboboxes) that need to be i18n aware - meaning the option’s text is different depending on the language. When you then have a form binder, things got quite complex and error-prone because of the view lifecycle and the moment when onLocaleChanged is called. It basically interfered with the binder, that was our experience. Maybe our page was too complex, or we did not understand the mechanism enough but in the end we dropped the observer, and just went with a full page refresh after the language is changed.

I do agree that for simple label translations, LocaleChangeObserver is the way to go.

Usually it’s enough to make a full page reload and it’s much easier. There are less corner cases.

2 Likes