Nov 7, 2013

Localization from url with Asp.Net MVC 4



To offer a website in multiple languages using ASP.Net we simply need to add some resource.resx files to our project and voilà. Based on the language of the browser, IIS will match the localization resource. However, what if we want to give the choice to the user?

The goal

One pattern often used to achieve this, is to split the resource based on the URL.

Ex:
http://www.DomainName.com/EN/About for the English path
http://www.DomainName.com/FR/About for the French path

The needs

We will need something to grab the desired language from the URL and set it as the current language.

The Solution

First, let's add a new route. Asp.Net uses routing to parse the URL and to extract information from it, while keeping the displayed URL more user friendly. The default route is {controller}/{action}/{id}. So without a new route, our language will be treated as a Controller name; but that’s no good.
The route we want is {lang}/{controller}/{action}/{id}. We could just replace the default, but then what would happen to "normal" calls?

The best thing to do is to add our localized route first and keep the default second. The way the routing works, it will use the first route that matches. Since we will use the two-letter code for chosen language, lets add the first part {lang}, which must be two characters long to be considered valid. You can see this in the code where I define a constraint using the following Regex: "^[a-zA-Z]{2}$".

Class_RouteConfig
Now that we have the language, we must change the user interface culture of the current thread. I decided to use an Attribute, making it easy to use. Under the Filter folder add a new class which inherits from ActionFilterAttribute. This method will check if "lang" is available from RouteData. If lang is present it will change the currentUICulture of the current thread. If "lang" is not part of the URL, then it will set it to the default.

Class_LocalizationAttribute

We could put the [Localization] attribute on all controller classes, but a best practice is to create a BaseController class and use it there.

Class_BaseController

Voilà, you can now change the language of the entire website by changing the URL.

Bonus: Use it everywhere


To use it in the view and the controller it's easy; just add the namespace and just type Resources.NameOfYourResourceString.
To use it in the validation and the generated code from the model, we could use something like this:

Class_PersonModel

This way, in the view, the code will still stay clean and simple.

@Html.LabelFor(model.UserName)

I hope this post helps you in your development efforts. Any comments, suggestions and/or questions are welcome.
 

~Frank



8 comments:

  1. Hi Thanks for the valuable post.
    Just one clarification..
    How the PersonModel will get dynamic Resource file on basis of language. currently it is Resources.Resource fixed..

    Please check it..

    Thanks again

    ReplyDelete
    Replies
    1. You still need a resources file. And to change the language you can add a drop down.

      Delete
  2. thanks for this Post
    but i have a question please
    i'm using areas in my solution and i can't apply the routing to read the language and the areas

    thanks

    ReplyDelete
  3. A good developer knows all the aspects of language, but it is very difficult to find a good developer, that is why people hire asp.net developers from firm and consultancy.
    Such posts makes people to get rid of asp.net problems.

    ReplyDelete
  4. Frank, if you need a good tool to manage collaborative localization projects using RESX files, I highly recommend the translation management platform https://poeditor.com/

    ReplyDelete
  5. Thanks @summ3r, you're right. Nice tool easy to use.

    ReplyDelete
  6. This comment has been removed by the author.

    ReplyDelete