The default route to take is with Resources.
However, I understand your pain :) The way I've achieved it is a little unusual, but I'll give you a quick rundown.
In our project, using resource files is not an option as its way too limited for our purposes, the details of which I won't bore you with now! :)
At it's most basic principle, we're setting the errorMessage property of the validation attribute to some sort of "key", and then just using that as a way to lookup the correct (languaged) response in our CMS database, when the validation fails (in our case using MVC, when we update the model and check the state - all at Controller level).
This is the same principle as using the resources (by specifying "ErrorMessageResourceName" and "ErrorMessageResourceType"), but you get to do what you want with it.
To be clear, we originally extended the RequiredAttribute (as one example) with our own stuff, including putting in properly named arguments to allow us to retrieve a sensible CMS value from the database later on. To be extra clear, we're using MVC and custom HtmlHelpers to render our own ValidationControls, which are what ultimately consume the custom values from our custom annotations, etc - None of this affects the dumbed-down principle here though, which is to just use "errorMessage" , or something like it, as a way to look up the actual message from where YOU want to, and WHEN you want to.