CHUVASH.eu

CHunky Universe of Vigourous Astonishing SHarepoint :)

ScriptResx.ashx in SharePoint

In my previous post I showed a little proof-of-concept for an httphandler which I want to use to dynamically get the localization resources from SharePoint as javascript object. But wait a moment. How does SharePoint handle localization on client? When you look in Script tab in Chrome dev tools, you’ll find:

ScriptResource.axd

It is added to the server when deployed. See a good introduction to WebResource.axd and ScriptResource.axd by Brian Chavez.

ScriptResx.ashx

That was new. Try to google it. You won’t find much results.

Wait a sec, so there is actually the localization httphandler in SharePoint which I wanted to do?

Can’t be true, can it? Let’s look closer. So the url for this javascript file is:

/_layouts/ScriptResx.ashx?culture=nb-no&name=SP.Res

It is added with RegisterSod:

<script type="text/javascript">
    RegisterSod("sp.res.resx",
        "\u002f_layouts\u002fScriptResx.ashx?culture=nb\u00252Dno\u0026name=SP\u00252ERes\u0026rev=4rLK\u00252F2Oo4ectujVWgrynrA\u00253D\u00253D");
</script>

It begins by:

_EnsureJSNamespace('SP');
SP.Res={lcid:'1044',autocompleteAccessibleMenuName:'Autofullf\u00F8r-meny'....

Very nice. But where resides this SP.Res?… Perhaps, it isn’t a file, rather a name, that the javascript code is encapsulated within. The javascript object is called SP.Res.

By the way, a nice usage of it is to define the current language:

var lang = SP.Res.lcid;

ScriptResx.ashx file is located in Layouts folder and contains only one line:

<%@ WebHandler
   Language="C#" Class="Microsoft.SharePoint.ApplicationPages.ScriptResxHandler,Microsoft.SharePoint.ApplicationPages,Version=14.0.0.0,Culture=neutral,PublicKeyToken=71e9bce111e9429c"
     %>

So the class is Microsoft.SharePoint.ApplicationPages.ScriptResxHandler. Google gives no results… The Microsoft.SharePoint.ApplicationPages.dll resides in C:\inetpub\wwwroot\wss\VirtualDirectories\80\_app_bin

This is what .NET Reflector reveals:

The file is loaded is actually 14/Resources/SP.Res.resx:

Usage for other and custom .resx files

Wow, those who read all this, you’ll be awarded: You can actually load any localization files with ScriptResx.ashx (anything which can be found in 14/Resources/-folder, core, spscore and much more, or your own custom resx-files). Just add your script:

<script src="/_layouts/ScriptResx.ashx?culture=nb-no&name=Takana></script>

This will be loaded into “Res”.

One shortcoming is that multiple resx-files would override each other because every localization file loads properties into “Res” object (except SP.Res). Another shortcoming is that we can’t load culture-invariant localization files, because the filePath concatenation is much hard coded: It depends on a dot and culture-name:

Get Culture dynamically

ScriptResx.ashx depends on culture name. Sure we can put this directly in the script tag. But what if you can’t know the current language of the site? It is not so difficult actually, just get the current culture name in the asp.net markup:

<script
    type="text/javascript"
    src="/_layouts/ScriptResx.ashx?culture=<%= System.Globalization.CultureInfo.CurrentCulture.Name %>&name=Takana">
</script>

Update: An even better solution is to use L_Menu_LCID (found on Ruud Heemskerk’s Blog):

<script
    type="text/javascript"
    src="/_layouts/ScriptResx.ashx?culture=" + L_Menu_LCID + "&name=Takana">
</script>
Resolving name conflict

If you load multiple localization files, all will use “Res” name for the localization object and override the latest localizations. To solve it we must catch the Res object and encapsulate it within another object which we have control over. Here we can use many techniques, among them ExecuteOrDelayUntilScriptLoaded (with RegisterSod and LoadSod) from SharePoint, we can use head.js to load and run a callback. But the simplest way is to use jQuery.getScript function:

jQuery.getScript("/_layouts/scriptresx.ashx?culture=nb-no&name=Takana")
	.done(function() { Takana = {}; Takana.Res = Res; })
	.fail(function() {console.log("error");});
Update 2013-02-01

I found a better way to resolve the name conflict for resx-files loaded with scriptresx.ashx. Just update the classFullName resheader in your resx file. Details in my new post:

JavaScript Localization in SharePoint
Advertisements

11 responses to “ScriptResx.ashx in SharePoint

  1. Mario 2014-07-21 at 11:29

    Hello Anatoly,

    We use this approach on our sharepoint pages which works fine in IE.
    But recently we found out it does not work in Safari.

    Do you have any idea how to fix this?

    Kind regards,
    Mario

    • Anatoly Mironov 2014-07-21 at 15:55

      Hi,Mario! It should work in Safari, as it is a standard ajax call. Unfortunately I do not have access to a Mac with a Safari. Perhaps it is some authentication issue in the ajax call. I’ll try to ask somebody who does have a Mac to try it out.

  2. Mario 2014-07-21 at 16:06

    Hello Anatoly,

    I tested with Safari on windows. You can try that yourself if you want. 😉

    Kind regards,
    Mario

  3. Mario 2014-07-22 at 16:45

    Hello Anatoly,

    Thanks.
    It seems that my issue is that the script in Safari isn’t loaded yet before called.
    And this issue is not there in IE.
    So I tried window.load and document.ready but this is giving me a headache because one does not work in all browsers.
    Do you have a suggestion how to use a script that fires after document or DOM has loaded completely?

    Kind regards,
    Mario

  4. Mario 2014-07-22 at 17:02

    Hello Anatoly,

    Just to be complete. I use the following code. Which runs fine in IE (all 3 alerts) But will only return the first 2 alerts in Safari:

    window.onload=function(){

    var thisUserID = $().SPServices.SPGetCurrentUser({
    fieldName: “SipAddress”,
    debug: false
    });
    alert(thisUserID);

    // Get Current language information
    function GetCurrentCulture(){
    var lang = document.getElementsByTagName(‘html’)[0].getAttribute(‘lang’);
    var strs = lang.split(‘-‘);
    return strs[0].toString() + ‘-‘ + strs[1].toString().toUpperCase() ;
    }
    var currentCult = GetCurrentCulture();
    alert(currentCult);
    var search_query = “/_layouts/ScriptResx.ashx?culture=” + currentCult + “&name=InCompanyApps”;
    s = document.createElement(‘script’);
    s.src = search_query;
    document.getElementsByTagName(‘head’)[0].appendChild(s);

    // Get tag text according to current culture
    var myRes = Res;
    alert(“Localized Value is : ” + myRes[‘new_Item’]);
    var myID = fd.getUrlParam(window.location.href, ‘ID’);
    //alert(myID);

    }

    • Anatoly Mironov 2014-07-22 at 17:31

      Maybe, Safari treats the script tag differently, Try setting async=false: s.async=”false”. You could also provide a new onload event for the new script element: s.onload = function() { alert(Res[‘new_Item’]);}; Another thing, you shouldn’t override window.onload, it may have dangerous consequences.

  5. Mario 2014-07-22 at 17:51

    Hello Anatoly,

    Now I have included your suggestions which works fine in Safari but not in IE:

    var thisUserID = $().SPServices.SPGetCurrentUser({
    fieldName: “SipAddress”,
    debug: false
    });
    alert(thisUserID);

    // Get Current language information
    function GetCurrentCulture(){
    var lang = document.getElementsByTagName(‘html’)[0].getAttribute(‘lang’);
    var strs = lang.split(‘-‘);
    return strs[0].toString() + ‘-‘ + strs[1].toString().toUpperCase() ;
    }
    var currentCult = GetCurrentCulture();
    alert(currentCult);
    var search_query = “/_layouts/ScriptResx.ashx?culture=” + currentCult + “&name=InCompanyApps”;
    s = document.createElement(‘script’);
    s.src = search_query;
    s.async=”false”;
    document.getElementsByTagName(‘head’)[0].appendChild(s);

    s.onload = function() { alert(Res[‘new_Item’]);};

    • Anatoly Mironov 2014-07-22 at 17:55

      That’s strange. Perhaps the only thing to do is to keep the code that works in IE, and implement special code for Safari. In SharePoint javascript library, there is a variable called browseris. There you can check if it is Safari.

  6. Pingback: Accédez à vos fichiers de ressources selon la langue courante avec SharePoint 2010 | The collaboration corner

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Вула Чăвашла

VulaCV - Чăвашла вулаттаракан сайт

Discovering SharePoint

And going crazy doing it

Bram de Jager talking Office 365, SharePoint and Azure

My view and thoughts on Productivity and more.

My programming life

and everything in between

SharePoint Development Lab by @avishnyakov

It is a good place to share some SharePoint stories and development practices.

SharePoint Dragons

Nikander & Margriet on SharePoint

Paul J. Swider - RealActivity

RealActivity is a specialized healthcare services and solution advisory firm.

Mai Omar Desouki - Avid SharePointer

Egyptian & Vodafoner - Senior SharePoint Consultant

Cameron Dwyer | Office 365, SharePoint, Outlook, OnePlace Solutions

Office 365, SharePoint, OnePlace Solutions & Life's Other Little Wonders

paul.tavares

Me and My doings!

Share SharePoint Points!!

By Mohit Vashishtha

Jimmy Janlén "Den Scrummande Konsulten"

Erfarenheter, synpunkter och raljerande om Scrum från Jimmy Janlén

SPJoel

SharePoint for everyone

SharePointRyan

Ryan Dennis is a SharePoint Solution Architect with a passion for SharePoint and PowerShell

SharePoint 2020

The Vision for a Future of Clarity

Aharoni in Unicode

Treacle tarts for great justice

... And All That JS

JavaScript, Web Apps and SharePoint

%d bloggers like this: