Monday, November 14, 2011

Use ASP.NET Resource strings from within javascript files

It seems to be a common issue.

ASP.NET allows you to use resource files (*.resx) to localize content of pages (or views, if we are in context of ASP.NET MVC). All what you need is to put resource files under ~/App_GlobalResources folder and use either resource expression or  HttpContext.GetGlobalResourceObject() API to get a proper string. It is well documented on MSDN. The only issue - this API is not accessible within static resources such JavaScript files.

There are several solution already described by different people: Martin Normark's solution is generating static JavaScript resource files on post-build, Mads Kristensen suggest to localize text in JavaScript files by string replacing, and finally Rick Strahl introduce a localization handler to serve ASP.NET resources to JavaScript.

The last solution looks most elegant for me. Since I am working only with global resources I just simplified his solution and ended up with my own:

    public class JavaScriptResourceHandler : IHttpHandler
        public void ProcessRequest(HttpContext context)
            var requestedCulture = new CultureInfo(context.Request.QueryString["locale"]);
            var classKey = context.Request.QueryString["classKey"];
            var dictionary = ReadResources(classKey, requestedCulture);
            var javaScriptSerializer = new JavaScriptSerializer();
            var script =
if (typeof(Resources) == ""undefined"") Resources = {};
Resources." + classKey + " = " +
                javaScriptSerializer.Serialize(dictionary) + ";";
            context.Response.ContentType = "application/javascript";
            context.Response.Expires = 43200; // 30 days
        public bool IsReusable
                return false;
        private static Dictionary<object ,object> ReadResources(string classKey,
                                                           CultureInfo requestedCulture )
            var resourceManager = new ResourceManager("Resources." + classKey,
            using (var resourceSet = 
                resourceManager.GetResourceSet(CultureInfo.InvariantCulture, truetrue))
                return resourceSet
                    .ToDictionary(x => x.Key,
                         x => resourceManager.GetObject((string)x.Key, requestedCulture));

The demo project running this code might be found at Googe Code: