Announcing new Visual Studio 2012 tool for JavaScript Localization in SharePoint 2013

Tags: SharePoint 2013, Visual Studio, Downloads

In SharePoint 2013 JavaScript is the new default language and all our (at least mine) solutions and projects are using JavaScript more and more, even though everything is not built as SharePoint Apps. Farm or Full-trust solutions built using JavaScript will in many situations create a better user interface and an improved perceived performance. The more we build user interfaces using JavaScript we cannot just forget about some of the basic UX rules, such as using localization. End-users really hate when they see mixed content in different languages. We’ve known for quite some time how to do localization server-side, but how do we do it in a smart way in JavaScript?

Localization in JavaScript

As always when it comes to cool stuff my mate Waldek Mastykarz already covered this topic pretty well in his post called “Globalizing JavaScript in SharePoint 2013”. In that blog post he shows how you actually can use a feature in SharePoint 2013 that allows you to get JavaScript objects, generated from RESX files, to localize the user interface. His guide pretty well covers everything you need, but I’m going to re-iterate some of it here anyways, and here is a sample on how to do it.

Assume that you have a resource file (RESX) in your solution in a SharePoint Mapped folder (to the Resources folder). By adding a script link to the ScriptResx.ashx HTTP Handler with the resource file name and the culture as parameters you can get all the resources as a JavaScript object. For instance a simple Hello World alert in a Visual Web Part could looks something like this.

First of all we need a resource file in the project (mapped to the Resources folder) and if you want localization, you of course have to translate it. This Resource file contains only one resource called HelloWorld.

A Resource file

To use this resource in JavaScript I have to write some code to load the ScriptResx.ashx HTTP Handler and pass in the name of the resource file and the name of the current culture.

SP.SOD.executeOrDelayUntilScriptLoaded(function () {
  SP.SOD.registerSod("demoresources", 
    "/_layouts/15/ScriptResx.ashx?name=demoresources&culture=" + 
    STSHtmlEncode(Strings.STS.L_CurrentUICulture_Name));

  SP.SOD.executeFunc("demoresources", 'Res', function () {
    alert(Res.helloWorld);
  });
}, "strings.js");

In the sample above I use the Script-On-Demand (SOD) JavaScript functions to first make sure that the Strings.js is properly loaded. I need that to get the name of the current culture (String.STS.L_CurrentUICulture_Name). Then I do a SOD registration and registers the script link for the ScriptResx.ashx file using the name of the RESX file and the name of the culture. Finally I wait for the SOD to load and then shows an alert using the Res.helloWorld object.

The ScriptResx.ashx file automatically creates a JavaScript object called Res and that object contains strings of all the resources in the RESX file. Note that the resources are using Camel Casing.

What is the problem with this approach?

This works fantastically great in most cases, and it is extremely hard to find anything on Waldeks posts that can be improved, but what if you don’t want to use the default namespace Res? It could be a matter of taste or a collision in names from different resource files. Fortunately there is a solution to this built into the ScriptResx.ashx HTTP Handler. You can actually specify two resheader elements in the Resource file to indicate that you want a custom namespace and the name of it – and this is exactly what SharePoint 2013 do for some of the built-in resource files.

<resheader name="scriptResx">
  <value>true</value>
</resheader>
<resheader name="classFullName">
  <value>SPResXDemo.Resources</value>
</resheader>

The resheader with the scriptResx name attribute tells the ScriptResx.ashx handler that we would like to generate vanity namespaces and the one with the classFullName name attribute tells the handler the namespace to use.

Unfortunately Visual Studio (not really, but the .NET ResXResourceWriter) does not handle this at all, as soon as you save your RESX file these two resheader elements will be removed. (And this is where I felt challenged!)

SPResX to the rescue!

To handle this situation and to be able to use custom namespaces for my JavaScript localizations I’ve created a small tool called SPResX that replaces the default RESX Custom Tool, the ResXFileCodeGenerator, and correctly preserves the resheader attributes.

The SPResX tool can be downloaded from the Visual Studio Gallery and installed on any Visual Studio 2012 system, or found in the Extensions and updates in Visual Studio.

SPResX in the Extension gallery

Once you have the tool installed you just need to change the Custom Tool to SPResX and save you Resource files. You need to do this on all resource files, including the different language and region variants. Now you will get a namespace that corresponds to your default project namespace. For instance if I have a project called Wictor.WebParts, the namespace will be Wictor.WebParts.Resources (since it is in the Resources folder). If you would like some namespace that is completely different, then you can just specify that namespace in the Custom Tool Namespace. (Yes, I know you will get a notification that the file has to be reloaded – that is just the way it is).

Configure the Custom Tool

This is how the code from above can then be re-written using this tool, it works in the exactly same way but with a fancy vanity namespace of the resources.

SP.SOD.executeOrDelayUntilScriptLoaded(function () {
  SP.SOD.registerSod("demoresources", 
    "/_layouts/15/ScriptResx.ashx?name=demoresources&culture=" + 
    STSHtmlEncode(Strings.STS.L_CurrentUICulture_Name));

  SP.SOD.executeFunc("demoresources", 'SPResXDemo', function () {
    alert(SPResXDemo.Resources.helloWorld);
  });
}, "strings.js");

Summary

I hope this little tool will help somebody out there and I would appreciate feedback on it, either on this post or in the Visual Studio gallery.

No Comments

  • Anatoly Mironov said

    Hi Victor! Thank you for sharing. Now when SharePoint loves javascript, the localization is very important. This approach to use resx files has been used by core SharePoint even in SP2010. If you inspect Network traffic, you could find that SP.Res is loaded by some pages. Of course in SharePoint 2013 it is more important and easier, by using the strings.js I wrote two articles about that topic: http://chuvash.eu/2013/02/01/javascript-localization-in-sharepoint/ http://chuvash.eu/2012/02/13/scriptresx-ashx-in-sharepoint/

    The culture could be retrieved from the built-in old-style variable called L_Menu_LCID (from SP2007) instead of strings.js (just to eliminate one dependency)..

    In my opinion, the great disadvantage of the OOB ScriptResx.ashx is that it is depending on an explicit culture. It doesn't get a fallback or culture invariant resx file. If we dynamically pass the current culture as a query string, we must ensure that we have localized our resx files properly for all supported languages.

    Thank you for the tool as well. It will make the javascript localization pretty easier.

  • Tommy said

    Great post! I have an issue that changes I do to the resx are not reflected on the page. I have added more values and changed the initial values, but it still loads the exact same values as it did the first time I ran the script. New values that I add, returns "undefined". However, the changes are reflected in c# code, aspx, ascx and other xml defininitions. It's just in the JavaScript part it does not get updated. Any idea what causes this?

    -Tommy

  • Troels said

    Hello Wictor,

    Great peice of work. This is exactly what we needed on our current project. Here we switched into using handlebars templates on both server and client side. The same templates, but only specified in resource files.

    There is, however, a problem. After placing some particular input in one of the resource files, the SPResX tool seems to have stopped working. It's not inserting the resheader tags. I suspect it's unable to parse the file.
    Would it be possible for you, to share the source of the SPResX project, so we can tweek it into working again?

    Thanks dude :)

  • Edgar Maucourant said

    Hi Wictor,

    This is a great help for everyone trying to better manage the Javascript localization, thank you !

    Is this tool is planned to be released for Visual Studio 2013 ? I'm not able to find it right now on the Visual Studio Gallery...

    Edgar

Comments have been disabled for this content.

About Wictor...

Wictor Wilén is the Nordic Digital Workplace Lead working at Avanade. Wictor has achieved the Microsoft Certified Architect (MCA) - SharePoint 2010, Microsoft Certified Solutions Master (MCSM) - SharePoint  and Microsoft Certified Master (MCM) - SharePoint 2010 certifications. He has also been awarded Microsoft Most Valuable Professional (MVP) for seven consecutive years.

And a word from our sponsors...