I18N localization
Defining the i18n provider property
The i18n.provider
property can be set from the command line as a system property, as a Servlet init parameter in the web.xml
or using the @WebServlet
annotation.
As a system property the parameter needs the vaadin
prefix e.g.:
bash
When using the annotation you could have the servlet class as:
Java
@WebServlet(urlPatterns = "/*", name = "slot", asyncSupported = true, initParams = {
@WebInitParam(name = Constants.I18N_PROVIDER, value = "com.vaadin.example.ui.TranslationProvider") })
public class ApplicationServlet extends VaadinServlet {
}
Or when using the web.xml
file:
You may provide a I18NProvider
as a bean in case you are using Spring. All you need in this case it’s just annotate your implementation with @Component
so it becomes available as a Spring bean. Spring add-on will automatically use it in case if it’s available. See the class SimpleI18NProvider.java implemented in the tutorial project as an example.
Locale selection for new session
The initial locale is decided by matching the locales provided by the I18NProvider
against the Accept-Language
header in the initial response from the client.
If an exact match (language + country) is found that will then be used, else we will try to match on only language. If neither is found the locale will be set to the first ‘supported’ locale from I18NProvider.getProvidedLocales()
and if that is empty Locale.getDefault()
will be used.
For this example we enable Finnish and English to be used with Finnish being the “default” that is used if the user client doesn’t specify english as an accepted language.
In this sample the language .properties
files start with “translate” e.g. translate.properties
(for default), translate_fi_FI.properties
and translate_en_GB.properties
The translation properties files are in the example loaded using the class loader so they should be located on the classpath for example in the resources folder e.g. src/main/resources
for a default maven setup.
Sample i18n provider implementation
public class TranslationProvider implements I18NProvider {
public static final String BUNDLE_PREFIX = "translate";
public final Locale LOCALE_FI = new Locale("fi", "FI");
public final Locale LOCALE_EN = new Locale("en", "GB");
private List<Locale> locales = Collections
.unmodifiableList(Arrays.asList(LOCALE_FI, LOCALE_EN));
private static final LoadingCache<Locale, ResourceBundle> bundleCache = CacheBuilder
.newBuilder().expireAfterWrite(1, TimeUnit.DAYS)
.build(new CacheLoader<Locale, ResourceBundle>() {
@Override
public ResourceBundle load(final Locale key) throws Exception {
return initializeBundle(key);
});
@Override
public List<Locale> getProvidedLocales() {
return locales;
}
@Override
public String getTranslation(String key, Locale locale, Object... params) {
if (key == null) {
LoggerFactory.getLogger(TranslationProvider.class.getName())
.warn("Got lang request for key with null value!");
return "";
}
final ResourceBundle bundle = bundleCache.getUnchecked(locale);
String value;
try {
value = bundle.getString(key);
} catch (final MissingResourceException e) {
LoggerFactory.getLogger(TranslationProvider.class.getName())
.warn("Missing resource", e);
}
if (params.length > 0) {
}
return value;
}
private static ResourceBundle initializeBundle(final Locale locale) {
return readProperties(locale);
}
protected static ResourceBundle readProperties(final Locale locale) {
final ClassLoader cl = TranslationProvider.class.getClassLoader();
ResourceBundle propertiesBundle = null;
try {
propertiesBundle = ResourceBundle.getBundle(BUNDLE_PREFIX, locale,
cl);
} catch (final MissingResourceException e) {
LoggerFactory.getLogger(TranslationProvider.class.getName())
.warn("Missing resource", e);
}
return propertiesBundle;
}
}
Using the internationalization in the application is a combination of using the I18NProvider and updating the translations on locale change.
To make this simple the application classes that control the captions and texts that are localized can implement the LocaleChangeObserver
to receive events for locale change.
This observer will also be notified on navigation in the attach phase of before navigation after any url parameters are set, so that the state from a url parameter can be used.
Java
Using localization without using LocaleChangeObserver
I18NProvider without LocaleChangeObserver
public class MyLocale extends Div {
public MyLocale() {
setText(getTranslation("my.translation", getUserId()));