Going to do some
posts on JavaScript localization in the context of .Net.
So as the web slowly
drifts towards SPA style architecture (or even just unobtrusive JavaScript) the
issue of JavaScript localization rears its ugly head. In the past people might
have had the JavaScript in the page itself and they might have just used the
same mechanism as the would normally use to replace strings, the resource
ExpressionBuilder in .Net WebForms. But this technique doesn't work when you
isolate your JavaScript into js files. The server typically just serves those
files directly and doesn't process resource expressions. So what do you do for
JavaScript localization?
First, some goals
for a JavaScript localization system.
- I want all my localization to be in one format. I want to hand localizers one big file and not hand them one file for .Net and one for JavaScript. If there is a localized string it should be from essentially one source. This would allow reuse of resource strings that might otherwise be duplicated in various sources.
- It should be very easy for developers. They should touch at most two files and nothing complex should be involved.
- I only want to send the needed resources over the wire. This means I don't want to send every language my page could be in or every resource I might have in my system regardless of whether it is used client side.
- I want to support formatted strings since grammar may differ between languages.
- I don't want to incur any kind of significant processing requirements during normal usage. A request may trigger the creation of some file, but that file should be cached.
- It would be nice for this to be easy in terms of configuration and build management.
Okay, because of
goals #1 to #3 I want something to run on the server that translates a resource
requirement in a JavaScript file into a .Net resource from a resx file. So that
brings up two questions:
- How will the resources get to the client? Embedded in the JavaScript or as a separate JavaScript file? Will there be a file marked with a language/culture identifier?
- When will the processing occur? During the build or dynamically when a request is made?
So my answer to the
first question is that I would, in JavaScript, like to do something like
Resources.Dotted.Resource.Name. That makes it act like it is accessing a
JavaScript "namespace". But this can potentially have a negative
performance consequences because you might be descending a long object
hierarchy deep inside a loop. So how about
Resources["Dotted.Resource.Name"]. Then we can have a JavaScript file
that is created automatically that is like the following:
var Resources = {
"Resource.One"
: "value";
"Resource.Two"
: "another value";
}
This file can be
referenced like FileName.en-US.js. This allows a JavaScript request to
generally return the same thing every time as opposed to FileName.js sometimes
returning English and sometimes Spanish. So the question becomes when will you
do processing. Dynamically is more flexible, you just need to manage the
caching and regenerating of the file. You just build a handler that will
examine if files are modified and will compare file modification times. If it
is out of date it will go through all the JavaScript files finding instances of
Resources[].
Okay, so another
issue is that your markup code won't
contain a hardcoded culture. So this brings up another question. How will you
serve a culture specific file? One way is to have your JavaScript figure out
culture and make the correct request. Another way is to have a request like
FileName.js.axd that will be intercepted by a handler that will figure out the
culture and serve the right file. This does mean that FileName.js.axd will
return different things violating the principle of a request returning a
specified resource, but in this case I think it is okay.
So now we have an
approach. On the client will we assume we have loaded a Resources object. This
gives us the option of changing what we are doing fairly easily. On the server
we create a special handler that will dynamically generate a JavaScript file that
has the right resources. It will watch the existing JavaScript files and have
an output file that it will serve based on the browser culture.
I will use some work
done by Mads Kristensen who has a similar solution posted at http://madskristensen.net/post/Localize-text-in-JavaScript-files-in-ASPNET.aspx
No comments:
Post a Comment