I18n Vaadin flow

Hi,

I’ve got a question about localization in Vaadin flow.
Will you implement a “transparent” way to internationalize Vaadin app ?

I read this documentation: https://vaadin.com/docs/v10/flow/advanced/tutorial-i18n-localization.html
Which means (if I understand correctly) that I (as a Vaadin developper) have to write getI18NProvider().getTranslation(“my.translation”, getUserId()) for each translated label/text … (I can also subclass vaadin textfield to I18nTextfield and override setCaption).

Is it possible to have something like we have in Hibernate validator (for example):
https://docs.jboss.org/hibernate/stable/validator/reference/en-US/html_single/?v=6.0#section-message-interpolation

For example, setCaption(“{my.translation}”) for a TextField. (A “default i18n provider” could be useful to externalize Vaadin SystemMessages or validator/required messages)

Thanks :slight_smile:

Thanks for the feedback. I think you have a really good point, the example you give from Hibernate is quite much less verbose and convenient compared to what we have now.

I’m not sure if we want to take the exactly same approach though, here is couple issues:

  • For me (before I saw the Hibernate spec), I cannot tell from looking at the code what should happen with the tf.setLabel("${foobar}").
  • Giving any parameters is an issue with using just a magic string syntax, since nobody wants to give overrides for their component methods for this
  • Using a magic string would mean that the Flow internals would have to do lots of checks for this to detect when the translations should be fetched and when not… unless we force the component developers to somehow mark their methods that control localizable content so that the framework could handle those automatically (this is one option we considered and might consider again)

But anyway, I think the getting of translation strings should be really easy to do, with one method call instead of two. Need to consider between the alternatives. There is an issue for this, please go and +1 and comment on it: https://github.com/vaadin/flow/issues/2919

Hi Pekka,

Thank you for your answer.
I don’t know if it’s related to this github issue but i will check this.

Here some explanations:
In Vaadin, you have a SystemMessagesProvider and every developer can change it with their own implementation.

For hibernate validator, it’s done by default in a I18N way (property file).
As Vaadin got a validation system, I thought this implementation is nice.

But you can also add a SystemMessagesprovider which does “nothing”. So every developer can write his own Messagesprovider to remove a lot of boilerplate code. (all I18nProvider.getTranslation(…))

For example, as a developer:

  • I can use Vaadin Designer without hardcoded caption inside my layout.

If you implement this inside Vaadin

Here the code to interpolate message in Hibernate validator.
https://github.com/hibernate/hibernate-validator/blob/master/engine/src/main/java/org/hibernate/validator/messageinterpolation/AbstractMessageInterpolator.java

For each message (i18n or not), it checks if the first character is ‘{’ (line 301 in their code).
This has to be documented in a i18n chapter.

This could be used for validators ( see this issue which is related to this “problem” https://github.com/vaadin/flow/issues/3228 ).
For asRequired, Vaadin can set a default value which may be overriden.
For SystemMessages, Vaadin can set a default value which may be overriden…
You can also use Vaadin Designer without hardcoding all the caption in the template.

Of course, this is a core feature and I don’t see all the impacts for every flow components (and extensions could use this). (This could be a problem https://github.com/vaadin/flow/issues/3371 )

I have same issue with Jean-Christophe Gueriaud, I want display message encode utf8 when use binder and javax.validation, but class BeanValidator always get default validator

I use vaadin 10 and spring boot 2.04

protected Context createContext(ConstraintViolation<?> violation) {
        return new ContextImpl(violation);
    }

    private static class LazyFactoryInitializer implements Serializable {
        private static final ValidatorFactory FACTORY = getFactory();

        private LazyFactoryInitializer() {
        }

        private static ValidatorFactory getFactory() {
            return Validation.buildDefaultValidatorFactory();
        }
    }