Thursday, May 13th, 2010

l10n.js: JS localization library

Category: JavaScript

<p>Eli Grey has been doing some great work that we will be featuring here on Ajaxian. First up we have his recent l10n.js, which is a JavaScript library that enables localization through the native JavaScript method intended for it, gracefully degrading if the library is not present. As it
gracefully degrades, you can make Ajax applications, JavaScript libraries, etc. that can be localized but not require l10n.js to function. There is already a placeholder method for all API calls as specified in the ECMAScript specification and is present in all JavaScript engines, so when l10n.js isn’t present, your application works fine. l10n.js can integrate various partial translations with main translations easily.

For example, you can define a base English (en) localization of your application, and then for slight variations such as American English (en-US), British English (en-GB), and Hixie English (en-US-x-Hixie / en-GB-x-Hixie), you can do partial localizations where appropriate.

You can point out localizations in a link tag such as:

  1. <link rel="localizations" href="path/to/localizations.json" type="application/x-l10n+json"/>.
  2.  
  3. <link rel="localization" hreflang="en-US" href="american-english.json" type="application/x-l10n+json"/>

and the localizations themselves can look like below (taken from the demo app):

javascript
< view plain text >
  1. {
  2.     "en": {
  3.         "%title": "English - l10n.js demo",
  4.         "%info": "You are viewing an English localization of this page."
  5.     },
  6.     "en-US": {
  7.         "%title": "American English - l10n.js demo",
  8.         "%info": "You are viewing an American English localization of this page."
  9.     },
  10.     "en-GB": {
  11.         "%title": "British English - l10n.js demo",
  12.         "%info": "You are viewing a British English localisation of this page."
  13.     },
  14.     "pt": {
  15.         "%title": "Português - demo do l10n.js",
  16.         "%info": "Vocé esta a ver uma localização Portuguesa desta página."
  17.     },
  18.     "es": {
  19.         "%title": "Español - l10n.js demo",
  20.         "%info": "Mira ustéd una versión español de esta pagina."
  21.     },
  22.     "fr": {
  23.         "%title": "Français - Démo de l10n.js",
  24.         "%info": "Vous lisez une localisation en français de cette page."
  25.     }
  26. }

Now you can get access to the localized Strings via string.toLocaleString() which folks often alias so you can do l("%title.search").

What about variable replacement?

Eli suggests using short variable strings instead of default strings:

It saves bandwidth by decreasing the size of localization files, and it enables you to write nice, short code as such in the following.

javascript
< view plain text >
  1. document.title = l("%title.search")
  2. //Example results: "Seach - Acme, Inc."
  3.  
  4. confirm(l("%confirm.deleteAccount"))
  5. //Example results: "Are you sure you want to delete your account?"
  6.  
  7. link.href = "http://www.google" + l("%locale.tld")
  8. // Example results: "http://www.google.co.uk"

Often, string concatenation is used instead of replacement in JavaScript. With l10n.js, to make localization easier, you may have to use replacements instead. You might want to use a JavaScript library that implements something similar to C++’s sprintf(). A nice JavaScript implementation I’d recommend is php.js’s sprintf().

This reminds me of the localization tools in webOS. You often see $L() code in a webOS application, as well as rich formatting options:

javascript
< view plain text >
  1. return Mojo.Format.formatChoice(
  2.     numComments,
  3.     $L("0##{num} Comments|1##{num} Comment|1>##{num} Comments"),
  4.     {num: numComments}
  5. );
  6.  
  7. var data={num:10};
  8. var localizedText = $L("You have #{num} messages").interpolate(data);

Would be nice to bake in this kind of support in a more standard way.

Related Content:

12 Comments »

Comments feed TrackBack URI

I also have to handle date and numeric formatting differences between locales. I have not seen any built-in support in JScript for the latter yet.
Am I missing something?

Comment by DhtmlGuy — May 13, 2010

I also noticed that the i10n.js library actually adds toLocaleString to the String.prototype. The article refers to the method as “the native JavaScript method intended for it”; this confused me for awhile as I was unaware of any ECMA spec version that defined this method on String. You may want to clarify this in the article.

Comment by DhtmlGuy — May 13, 2010

Using full sentences as keys? Nevermind redundancy, ineffecient compression and the search and replace needed to correct spelling/wording mistakes. How about a proper level of abstraction?
.
This is just insane. :(

Comment by rasmusfl0e — May 13, 2010

@rasmusfl0e: In the article, the author actually uses abstract keys like %title.search. This would be the recommended best practice.

Ideally, if the application is server-based, you would generate the json from the server-side resource files (e.g., java properties), so you’d share keys. (This is what we do in the applications I work on, though, we use our own proprietary i18n framework). This means you can hire a localization translation service and they can just make the locale-specific properties files and not have to touch JScript.

Comment by DhtmlGuy — May 13, 2010

@rasmusfl0e: Thank you for reading my mind and getting to the point. That format is just ridiculous.

Comment by frickenate — May 13, 2010

@rasmus

I thought that was a bit weird myself.

It’s nice to have JS localization outside of webOS though! I just finished a project this would have been useful for >_<

Comment by Baryn — May 13, 2010

@both of you: it works with variables too. Nobody is requiring you to use sentences.

Comment by EliGrey — May 13, 2010

Wow, every aspect of robust applications are getting attacked by different libraries.. What’s left? What’s to come?

Only JavaScript will flow through the pipes soon…

Comment by leomdg — May 13, 2010

There is a lot of data redundancy in that JSON.
Surely “fixable” …

Comment by dbjdbj — May 13, 2010

@dbjdbj: I updated the demo to use variable string replacement so the keys are less unsightly, though it never really mattered with gzip compression.

Comment by EliGrey — May 13, 2010

@eligrey: Good :)
.
You use a “%foo.bar”-pattern – does it mean anything? It looks like it should, but as far as I can tell it’s used directly as a key (the pattern has no real function). I could just go with “fooBar”?
.
String.prototype.toLocaleString doesn’t really make any sense; it’s essentially a lookup in an object with a key – and being so doesn’t make sense for any arbitrary string. It shouldn’t be a String method – just a function that wraps a lookup and takes a string as its argument like the “l” function you propose.

Comment by rasmusfl0e — May 13, 2010

If you want to use native methods, how about going with localized DTDs? That’s how Firefox implements it.

Comment by Jordan1 — May 13, 2010

Leave a comment

You must be logged in to post a comment.