0. Introduction
To manage i18n (internationalization) in Vaadin we need to:- Inform Vaadin which class will manage i18n.
- Create this i18n class (should implement the i18NProvider interface)
- Create resource bundles for each defined language
- Optionally create a language enumeration of all the languages used.
1. Informing Vaadin about the i18n responsible class
In the previous post, we saw the class that informed Vaadin about the use of CDI and also about the class that managed the i18n. As a reminder, Vaadin uses a class that extends VaadinServlet or CdiVaadinServlet (only for CDI) and the i18 manager class is defined in the @WebInitParam of the @WebServlet annotation of this class.
Here is again the source code of this class
Here is again the source code of this class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | package openadmin.listeners; import javax.servlet.annotation.WebInitParam; import javax.servlet.annotation.WebServlet; import com.vaadin.cdi.CdiVaadinServlet; import com.vaadin.flow.server.Constants; //import com.vaadin.flow.server.VaadinServlet; import com.vaadin.flow.server.VaadinServletConfiguration; /** * Information about app servlet * * Necessary for defining i18n Provider * @author ximo * */ @SuppressWarnings("serial") @WebServlet( urlPatterns = "/*", name = "slot", asyncSupported = true, initParams = { // I18N Provider for translation of labels @WebInitParam( name = Constants.I18N_PROVIDER, value = "openadmin.i18n.MyI18nProvider") }) @VaadinServletConfiguration(productionMode = false) //public class ApplicationServlet extends VaadinServlet { public class ApplicationServlet extends CdiVaadinServlet { } |
2. Creating the i18n managing class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | package openadmin.i18n; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Locale; import java.util.ResourceBundle; import java.util.stream.Collectors; import com.vaadin.flow.i18n.I18NProvider; @SuppressWarnings("serial") public class MyI18nProvider implements I18NProvider { //List of all the available locales @Override public List<Locale> getProvidedLocales() { return Collections.unmodifiableList( Arrays.stream(LangEnum.values()) .map(item -> new Locale(item.name())) .collect(Collectors.toList())); } /** * key -> bundle.key */ @Override public String getTranslation(String key, Locale locale, Object... params) { String loc=locale.getLanguage(); String[] bundle_key = key.split("\\."); ResourceBundle rsBundle = ResourceBundle.getBundle( "i18n." + bundle_key[0] + "_" + loc); if (! rsBundle.containsKey(bundle_key[1])) { System.out.println("missing resource key (i18n) " + key); //logger().info("missing resource key (i18n) " + key); return bundle_key[1] + " - " + locale; } else { return (rsBundle.containsKey(bundle_key[1])) ? rsBundle.getString(bundle_key[1]) : bundle_key[1]; } } public MyI18nProvider () { } } |
3. The resource bundles for the language
The resource bundles are stored in the src/main/resources/i18n folder (in this project, but not necessarily) , and there are several files, each file is named by a prefix followed by an underscore ("_"), the 2 digits of the locale, and the suffix ".properties". The prefixes are used for splitting a big property file into smaller and easier to manage ones. Here are some filename examples:
- "login_es.properties": Stores keys used for login and the Spanish translation
- "login_en.properties": Stores keys used for login and the English translation
- "messages_es.properties": Stores keys used for messages and the Spanish translation
- "messages_en.properties": Stores keys used for messages and the English translation
user = Usuario password = Contraseña login = Acceder invalid_credentials = Credenciales no válidas |
4. The language enumeration
Let's create a Java "enum" with the country (of the Locale) abbreviation and a description.
Methods are provided for getting the LangEnum from the description and getting the LangEnum from the Locale.
Here is the code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | package openadmin.i18n; import java.util.Locale; import lombok.Getter; public enum LangEnum { es ("Español"), ca ("Valencià"), en ("English"), fr ("Francaise"), de ("Deustch"), it ("Italiano"), ro ("Românesc"); @Getter private final String definition; private LangEnum(String definition) { this.definition=definition; } /** * Return the LangEnum that matches the definition * @param loc * @return */ public static LangEnum getLangEnum(String definition) { LangEnum lEnum=LangEnum.ca; for (LangEnum item: LangEnum.values()) if(item.getDefinition().equalsIgnoreCase(definition)) lEnum=item; return lEnum; } /** * Return the LangEnum that matches the locale * @param loc * @return */ public static LangEnum getFromLocale(Locale loc) { LangEnum lEnum=LangEnum.ca; for (LangEnum item: LangEnum.values()) if(item.name().equalsIgnoreCase(loc.getLanguage())) lEnum=item; return lEnum; } public static void main (String[] args) { /** Arrays.stream(LangEnum.values()) .map(LangEnum::getDefinition) .collect(Collectors.toList()); */ LangEnum le=LangEnum.getFromLocale(new Locale("es")) ; System.out.println(le.name()); le=LangEnum.getFromLocale(new Locale("ca")) ; System.out.println(le.name()); le=LangEnum.getFromLocale(new Locale("en")) ; System.out.println(le.name()); } } |
No hay comentarios:
Publicar un comentario