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
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/*");
}