What I came up with was a pattern using JQuery AJAX and JSON to download the resource file to the browser. The translations are available using the same object notation available on the server eg
// -- Localisation -- var localResources; var globalResources; //Sample JSON for javascript resource values eg {TrackDetail:{HideHelp:"Hide Help", ShowHelp:"Show Help"}} //Usage e.g: alert(localResources.TrackDetail.HideHelp); //Load Localisation values into variables so that they can be available on the client //Note that these values are loaded asynchronously, the code in the function will not run until the call has completed. $.getJSON('Localisation.ashx?files=TrackDetail.aspx.resx&local=true', function(data) { localResources = data}); $.getJSON('Localisation.ashx?files=Errors.resx,Strings.resx', function(data) { globalResources = data});
The code on the server reads the local or global resource file and streams the contents back as a JSON formatted object. Note that I opted to roll my own JSON serialization code instead of using one of the built-in serializers.
Imports System.Web Imports System.Web.Services Imports System.Xml Imports System.Resources Imports System.Reflection Public Class Localisation Implements System.Web.IHttpHandler Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest Dim files As String = context.Request.QueryString("files") Dim local As String = context.Request.QueryString("local") Dim isLocal As Boolean Dim folder As String = "App_GlobalResources" context.Response.ContentType = "text/javascript" 'Write out file as object context.Response.Write("{") 'Determine if local resource file If local IsNot Nothing Then isLocal = CBool(local) If isLocal Then folder = "App_LocalResources" End If If files Is Nothing OrElse files.Length = 0 Then Throw New ArgumentException("Parameter 'files' was not provided in querystring.") Dim flag As Boolean = False For Each file As String In files.Split(",") If flag Then context.Response.Write(",") Dim className As String = file.Split(".")(0) 'Write the class (name of the without any extensions) as the object context.Response.Write(className) context.Response.Write(":{") 'Open the resx xml file Dim filePath As String = context.Server.MapPath("~\" & folder & "\" & file) Dim document As New XmlDocument() Dim flag2 As Boolean = False document.Load(filePath) Dim nodes As XmlNodeList = document.SelectNodes("//data") For Each node As XmlNode In nodes 'Write out the comma seperator If flag2 Then context.Response.Write(",") Dim attr As XmlAttribute = node.Attributes("name") Dim resourceKey As String = attr.Value context.Response.Write(resourceKey) context.Response.Write(":""") 'Write either the local or global value If isLocal Then context.Response.Write(HttpContext.GetLocalResourceObject(String.Format("~/{0}", file.Replace(".resx", "")), resourceKey)) 'Has to be full path to the .aspx page Else context.Response.Write(HttpContext.GetGlobalResourceObject(className, resourceKey)) End If context.Response.Write("""") 'Flag that we need a comma seperator flag2 = True Next context.Response.Write("}") flag = True Next 'End file context.Response.Write("}") End Sub Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable Get Return True End Get End Property End Class