Archive for August, 2009

Localizing ASP.Net MVC Pages without the need to RunAt=”server”

Thursday, August 20th, 2009

A common complaint when faced with localizing ASP.net MVC pages is that littering your code with tonnes of runat=”server” tags breaks the “purity” of the MVC model.  Regardless of how meaningful that debate is, there is a way to achieve globalisation without server controls.

I’m going to walk you through a sample implementation which should hopefully make this clearer.  As a standard disclaimer, none of this code has been tested in a production environment and I wouldn’t advise implementing it blindly.

I’m going to attempt to play this out mostly in screenshots…

The Idea

  • The required language is stored in a database / session / extrapolated from the Url route information
  • Your view pages derive from the type TranslatableViewPage
  • This page adds support for a LanguageCode property that you can make use of inside the view along with adding a class implementing ITranslator, a class that provides hooks into a translation database.
  • Your controller derives from the type TranslatableController.
    • This controller add a method called ViewInLanguage(string languageCode) that you use instead of View() or View(model) to return your Asp.net MVC view.
  • At application start up in the Global.asmx file, you register a default language code for failure conditions, and specify the implementation of ITranslator you wish to use to acquire localized strings.
  • If your TranslatableViewPage when rendering your output, you simple need to use the embedded <%=Translator.Translate(propertyName) %> method call to load a translated string while the page output is rendering.
  • Class Layout

    The following is built upon the standard Asp.net MVC starter project for the sake of illustration.

    image

    Implementation

    First, configure the translation settings and register your translator…

    image

    You need to configure a fail-safe default language code and a type that implements ITranslator.  This translator will be responsible for doing the heavy lifting.  Ideally we’d add some inversion of control here to allow you to define the translator implementation at configuration time, but that’s outside of the scope of this example.  I’ve implemented a very crude resource .resx translator for the example.

    Next, make your controllers inherit from TranslatableController

    image

    Once inherited, switch from using the View(); method to ViewInLanguage() passing in your desired language code (gathered from the user session / database / Url route).

    Then set your view type (or derive your view from) TranslatableViewPage

    image

    Once your view is inheriting from TranslatableViewPage, you’ll have access to an instance of your specified Translator and the LanguageCode inside the view which you can use in a manner similar to the built in HtmlHelper class to access your translated strings.

    How It Works

    The TranslatableController provides you with ViewInLanguage and when called generates the standard MVC ActionResult.  This ActionResult will be a ViewResult, which is then wrapped in a LocalizedViewResult wrapper class adding a LanguageCode.

    When ExecuteResult is called on the LocalizedViewResult to render the view, the LanguageCode is placed in the TempData array in the TranslatableViewPage.  Then, when the OnInit(EventArgs e) method is called on the TranslatableViewPage, this LanguageCode is extracted and placed in the LanguageCode property on the page.  In addition to this the page provides a constructed instance of ITranslator which you can use in your views to source translated data as the page is rendered.

    Source Code

    Download Here

    MobileTFL 1.0.0.9

    Sunday, August 9th, 2009

    A quick note: I’ve upgraded MobileTFL to version 1.0.0.9.

    Get it here.

    +Fixed critical bug due to data format changes.
    +Reworked parsing of source data so it’s less sensitive to format changes in the future.

    Apologies for the rapid releases, but hopefully the app should be good “long term” as of this release.
    There will be one further release in the near future consisting solely of cosmetic changes.