Using .Net Resources in Javascript

Internationalization can be tricky, to say the least.

For .Net, you have some good tooling in place to help you create and edit resource files, which can provide text and images that can be used to support an internationalized application. But when I tried to internationalize the javascript side of an application, I didn’t find anything that looked like it would work for us.

I had been working on an ASP.Net MVC application, and I was already using .Net resource files for internationalization on the .Net side. I wanted to leverage the existing .Net resource files, because there was already a workflow for keeping them up to date and there was a good amount of text already translated that I wanted to make use of. And I wanted this data available in Javascript, because part of the application was written in Javascript.

Here is what my javascript initially looked like before internationalization:

1
$('#status').text("Hello World!");

The text, being hardcoded in my javascript file, was clearly not internationalized.

First Try: Razor

My first idea was to move all of my javascript from .js files to razor views (.cshtml file). The views, being parsed on the server, would then have access to the existing resource classes.

For each .js file, I created an action on a controller and a corresponding view. In the action method, I set the content type so the browser would see my view as a script, even though it wouldn’t have a .js extension.

1
2
3
4
5
public ActionResult SomeScript()
{

Response.ContentType = "text/javascript";
return View();
}

The SomeScript.cshtml view looked like this

1
@using MyNamespaceForResources
$('#status').text("@MyResourceClass.HelloWorld");

Verdict: Works, but could be better

This worked, but I didn’t like it, because I wasn’t able to figure out how to get Visual Studio to provide syntax highlighting or intellisense for the javascript inside the Razor view.

Visual Studio didn’t provide syntax highlighting or intellisense because the javascript in the cshtml file was not included inside <script> tags. I couldn’t include them inside <script> tags because the entire file was a javascript file.

Second Try: Javascript Object

My next idea was to provide the browser with a single javascript file that would define a global object showing the local versions of all text resources. Here is what I wanted to see if, for instance, a browser set to the French language requested this javascript resource file:

1
2
var Resources = {};
Resources.HelloWorld = "Bonjour le Monde!";

Then I could make use of it in javascript by referencing the global object:

1
$('#status').text(Resources.HelloWorld);

To make this happen, I created an action on a controller with a corresponding razor view. Don’t forget to set the content type in the Controller as shown above.

Here is the view I wrote:

1
@using System.Collections
@using System.Globalization
@using System.Resources
@using MyNamespaceForResources
@{
    Layout = null;
    // Get a set of resources appropriate to
    // the culture defined by the browser
    ResourceSet resourceSet =
      @MyResourceClass.ResourceManager.GetResourceSet
        (CultureInfo.CurrentUICulture, true, true);
}

// Define the empty object in javascript
var Resources = {};
@foreach (DictionaryEntry res in resourceSet)
{
    // Create a property on the javascript object for each text resource
    @:Resources.@res.Key = "@Html.Raw(
        HttpUtility.JavaScriptStringEncode(res.Value.ToString()))";
}

This will convert a .net resource file into a javascript object.

We don’t have to do much to determine what culture to use. The web browser, when it hits the server, includes header information showing what cultures it supports. ASP.Net automatically puts this information into CultureInfo.CurrentUICulture. We pass this into the GetResourceSet method, which then returns the resource set that matches the current browser settings.

Thus, if the browser is set to French, the French resources, and only the French Resources, will be returned.

Verdict: Success!

When you hit this view from a browser, you will see the javascript object. And assuming that the browser is set to the French language, and a French Resources file has been set up on the .Net side, this will be returned:

1
2
var Resources = {};
Resources.HelloWorld = "Bonjour le Monde!";

You can include this view on your page in a script tag, assuming the name of the action is SomeScript as in the code block above:

1
<script src="/MyController/SomeScript"></script>

Finally, the resources can be used in javascript in a very straightforward manner:

1
$('#status').text(Resources.HelloWorld);