Saturday, November 24, 2012

Using T4 for localizing JavaScript resources based on .resx files

In our project we're using two languages: Dutch and English. Furthermore, the IT company who built the application is using a framework on top of EXT.NET and thus there is a lot of JavaScript involved. There are a couple of solutions out there for localizing JavaScript in an ASP.NET MVC application, and I think the most common is this one:
<%$Resources:Resource, FieldName %>
But that his obvious limitations as described here Use ASP.NET Resource strings from within javascript files, namely you cannot use inside the body nor in .js files. I used a slightly different approach to localize the JavaScript in or project, based on the discussion here keeping three goals in mind:
  • Having only 1 place where resources are managed ( namely the .resx files )
  • Support for multiple cultures
  • Leverage IntelliSense - allow for code completion
Because of the last point - I decided to go with code generation. Code generation of course normally comes down to T4 Text Templates. So - currently we're using a text template in the /Scripts folder which generates Resources.js ( marked as 'copy to output directory' ) which is published on Web Deploy. Here's an example:
var Resources = {
  Common: {},

Resources.Common.Greeting = { 
 'nl-NL': 'Hallo',
 'en-GB': 'Hi'
Which gives me IntelliSense in JavaScript as it gives me in C#:
In the master page I'm including the JavaScript file and set the global space var 'locale' using the thread culture on the server:

This enables us to use the resources like this:
var msg = Resources.Common.Greeting[locale];
And now for the T4 template:
<#@ template language="C#" debug="false" hostspecific="true"#>
<#@ assembly name="System.Windows.Forms" #>
<#@ import namespace="System.Resources" #>
<#@ import namespace="System.Collections" #>
<#@ import namespace="System.IO" #>
<#@ output extension=".js"#>
 var path = Path.GetDirectoryName(Host.TemplateFile) + "/../App_GlobalResources/";
 var resourceNames = new string[1]

* Resources
* ---------
* This file is auto-generated by a tool
* 2012 Jochen van Wylick
var Resources = {
 <# foreach (var name in resourceNames) { #>
 <#=name #>: {},
 <# } #>
<# foreach (var name in resourceNames) { 
 var nlFile = Host.ResolvePath(path + name + ".nl.resx" );
 var enFile = Host.ResolvePath(path + name + ".resx" );
 ResXResourceSet nlResxSet = new ResXResourceSet(nlFile);
 ResXResourceSet enResxSet = new ResXResourceSet(enFile);

<# foreach (DictionaryEntry item in nlResxSet) { #>
Resources.<#=name#>.<#=item.Key.ToString()#> = { 
 'nl-NL': '<#= ("" + item.Value).Replace("\r\n", string.Empty).Replace("'","\\'")#>',
 'en-GB': '<#= ("" + enResxSet.GetString(item.Key.ToString())).Replace("\r\n", string.Empty).Replace("'","\\'")#>'
<# } #>
<# } #>
Find the code snippet here The resourceNames array takes the names of the resource files that I want included in the .js file. The solution is generic enough for our needs right now, and if you would want to include other languages - some changes would be required. The shortcomings of this solution are of course that the size of the .js file might become quite large. However, since it's cached by the browser, we don't consider this a problem for our application. However - this caching can also result in the browser not finding the resource called from code.


  1. Dear Jochen,

    What a joy to find your well thought generic solution!

    I've integrated it in my project and I'm happily taking advantage of strings stored in both .resx (*.pt-BR and .resx) files. No more duplication. DRY principle.

    I'm going to share your post here:

    Thanks and God bless your life,


    1. Hi, Great.. Tutorial is just awesome..It is really helpful for a newbie like me.. I am a regular follower of your blog. Really very informative post you shared here. Kindly keep blogging. If anyone wants to become a .Net developer learn from Dot Net Training in Chennai. or learn thru Dot Net Training in Chennai. Nowadays Dot Net has tons of job opportunities on various vertical industry.
      or Javascript Training in Chennai. Nowadays JavaScript has tons of job opportunities on various vertical industry.

  2. Thanks Leniel, glad you like it, thank you for the feedback.

  3. Exactly what I needed! I came to the same conclusion as you, but the T4-part scared me. Fortunately, you have shown me the right path. Thank you.

  4. Hello Jochen! If you are involved in l10n projects, I would suggest to evaluate a collaborative translation management platform like POEditor that can help you easily manage your projects.

  5. Hi ,
    thanks for your great article , where can I find the code?!