JavaScript Localization in MVC

Localizing content in MVC is straight forward with the use of .resx files to either annotate your data models or referencing the resources directly. But accessing the localized resource from within JavaScript code can be a little bit fiddlier.

If your JavaScript is within your .cshtml you can reference the localized resource in a stright forward way:

using Resources;
...
//To access a string called ErrorMessage_PasswordNotStrongEnought in the Account resx

alert(userNameTooltip = @Resources.Account.ErrorMessage_PasswordNotStrongEnought);

But if your JavaScript is in its own .js file there is a bit more setup to do, as you can’t access the localized resources in the same way. There are many good reasons to put JavaScript in its own .js file and not inline with the rest of your html, and most most of the time this is best practice.

I like to keep all my localized content in resx files, as it keeps all the content in one place (though possibly split into separate files/folder for organising). It also helps to keep all the localzsed in the same format as it make it easier to manage and translate the content for non technical users.

This article will show how to store your localized content in resx files, and then to automatically convert these into a JSON object in a JavaScript file that can be referenced from any of by other JavaScript files.

Create aresource file (.resx) and add some key value pairs. Make sure the Access Modifier is set to Public.

Create a new controller ‘JSResourceController’. This can be extended to implement caching:

using System.Web.Mvc;
namespace Demos.Controllers
{
public class JSResourceController : Controller
{
// GET: Resources
public ActionResult Index()
{
Response.ContentType = "text/javascript";
return View();
}
}
}

And create the associated view:

@using System.Collections
@using System.Globalization
@using System.Resources
@using Demos.Resources

@{
Layout = null;

// Get a set of resources in the resources for the browser's culture
ResourceSet resources = WebReources.ResourceManager.GetResourceSet(CultureInfo.CurrentUICulture, true, true);
}

var FormElementsLang = {};
@foreach (DictionaryEntry item in resources)
{
@:[email protected] = "@Html.Raw(HttpUtility.JavaScriptStringEncode(item.Value.ToString()))";
}
[/code]

The output of the JavaScript file give you a JSON object of the translations based on the user’s localle.

var FormElementsLang = {};
FormElementsLang.Username_Label = "Username";
FormElementsLang.Password_Label = "Password";
FormElementsLang.Password_Toolip = "Please enter your password. If you have forgotten it plaase click the forgot password link.";
FormElementsLang.Username_Tooltip = "Please enter you username.";
[/code]

Create a reference to the generated JavaScript in your _Layout.cshtml partial view or in specifc pages or section as needed:

<a href="http://~/JSResources/[email protected]&version=@version">http://~/JSResources/[email protected]&version=@version</a>

I have created two query string variables. These are both to help control the browser caching" The ‘locale’ parameter will ensure they get a different version of the JS based on their localle. This variable won’t change the generation of the JavaScript, but will ensure they don’t get a cached version of the file if they change their locale. Without this it is possible that they may have a ‘French’ version of the JavaScript file, and if trhey change their localle to Spanish the browser will have cached the JavaScript file and still use the French version. The ‘version’ parameter enables you as a developer to make sure the user’s browser requests a new version of the JavaScript file when you update the version.

The version could be tied to the Assembly version:

string version = Assembly.GetExecutingAssembly().GetName().Version.Major + "." + Assembly.GetExecutingAssembly().GetName().Version.Minor + "." +Assembly.GetExecutingAssembly().GetName().Version.Build + "." + Assembly.GetExecutingAssembly().GetName().Version.Revision;

You may want to cache this or store it in an application variable on startup, to prevent calling it on every page load. Alternatively, you may want to base it on a Web.config entry to give you more flexibility on when to change the version.

You can then reference the JavaScript object as follows to get localised content based on the key:

alert(FormElementsLang.ErrorMessage_PasswordNotStrongEnought);
Alex Orpwood Written by:

Software developing and architecting for 20 years. Satellite monitoring by day, writing my own app by night. More about me