Skip to content

Commit

Permalink
HV-1748 HV-1749 Add some documentation about the localization support
Browse files Browse the repository at this point in the history
  • Loading branch information
gsmet committed Jan 15, 2020
1 parent c4dfc46 commit 582db15
Show file tree
Hide file tree
Showing 2 changed files with 127 additions and 0 deletions.
52 changes: 52 additions & 0 deletions documentation/src/main/asciidoc/ch12.asciidoc
Expand Up @@ -51,6 +51,9 @@ Note that when a package is part of the public API this is not necessarily true
`org.hibernate.validator.spi.constraintdefinition`::
An SPI for registering additional constraint validators programmatically, see <<section-constraint-definition-contribution>>.

`org.hibernate.validator.spi.messageinterpolation`::
An SPI that can be used to tweak the resolution of the locale when interpolating the constraint violation messages. See <<section-locale-resolver>>.

`org.hibernate.validator.spi.nodenameprovider`::
An SPI that can be used to alter how the names of properties will be resolved when the property path is constructed. See <<section-property-node-name-provider>>.

Expand Down Expand Up @@ -443,6 +446,55 @@ error messages from other resource bundles than _ValidationMessages_ while still
interpolation algorithm as defined by the specification. Refer to
<<section-resource-bundle-locator>> to learn how to make use of that SPI.

[[section-locale-resolver]]
=== Customizing the locale resolution

[WARNING]
====
These contracts are marked as `@Incubating` so they might be subject to change in the future.
====

Hibernate Validator provides several extension points to build a custom locale resolution strategy.
The resolved locale is used when interpolating the constraint violation messages.

The default behavior of Hibernate Validator is to always use the system default locale (as obtained via `Locale.getDefault()`).
This might not be the desired behavior if, for example, you usually set your system locale to `en-US` but want your application to provide messages in French.

The following example shows how to set the Hibernate Validator default locale to `fr-FR`:

[[example-configure-default-locale]]
.Configure the default locale
====
[source, JAVA, indent=0]
----
include::{sourcedir}/org/hibernate/validator/referenceguide/chapter12/localization/LocalizationTest.java[tags=default-locale]
----
====

While this is already a nice improvement, in a fully internationalized application, this is not sufficient:
you need Hibernate Validator to select the locale depending on the user context.

Hibernate Validator provides the `org.hibernate.validator.spi.messageinterpolation.LocaleResolver` SPI
which allows to fine-tune the resolution of the locale.
Typically, in a JAX-RS environment, you can resolve the locale to use from the `Accept-Language` HTTP header.

In the following example, we use a hardcoded value but, for instance, in the case of a RESTEasy application,
you could extract the header from the `ResteasyContext`.

[[example-locale-resolver]]
.Fine tune the locale used to interpolate the messages via a `LocaleResolver`
====
[source, JAVA, indent=0]
----
include::{sourcedir}/org/hibernate/validator/referenceguide/chapter12/localization/LocalizationTest.java[tags=locale-resolver]
----
====

[NOTE]
====
When using the `LocaleResolver`, you have to define the list of supported locales via the `locales()` method.
====

=== Custom contexts

The Jakarta Bean Validation specification offers at several points in its API the possibility to unwrap a
Expand Down
@@ -0,0 +1,75 @@
package org.hibernate.validator.referenceguide.chapter12.localization;

import static org.junit.Assert.assertEquals;

import java.util.List;
import java.util.Locale;
import java.util.Locale.LanguageRange;
import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.constraints.AssertTrue;

import org.hibernate.validator.HibernateValidator;
import org.hibernate.validator.spi.messageinterpolation.LocaleResolver;
import org.hibernate.validator.spi.messageinterpolation.LocaleResolverContext;
import org.junit.Test;

public class LocalizationTest {

@Test
public void changeDefaultLocale() {
// tag::default-locale[]
Validator validator = Validation.byProvider( HibernateValidator.class )
.configure()
.defaultLocale( Locale.FRANCE )
.buildValidatorFactory()
.getValidator();

Set<ConstraintViolation<Bean>> violations = validator.validate( new Bean() );
assertEquals( "doit avoir la valeur vrai", violations.iterator().next().getMessage() );
// end::default-locale[]
}

@Test
public void localeResolver() {
// tag::locale-resolver[]
LocaleResolver localeResolver = new LocaleResolver() {

@Override
public Locale resolve(LocaleResolverContext context) {
// get the locales supported by the client from the Accept-Language header
String acceptLanguageHeader = "it-IT;q=0.9,en-US;q=0.7";

List<LanguageRange> acceptedLanguages = LanguageRange.parse( acceptLanguageHeader );
List<Locale> resolvedLocales = Locale.filter( acceptedLanguages, context.getSupportedLocales() );

if ( resolvedLocales.size() > 0 ) {
return resolvedLocales.get( 0 );
}

return context.getDefaultLocale();
}
};

Validator validator = Validation.byProvider( HibernateValidator.class )
.configure()
.defaultLocale( Locale.FRANCE )
.locales( Locale.FRANCE, Locale.ITALY, Locale.US )
.localeResolver( localeResolver )
.buildValidatorFactory()
.getValidator();

Set<ConstraintViolation<Bean>> violations = validator.validate( new Bean() );
assertEquals( "deve essere true", violations.iterator().next().getMessage() );
// end::locale-resolver[]
}

private static class Bean {

@AssertTrue
private boolean invalid = false;
}
}

0 comments on commit 582db15

Please sign in to comment.