Closed aaguilera closed 4 years ago
Thanks for the suggestion. I can see the value in providing a configuration property for Hibernate Validator's default locale, as doing it yourself requires quite a bit of code at the moment. For example, the equivalent of the current auto-configuration but with the default locale set to German, requires the following:
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public static LocalValidatorFactoryBean defaultValidator() {
LocalValidatorFactoryBean factoryBean = new LocalValidatorFactoryBean() {
@Override
protected void postProcessConfiguration(javax.validation.Configuration<?> configuration) {
if (configuration instanceof HibernateValidatorConfiguration) {
((HibernateValidatorConfiguration) configuration).defaultLocale(Locale.GERMAN);
}
}
};
MessageInterpolatorFactory interpolatorFactory = new MessageInterpolatorFactory();
factoryBean.setMessageInterpolator(interpolatorFactory.getObject());
return factoryBean;
}
I don't think we should use spring.mvc.locale
to control Hibernate Validator's locale. There's nothing MVC- or even web-specific about Hibernate Validator so I don't think its default locale should be tied to the spring.mvc.locale
property.
Thanks @wilkinsona. You're right about the name of the property name.
Anyway, I'm trying to use your example as a workaround, but it's not working for me. Hibernate Validator still falls back to the system locale (es_ES, in my computer), ignoring the custom configuration. Am I missing something else?
Sorry, I should have looked more closely at how Hibernate Validator uses the default locale and the effect that you were hoping for. LocalValidatorFactoryBean
will already wrap the MessageInterpolator
in a org.springframework.validation.beanvalidation.LocaleContextMessageInterpolator
that uses LocaleContextHolder
to determine the locale that should be used for message interpolation.
Having taken a step back, I'm no longer sure that there's much benefit in providing a configuration property that targets Hibernate validator. To help us to figure out what, if anything, we should do, can you please provide some more details about what behaviour you want to configure. A small sample zipped up and attached to this issue or pushed to a separate repository would be the ideal way to do that.
I have prepared a little demo at https://github.com/aaguilera/demo-springboot-issue-20673
This demo is a simple HTML form which shows a validation error message when submitted.
I need the error message to be show in the language of the user's browser, falling back to English whenever the user's browser is not any of the accepted languages (English, Spanish or Catalan).
Steps to reproduce:
Launch the application with mvn spring-boot:run
and connect to http://localhost:8080
If you want to simulate the application running on a different system locale, you can do it by launching the application like this:
LANG=es_ES.UTF-8 mvn spring-boot:run (simulates spanish system locale)
LANG=ca_ES.UTF-8 mvn spring-boot:run (simulates catalan system locale)
LANG=en_US.UTF-8 mvn spring-boot:run (simulates english system locale)
You will see an HTML form. Leave the field empty, and press the «submit» button.
The form will be validated, and an error message will appear next to the text field.
That error message is resolved by Spring via Hibernate Validator, using the Accept-Language
HTTP header to decide the Locale, obtaining messages from several files at src/main/resources
:
ValidationMessages_en.properties
ValidationMessages_es.properties
ValidationMessages_ca.properties
I'd like to be able to force the fallback locale as "english" (for example, en_US) regardless of the current system locale.
You can simulate the form submission with different "browser" languages with curl
. For example, the following requests work as expected regardless of the system locale:
curl -s -X POST http://localhost:8080 -H "Accept-Language: es" | grep name.errors
curl -s -X POST http://localhost:8080 -H "Accept-Language: ca" | grep name.errors
curl -s -X POST http://localhost:8080 -H "Accept-Language: en" | grep name.errors
But if you launch the server with LANG=es_ES.UTF-8 mvn spring-boot:run
, when you make a request in french:
curl -s -X POST http://localhost:8080 -H "Accept-Language: fr" | grep name.errors
The error message will be in spanish, and not in english.
Desired behavior: I want to be able to configure Spring Boot to force a fallback Locale for Hibernate Validator error messages.
Thanks for the sample. Unfortunately, I think it has shown that Hibernate Validator cannot easily be configured to do what you'd like. Hibernate Validator's default locale only comes into play when message interpolation is being performed without a locale. That doesn't happen here as, when a request is made with Accept-Language: fr
, Hibernate Validator's ResourceBundleMessageInterpolator
is called with fr
as the locale.
This call to the interpolator results in a call to PlatformResourceBundleLocator.getResourceBundle(Locale)
and in turn a call to the JDK's java.util.ResourceBundle.getBundle(String, Locale, ClassLoader)
. When no bundle is found for the fr
locale, it falls back to using Locale.getDefault()
which is picked up from the environment when the JVM is launched.
I think you have a few options, but I'm not sure how suitable they may be for your situation:
-Duser.language=en
to cause Locale.getDefault()
to be en
.Locale.setDefault(Locale.ENGLISH)
in your application's main method.MessageInterpolator
that uses a different fallback strategy. I believe you could implement that by calling java.util.ResourceBundle.getBundle(String, Locale, Control)
with a custom Control
sub-class that overrides getFallbackLocale(String, Locale)
to return Locale.ENGLISH
rather than Locale.getDefault()
.I'm going to close this issue as I don't think there's anything that we can reasonably do about this from a Spring Boot perspective. I'd recommend exploring option 1 or 2 above.
I will try your suggestions. Thank you very much for the follow-up Andy!
Did you ever find a solution for that? I am trying to disable translation of hibernate validation messages and keep them english for hours now... :(
Spring Boot 2.3 will upgrade Hibernate Validator to version 6.1.
This version allows for customization of locale resolution. See Custiomizing the locale resolution.
It would be nice if Spring Boot automatically configured Hibernate Validator to use the locale defined in
spring.mvc.locale
, if this property has been set.