Localizing ASP.NET MVC Validation

This is the fourth post in my series on ASP.NET MVC 2 and its new features.

  1. ASP.NET MVC 2 Beta Released (Release Announcement)
  2. Html.RenderAction and Html.Action
  3. ASP.NET MVC 2 Custom Validation
  4. Localizing ASP.NET MVC Validation

In my recent post on custom validation with ASP.NET MVC 2, several people asked about how to localize validation messages. They didn’t want their error messages hard-coded as an attribute value.

world-in-handsIt turns out that it’s pretty easy to do this. Localizing error messages is not specific to ASP.NET MVC, but is a feature of Data Annotations and ASP.NET. And everything I cover here works for ASP.NET MVC 1.0 (except for the part about client validation which is new to ASP.NET MVC 2).

I covered this feature a back in March at Mix 09 in my ASP.NET MVC Ninjas on Fire Black Belt Tips talk. If you want to see me walk through it step by step, check out the video. If you prefer to read about it, continue on!

Let’s start with the ProductViewModel I used in the last post

public class ProductViewModel {
  [Price(MinPrice = 1.99)]
  public double Price { get; set; }
 
  [Required]
  public string Title { get; set; }
}

If we’re going to localize the error messages for the two properties, we need to add resources to our project. To do this, right click on your ASP.NET MVC project and select Properties. This should bring up the properties window. Click on the Resources tab. You’ll see a message that says,

This project does not contain a default resources file. Click here to create one.

Obey the message. After you click on the link, you’ll see the resource editor.

resources-tab Make sure to change the Access Modifier to Public (it defaults to Internal).

resources-tab-access-modifier

Now enter your resource strings in the resource file.

resource-file

Hopefully my Spanish is not too bad. An ASP.NET build provider will create a new class named Resources behind the scenes with a property per resource string. In this case there’s a property named PriceIsNotRight and Required. You can see the new file in the Properties folder of your project.

solution-with-resources

The next step is to annotate the model so that it pulls the error messages from the resources.

public class ProductViewModel {
  [Required(ErrorMessageResourceType = typeof(Resources), 
    ErrorMessageResourceName = "Required")]
  public string Title { get; set; }
  [Price(MinPrice = 3.99, ErrorMessageResourceType = typeof(Resources), 
    ErrorMessageResourceName = "PriceIsNotRight")]
  public double Price { get; set; }
}

For the ErrorMessageResourceType, I just specify the type created by the build provider. In my case, the full type name is CustomValidationAttributeWeb.Properties.Resources.

For the ErrorMessageResourceName, I just use the name that I specified in the resource file. The name identifies which resource string to use.

Now when I submit invalid values, the error messages are pulled from the resource file and you can see they are in Spanish.

Client Validation - Windows Internet Explorer

Localized Error Messages Custom Client Validation

Note that these localized error messages continue to work even if you enable client validation. However, if you were to try it with the original code I posted in my last validation example, the error message would not work for the custom price validation attribute.

Turns out I had a bug in the code, which is now corrected in the blog post with a note describing the fix. Just scroll down to the PriceValidator class.

As always, I have a code sample you can look at. It’s the same example as before, just updated. Download the sample!

What others have said

Requesting Gravatar... Dave R. Dec 13, 2009 8:07 PM
# re: Localizing ASP.NET MVC Validation
I'm unsure how your example is localized. All you've done is hard-code Spanish strings in the resource file instead of hard-coding English ones in the main source. To be localized, you'll have to be able to switch to culture-specific strings at runtime. In the past, you could do this with multiple .resx files and by using the ResourceManager - is this no longer possible in MVC?

Why not follow the instructions here, which describe multiple approaches, including using the culture info exposed by the browser visiting your page:

msdn.microsoft.com/en-us/library/aa905797.aspx
quickstarts.asp.net/.../localization.aspx

MS should produce some best practices for localizing MVC based apps if the existing ASP.NET methods no longer work.
Requesting Gravatar... Raj Dec 14, 2009 2:04 PM
# re: Localizing ASP.NET MVC Validation
Hi
I was unable to download the sample. Even when I do "Save Link As".


Requesting Gravatar... Aaron King Dec 18, 2009 2:07 AM
# re: Localizing ASP.NET MVC Validation
I too was unable to download the sample.
Requesting Gravatar... marus Dec 28, 2009 2:05 AM
# re: Localizing ASP.NET MVC Validation
c'mmon! download?!...
Requesting Gravatar... msi Jan 11, 2010 5:03 AM
# re: Localizing ASP.NET MVC Validation
On my Visual Studio 2008 vi instaled ASP.NET MVC 2, I have disabled field "Access Modifier", how can I enable it?
Requesting Gravatar... Mustafa Gülmez Jan 19, 2010 9:49 AM
# re: Localizing ASP.NET MVC Validation
If your .res file is under App_GlobalResources or App_LocalResources, Access Modifier shown as disabled. move under Properties, Access Modifier turn enabled.
Requesting Gravatar... msi Jan 20, 2010 1:55 AM
# re: Localizing ASP.NET MVC Validation
I've found another solution
Requesting Gravatar... Adam Jan 22, 2010 6:35 AM
# re: Localizing ASP.NET MVC Validation
I also can't download sample, this zip file probably don't exist. Error - "The system cannot find the file specified"
Requesting Gravatar... Sharbel Jan 26, 2010 8:51 PM
# re: Localizing ASP.NET MVC Validation
I think you should change the title of this post from 'Localizing' because honestly this is not localizing at all. It's a great article to show how not to hard-code validation error messages in the model, but it doesn't at all touch on localizing the messages based on the client locale.
Requesting Gravatar... Mahdi Taghizadeh Feb 05, 2010 9:07 PM
# re: Localizing ASP.NET MVC Validation
Renaming 'Resources.resx' to something like 'Resources.fr-FR.resx' causes a problem. I described here: stackoverflow.com/...
Requesting Gravatar... msi Feb 14, 2010 4:16 AM
# re: Localizing ASP.NET MVC Validation
It does not work on my situation :(
I've found the solution and describe it on my blog. But it is only on russian language.
Requesting Gravatar... trinity Feb 16, 2010 12:44 AM
# re: Localizing ASP.NET MVC Validation
even though this isn't really true localization, it does give you a good example of how to implement the localization strings in the models, with the

ErrorMessageResourceType = typeof(Resources), ErrorMessageResourceName = "PriceIsNotRight")

line.

this is a great example of localization: http://code.google.com/p/aspmvclocalization/ - but it leaves out what I said above. enjoy...
Requesting Gravatar... Gregor Suttie May 30, 2010 10:18 PM
# re: Localizing ASP.NET MVC Validation
How do I go about this problem - I have 2 date time values in my model and when I go to insert a new project the start date and end date validation error messages say that the format is incorrect. Im in the UK and add them as 30/05/2010 but the error message says its invalid and the format 05/30/2010 is invalid.
Requesting Gravatar... Shash J Aug 02, 2010 12:53 PM
# re: Localizing ASP.NET MVC Validation
I want to replace certain words that are in the resource file. Is there a way to derive a class from a base class that will replace words.

<asp:Localize ...

<custom:Localize ...
Requesting Gravatar... Lee Aug 10, 2010 10:24 PM
# re: Localizing ASP.NET MVC Validation
If we use Database as our Resource Content then How can we use this approach.
Requesting Gravatar... Rob Aug 16, 2010 2:54 AM
# re: Localizing ASP.NET MVC Validation
Link for the sample code is broken. thx for the post btw, everything works very nice.
Requesting Gravatar... RR Aug 24, 2010 7:45 PM
# re: Localizing ASP.NET MVC Validation
The download is available through:
code.haacked.com/...
Requesting Gravatar... denappel Oct 19, 2010 6:16 PM
# re: Localizing ASP.NET MVC Validation
Thanks for the example.
We aren't using static resources, but we get the resources from the database.
If I fill in the following for the dataannotations:


[MetadataType(typeof(IncidentsMetaData))]
public partial class INCIDENTS
{
private class IncidentsMetaData
{
[Required(ErrorMessageResourceType = typeof(CustomResourceProviders.DBResourceProviderFactory),
ErrorMessageResourceName="1277")]
public string SUBJECT { get; set; }
}
}



Then I get the following error:
The resource type 'CustomResourceProviders.DBResourceProviderFactory' does not have an accessible static property named '1277'.

Of course there is no such property, it should be accessed by a function.
Any idea what I could do about this?
tnx
Requesting Gravatar... Ryan Nov 24, 2010 5:23 PM
# re: Localizing ASP.NET MVC Validation
I've got a stupid question: is it possible to replace all of the english text around the validation errors with errors in a different language. WITHOUT using data annotations?

We've built a web application which currently only supports one language (dutch). It will eventually be globalized, but the immediate problem is that the error messages are all (US) English.

It's not really efficient use of time to add several thousand attributes to view models just to change a dozen string constants..
Requesting Gravatar... Ryan Nov 29, 2010 1:50 PM
# re: Localizing ASP.NET MVC Validation


Still can't download the sample: "An error occurred while processing your request."

Thanks
Requesting Gravatar... JohnF Jan 16, 2011 4:43 AM
# re: Localizing ASP.NET MVC Validation
By the way, here is a nice and detailed ASP.NET MVC 3 Internationalization/Localization post http://bit.ly/gUBkX3
Requesting Gravatar... Esmaltes Mar 10, 2011 11:24 PM
# re: Localizing ASP.NET MVC Validation
How should I localize DisplayName Attribute ?
Requesting Gravatar... haacked Mar 11, 2011 12:50 AM
# re: Localizing ASP.NET MVC Validation
@Esmaltes you can't. If you're running on .NET 4, use the DisplayAttribute instead.

What do you have to say?

(will show your gravatar)
Please add 7 and 8 and type the answer here: