November 30, 2013

ASP.NET MVC I18n – Part 3: Custom Language Choice

The last post showed how we could honor the language preferences the user declared in his browser. However, it is also good practice to let the user change the region, independent of the browser settings.

a way to maintain the user’s culture choice overriding the browser preferences

a way to actually change the preferred culture

Maintaining the preferred culture…

As we know, each request comes with the accept-language header, telling us language preferences set in the browser. We need something similar to maintain the overriding culture choice.

One option, that is used very often used, is including the region in the URL. This implies addressing the culture in every route declaration, and every action link needs to provide the culture as additional parameter. Alex shows how the URLs can be analyzed and the culture applied using a custom MvcRouteHandler; Nadeem does it in a Controller base class with similar intentions. Something in the same line should be possible for generating URLs (e.g. with a custom route class).

This certainly works and there is nothing wrong with it. Still, I don’t like this approach all that much. From a technical perspective, URLs in static content like CSS files are still not addressed properly. Additionally there are also other MVC features affecting URLs as well, e.g. areas, which might cause problems. And from a more “semantic” perspective, URLs are meant to address "resources" – which is a hard enough task already. Language preferences, similarly to skin and other profile data, is kind of "orthogonal" information affecting the rendering, but not addressing the resource. Unfortunately MVC does not really give an answer on how to pass that kind of information, which is why you can find all possible approaches (URL parts, query params, cookies, user session, …), none of which is always good or always bad.

For the problem at hand, the preferred culture, my choice is using a cookie: Adjusting the URL feels too invasive, query params are too error prone, and no need to enforce a session.

For the UI it’s really up to you how you present the choice: some drop down list is quite common. I intend to provide a single action link that simply choses the next supported culture, thus repeatedly clicking it would cycle through all cultures. For this a little helper method makes life simpler: