Internationalization

Author: Rudy De Busscher
Reviewer: Gerhard Petracek

Introduction

The messages which are shown when a validation fails can be customized in different ways. MyFaces integrates different constraint types (JSF based validators, Bean-Validation constraints, ExtVal constraints and any kind of custom constraints). The different constraint types might be a bit confusing at the beginning. This page shows an easy way to customize the violation messages of the constraints.

Message keys

Just like most web applications, the messages are identified by keys which are used e.g. in resource bundles. The following table shows an overview of the keys:

ExtVal Annotations for JSF Validators

Annotation

Message Key

@Length

javax.faces.validator.LengthValidator.MINIMUM
javax.faces.validator.LengthValidator.MAXIMUM

@LongRange

javax.faces.validator.LongRangeValidator.NOT_IN_RANGE
javax.faces.validator.LongRangeValidator.MAXIMUM
javax.faces.validator.LongRangeValidator.MINIMUM
javax.faces.validator.LongRangeValidator.TYPE

@DoubleRange

javax.faces.validator.DoubleRangeValidator.NOT_IN_RANGE
javax.faces.validator.DoubleRangeValidator.MAXIMUM
javax.faces.validator.DoubleRangeValidator.MINIMUM
javax.faces.validator.DoubleRangeValidator.TYPE

JPA annotations

Annotation

Message Key

@Column

field_required
field_too_long

@Basic

field_required
field_too_long

@Id

field_required
field_too_long

@OneToOne

field_required
field_too_long

@ManyToOne

field_required
field_too_long

Bean-Validation Constraints

The BV spec. suggests to use the name of a constraint + the postfix ".message".
Key have the be marked with curly braces.
For example the @Null constraint uses: {javax.validation.constraints.Null.message}
In the resource bundle the key is javax.validation.constraints.Null.message
The keys for the standard constraints are documented in the [BV spec.]

ExtVal Simple-Validation Annotations

Annotation

Message Key

@Required

field_required

@Pattern

no_match

ExtVal Cross-Validation Annotations

Annotation

Message Key

@Equals

duplicated_content_required

@NotEquals

duplicated_content_denied

@DateIs

wrong_date_not_before
wrong_date_not_after
wrong_date_not_equal

@RequiredIf

empty_field

@EmptyIf

field_not_empty

Define a central Resource-Bundle

As you can see there are 5 groups of annotations (incl. custom constraints with custom message keys) that can be used with ExtVal for validation. The validation strategies (the code which is responsible for making the actual checks or the delegation to existing validators) for the ExtVal annotations can be split up into 2 groups. The ones that use the JSF validators (like @Length) and those that are implemented by ExtVal itself (like @Pattern and @Required). So we have actually 6 groups that have small differences in 'resolving' their message. You can find the details in the next paragrapgh, but if you need a quick solution that works for any group, do the following:

  1. Create a new resource bundle, according to the standards of Java (a properties files with the correct postfixes for the languages and countries). An example could be com/mycompany/myprog/messages.properties, com/mycompany/myprog/messages.properties, etc ..
  2. Define this resource bundle as message bundle in your faces-config file
    <application>
      <message-bundle>com.mycompany.myprog.messages</message-bundle>
    </application>
    
  1. Define the following web application parameters in your web.xml file.
    <context-param>
      <param-name>org.apache.myfaces.extensions.validator.CUSTOM_MESSAGE_BUNDLE</param-name>
      <param-value>com.mycompany.myprog.messages</param-value>
    </context-param>
    
    <context-param>
      <param-name>org.apache.myfaces.extensions.validator.JPA_VALIDATION_ERROR_MESSAGES</param-name>
      <param-value>com.mycompany.myprog.messages</param-value>
    </context-param>
    

Now you can use the keys listed in the first section of this page to redefine the message(s). JSF differentiate between two kinds of messages (summary and detail). You can use the listed message keys + the postfix "_detail" for a detail message.

If you like to use other keys then the ones on this page, you can specify them via the attributes of a constraint.
ExtVal constraints use the attribute name validationErrorMsgKey (it isn't a rule -> for custom ExtVal constraints you can use any name you prefer) or message for BV constraints (that's a fixed rule). JPA annotations as well as annotations for JSF validators don't have a special attribute.

Detailed customization steps

In this paragraph, the different steps which are followed to resolve the message are written out for each of the 5 groups. This can be used if you want to customize the Internationalization aspect of ExtVal further more.

MessageResolver

A MessageResolver allows customizing the resolution of violation messages.

Handy Hint

The advanced Internationalization page (TODO) provides examples which illustrate e.g. internationalization based on other message sources.

Messages for ExtVal annotation

The steps below are the lookup order for violation messages of ExtVal annotations (e.g. @Required and @Pattern) which don't delegate the validation to std. JSF validators.

The message-text or the message-key which is specified in validationErrorMsgKey of the annotation will be used to lookup the violation message. If the user didn't specify one, the default one is used and can be found in the table on top of the page. The value of it will be referenced as msgOrKey in the rest of the paragraph.

  1. If the msgOrKey value contains a space, it is the literal text that is used as message.
  2. The value of msgOrKey is used as the key for the message-source (e.g. a resource bundle) which is used by the MessageResolver
    (The default implementations use messageBundleBaseName and messageBundleVarName. The last one is available since ExtVal for JSF 1.2+)
  3. If msgOrKey wasn't found, the convention for a custom bundle is used org.apache.myfaces.extensions.validator.custom.validation_messages.
  4. The method getCustomBaseName can return a custom base name which is specified via org.apache.myfaces.extensions.validator.CUSTOM_MESSAGE_BUNDLE in web.xml.
  5. The method getBaseName has to return the base name for the current validation module. In case of the annotations mentioned above it's org.apache.myfaces.extensions.validator.baseval.message.bundle.validation_messages

If there is no message available, the key surrounded with ??? is returned. If a ValidationStrategy overrides the method resolveMessage it's possible to provide a fallback message. In case of @Required the fallback message is the message of the required attribute (key: javax.faces.component.UIInput.REQUIRED - the message text depends on the custom or default resource bundle of JSF).

ExtVal annotations which delegate to JSF Validators

The message is resolved through the standard functionality of JSF. That means that the keys (javax.faces.validator.xxxx) are looked up in the message bundle defined in the faces-config file. If it can't find it there, JSF looks in the default bundle.

So ExtVal isn't responsible for resolving the message.

JPA annotations

The keys used (as value for msgOrKey) is field_reqiured or field_too_long.

If the msgOrKey value contains a space, it is the literal text that is used as message. JPA annotations don't provide an attribute for such messages. Therefore it's required to use an add-on (e.g. the virtual meta-data add-on) for using different messages for JPA based validation.

The rest is similar to the msg resolution of plain ExtVal annotations. The only differences:
getCustomBaseName returns the base name which is configured via org.apache.myfaces.extensions.validator.JPA_VALIDATION_ERROR_MESSAGES in the web.xml. As alternative to the web.xml you can provide the base-name via the global property JPA_VALIDATION_ERROR_MESSAGES

getBaseName returns org.apache.myfaces.extensions.validator.baseval.message.bundle.jpa_messages

Cross validation annotations

It's similar the the message resolution of simple ExtVal annotations. However, in this case we have a different (logical) module. So the message bundle base name of this module is org.apache.myfaces.extensions.validator.crossval.message.bundle.validation_messages. Furthermore, it's possible to have different messages for different violations. Furthermore, there might be a reverse violation message if the validation target isn't in the same page and therefore the model value is used as validation target.

Further details will be available soon.

Bean validation

The validations performed by the Bean Validation Framework are based on a completely different system than the ones by JSF itself. The validation engine of BV just returns a list of violations. By default the MessageInterpolator of BV is responsible for resolving and interpolating the messages. ExtVal suplies a special MessageInterpolator which uses an optional MessageResolver to resolve the message template for the final interpolation of the message. So the possibilities of the MessageInterpolator can be used here as well.

Further details for BV inline-messages and message keys are available in JSF 303 and the documentation of the validation provider.
The lookup steps of the MessageResolver depend on the implementation you provide. By default the MessageResolver of the core is used. So the method getCustomBaseName returns a custom base name which is specified via org.apache.myfaces.extensions.validator.CUSTOM_MESSAGE_BUNDLE in web.xml. And the method getBaseName returns org.apache.myfaces.extensions.validator.core.message.bundle.validation_messages.

(If we don't have a bv-message-key (= marked via curly braces), the MessageResolver is not used because we have an inline-message.)

  • No labels