Multi Language Support and i18n for Views designed with the vaadin designer

I try to to internationalizing my Vaadin-Application, but don’t know how to do this for my declarativ designs designed by vaadin-designer. Is there a solution for it?
Thanks and regards!

Hi Zafer,
I think there is no ready-to-use solution in the vaadin-designer.
What you would basically do is to manually set the caption via a ResourceBundle. (e.g. how it is done
here
)

It’s pretty annoying to do it for a lot of elements, so I did some hacking with reflections, something like this:

import com.vaadin.ui.Component;
import com.vaadin.ui.HasComponents;
import java.lang.reflect.Field;
import java.util.Locale;
import java.util.ResourceBundle;
public class CaptionTranslator {
  public static void setCaptions(HasComponents container, Locale locale){
    Field fields = container.getClass().getDeclaredFields();
    ResourceBundle resourceBundle = ResourceBundle.getBundle("captions", locale);
      for (Field currentField: fields){ currentField.setAccessible(true);
        try {
          Object component = currentField.get(container);
          if (component instanceof HasComponents){
            setCaptions((HasComponents) component, locale);
          } else if (component instanceof Component){
             String currentFieldName = currentField.getName();
             if (resourceBundle.containsKey(currentFieldName)){
               ((Component) component).setCaption(ResourceBundle.getBundle("captions", locale).getString(currentFieldName));
             } else {
                System.err.println("caption not found in resourcebundle for component " + currentFieldName);
             }
          }
       } catch (IllegalAccessException e) {
          //do something nice here
       }
     }
   }
}

Usage:

CaptionTranslator.setCaptions(layout, new Locale("de"));

This will translate all components in the layout with “de”-locale (german) and assumes you have a resource bundle “captions.properties” for your languages.
layout could be the object generated from vaadin designer.
If you missed a translation in your resource bundle it will print an error "caption not found in resourcebundle for component textFieldName"

Hope you get some hints from this.

Edit:
The resource bundle would contain your component names. Some more checks would be necessary, I tried to modify the code accordingly but have not checked it in real vaadin code.

Edit2:
changed the code so that it actually works :wink:

Kind regards
Olli

Hi Oliver,
Thank you very much for your quick response. After a long research on the internet, I had already feared that the solution would be a
hack. Thank you also for this hack. Sometimes I’m wondering if I’m the only one who uses Vaadin to create a Web application for global companies, or the only one using the designer, because an i18n theme should be standard?
Many greetings
Zafer

I don’t use Vaadin designer because there is no i18n (I don’t put caption/text inside code or design) and there is no way no use custom component (which is the first thing you will do for an application, for example to create a I18nButton).

I think the next version of Vaadin Designer (for Vaadin 10) will allow custom components (which will allow to extend component to i18n component).

I want make i18n languages vaadin app, but only sith spring java it is possible put messages to buttons, textfields labels texts, in V 10 will full i18n standard i read in documentation, i hope V10 will released soon

The easiest way for me was to register a second servlet to “/frontend/src” that provided the translated “*.html” Layouts. I defined Keys for ex. ##key.key## and then had the new Servlet read the HTML-Layout-File and replace the key with the translated text. The translated File was then returned at the requested URL using the HTTPServlet example with Spring:

@Component
public class HtmlServer extends HttpServlet{

	@Autowired
	TranslationProvider tp;
	
	@Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter pw = response.getWriter();
        pw.print(loadStringForPath(request, request.getPathInfo()));
        pw.flush();
    }
	
	private String loadStringForPath(HttpServletRequest httprequest, String path)
	{
		path = "/frontend/src" + path;
		System.out.println(path);
		try {
			InputStream is = httprequest.getServletContext().getResourceAsStream(path);
			if(is == null)
			{
				return "";
			}
			StringBuilder sb = new StringBuilder();
			String line = null;
			BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8));
			while ((line = bufferedReader.readLine()) != null) {
				sb.append(line+ "\n");
			}
			String s = sb.toString();
			while(s.indexOf("##") >=0)
			{
				int idx1 = s.indexOf("##");
				int idx2 = s.indexOf("##", idx1 +1);
				String key = s.substring(idx1+2, idx2);
				String replacement = tp.getTranslation(key);
				s = s.substring(0, idx1) + replacement + s.substring(idx2 + 2,s.length() -1);
			}
			return s;
		}catch(Exception e)
		{
			e.printStackTrace();
		}
		return "<html><body>test</body></html>";
	}
}

and in one Configuration file:

	@Bean
	public ServletRegistrationBean<HtmlServer> registerHtmlServer(@Autowired HtmlServer htmls)
	{
		return new ServletRegistrationBean<>(htmls,"/frontend/src/*");
	}