Localizing Validator Errors

A common request I’ve seen is a way to localize the Validator error messages. Unfortunately the built-in Validator classes don’t make that easy in their current state (something we’re hoping to work on in the next version). In the meantime, here is one approach (and I’m sure there are more if you wanted) to changing the error messages using some form of resource file.

First we need a resouce file, I’m gonna format mine to be as close to the validator names as possible:

validatorStrings.xml<validators>
<StringValidator>
<tooLongError>Localized too long</tooLongError>
<tooShortError>Localized too short</tooShortError>
</StringValidator>
</validators>

Note that the validators is just an outer tag to make this valid XML. Inside I would put one tag for every validator. Here I just did StringValidator, but you can imagine a NumberValidator tag sitting right underneath it. Inside the StringValidator tag I put an entry for each error message, the name of the tag is the error name and the body of the tag is the actual value.

Now we need this resource loaded, so I’m just gonna use an HTTPService to do that, then I’m going to store the result in a Model that will be accessible from anywhere.

app.mxml<mx:Application xmlns:mx="http://www.macromedia.com/2003/mxml" xmlns="*" initialize="validatorStringsSvc.send()"><mx:HTTPService id="validatorStringsSvc" url="validatorStrings.xml" />
<mx:Model id="validatorStrings">
{validatorStringsSvc.result.validators}
</mx:Model>

Now we need a Validator to actually use this resource.

StringValidator.asclass StringValidator extends mx.validators.StringValidator{private var stringsCopied : Boolean = false;private function copyStrings() : Void{//if for some reason the HTTPService is slow to load this may need to re-execute, hence the extra checks and repeated callsif (!stringsCopied){var strings : Object = mx.core.Application.application.validatorStrings.StringValidator;if (strings != null){for (var i in strings){this[i] = strings[i];}stringsCopied = true;}}}public function doValidation(value) : Void{copyStrings();super.doValidation(value);}}

You could basically copy this code and do it for any validator that already exists. I’m sure there is a better way to optimize the copyStrings approach to avoid the repetitive calls (for example you could put the if check in the doValidation method so you pay the price of a compare instead of a function call and THEN a compare), but I think it’s not a big deal.

And now finally, how do you use this lovely new Validator? Just use the normal validator tag and change the namespace to point to your local version.

TADA!

The story of why Validators are architected in such a way that this is difficult is a story for another time 🙂

3 Responses to Localizing Validator Errors

  1. stephan says:

    Thanks Matt,wow – quick solutionthats good support !I wish you luck with binding 2 validators in flex2.0;-)

  2. Alex says:

    shouldn’t it be more appropriate to embed xml file?I realize we will need to re-compile the app each time we change xml file but i doubt there is any need to change it frequently.

  3. David Ringley says:

    We have separated the localized text into an XML-based resource file. This file is loaded once the flex app is initialized. The app knows which locale specific XML file to load from a flashvar set in the query string (i.e. Index.mxml?locale=en_US). This way the flex app does not need to be recompiled when the XML file or the locale changes.