views:

2013

answers:

5

Hi folks,

what is the best practice for multilanguage website using DOM Manipulating with javascript? I build some dynamic parts of the website using javascript. My first thought was using an array with the text strings and the language code as index. Is this a good idea?

+4  A: 

When I've built multi-lingual sites before (not very large ones, so this might not scale too well), I keep a series of "language" files:

  • lang.en.js
  • lang.it.js
  • lang.fr.js

Each of the files declares an object which is basically just a map from key word to language phrase:

// lang.en.php
lang = {
    greeting : "Hello"
};

// lang.fr.php
lang = {
    greeting : "Bonjour"
};

Dynamically load one of those files and then all you need to do is reference the key from your map:

document.onload = function() {
    alert(lang.greeting);
};

There are, of course, many other ways to do this, and many ways to do this style but better: encapsulating it all into a function so that a missing phrase from your "dictionary" can be handled gracefully, or even do the whole thing using OOP, and let it manage the dynamic including of the files, it could perhaps even draw language selectors for you, etc.

var l = new Language('en');
l.get('greeting');
nickf
+2  A: 

Just found a nice article about i18n in javascript:
http://24ways.org/2007/javascript-internationalisation

Although a simple google search with i18n + javascript reveals plenty of alternatives.

In the end, it depends on how deep you want it to be. For a couple of languages, a single file is enough.

You could use a framework like Jquery, use a span to identify the text (with a class) and then use the id of each span to find the corresponding text in the chosen language.
1 Line of Jquery, done.

Berzemus
HOW DO THE REINDEER TYPE?? THEY HAVE HOOVES!!
nickf
+1  A: 

There are are a few things you need to keep in mind when designing multilanguage support:

1 - Separate code from data (i.e. don't hard-code strings right into your functions)

2 - create a formatting hook function to deal with localization differences. Allowing formattable strings ("{0}") is better than concatenating ("Welcome to" + value), for a lot of reasons:

  • in some languages, a number is formatted like 1.234.678,00 instead of 1,234,567.00
  • pluralization is often not as simple as appending an "s" at the end of the singular
  • grammar rules are different and can affect the order of things so you should allow dynamic data to be appended after the translation hook: for example, "Welcome to {0}" turns into "{0} he youkoso" in japanese (this happens in pretty much every language, mind you).

3 - Make sure that you can actually format strings after the translation hook runs, so you can reuse keys.

4 - Do not, under any circunstance, hook database outputs to the translator utility. If you have multilingual data, create separate tables / rows in your database. I've seen people get this no-brainer wrong fairly often (usually for countries and states/provinces in forms).

5 - Create explicit coding practices rules for creating keys. The formatter utility function (which will look something like translate("hello world") will take a key as a parameter, and keys with slight variations make maintainance very annoying. For instance, you might end up with three keys in the following example: "enter you name", "enter your name:", "enter your name: ". Choose one format (e.g. no colon, trimmed) and catch discrepancies in code reviews. Don't do this filtering programmatically, as it can trigger false positives.

6 - Be mindful that HTML markup could potentially be needed in the translation table (e.g. if you need to bold a word in a sentence, or have footnote medical references). Test for this extensively.

7 - There are several ways of importing language strings. Ideally, you should have multiple versions of a language.lang.js file, switch between them with server side code, and reference the file from the bottom of the HTML file. Pulling the file via AJAX is also an alternative, but could introduce delays. Merging language.js into your main code file is not advisable, since you lose the benefits of file caching.

8 - Test with your target languages. This sounds silly, but I've seen a serious bug once because the programmer didn't bother to check for the existence of "é" in the key.

Leo
A: 

You should look into what has been done in classic JS components - take things like Dojo, Ext, FCKEditor, TinyMCE, etc. You'll find lots of good ideas.

Usually it ends up being some kind of attributes you set on tags, and then you replace the content of the tag with the translation found in your translation file, based on the value of the attribute.

One thing to keep in mind, is the evolution of the language set (when your code evolves, will you need to retranslate the whole thing or not). We keep the translations in PO Files (Gnu Gettext), and we have a script that transforms the PO File into ready to use JS Files.

Bertrand Gorge
A: 

Forgot two things :

  • Always use UTF-8 - this sounds silly, but if you are not in utf-8 from start (HTML head + JS encoding), you'll be bust quickly.
  • Use the english string as a key to your translations - this way you won't end up with things like: lang.Greeting = 'Hello world' - but lang['Hello world'] = 'Hello world';
Bertrand Gorge