Internationalization: How to Localize HTML5 Projects?

While working on a HTML5 project I came across the problem that I needed to localize it to different languages. Therefore obviously strings of HTML tags as well as JavaScript files need to be translated.

Although I think internationalization is something very important in a globally connected world, it looks like as this topic was completely forgotten for HTML5 development. I just found a proposal in the Common JS Wiki regarding that with no activity since more than a year!

After searching for while I found this post about Passive localization in JavaScript. Of course, I would prefer an officially standardized approach for the localization, but anyway, this JavaScript library is very helpful to use in the meantime until there is an an officially standardized solution.

In the following I will explain how I use this library, not only for JavaScript files, but also for translating the content of HTML tags.

HTML5 Test Page

First of all we need a small HTML5 test page like this:

<!doctype html>
<html class="no-js" lang="en">
	<meta charset="utf-8">
	<title>Internationalization Test</title>

	<link rel="localization" hreflang="de" href="lang/de.json" type="application/vnd.oftn.l10n+json"/>
	<link rel="stylesheet" href="css/style.css">
	<script type="text/javascript" src="js/i18n.js"></script>
	<script type="text/javascript" src="js/script.js"></script>
<body onload="loaded()">
	<h1 id="headertext">This is an Internationalization Test!</h1>
	<h2 id="subtitletext">With any subtitle.</h2>
	<a id="showinenglish" href="index.html?lang=en">Show in English</a>
	<a id="showingerman" href="index.html?lang=de">Show in German</a>

You can see that I assigned IDs to all major HTML tags. We will use them later on for doing the translation.

JavaScript Helper Functions

Before starting with the translation itself, we need some JavaScript helper functions first:

var _ = function (string) {
	return string.toLocaleString();

function localizeHTMLTag(tagId)
	tag = document.getElementById(tagId);
	tag.innerHTML = _(tag.innerHTML);

function getParameterValue(parameter)
	parameter = parameter.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
	var regexS = "[\\?&]" + parameter + "=([^&#]*)";
	var regex = new RegExp(regexS);
	var results = regex.exec(window.location.href);
	if(results == null)
		return "";
		return results[1];

Here is a short explanation about what these helper functions are doing:

  • _(): that’s just a short form of the prototype string.toLocaleString().
  • localizeHTMLTag(tagId): this function gets the appropriate HTML element from the DOM tree based on the passed tag ID and directly does the translation afterwards.
  • getParameterValue(parameter): we’ll need this function to get a URL parameter value to change the language of the page upon user request.

Doing the Localization

We have all needed parts to do our localization which is really easy now:

function loaded()
	var lang = getParameterValue("lang");
	if (lang != "") String.locale = lang;

	alert(_("Localizing the document title..."));
	document.title = _(document.title);

	alert(_("Localizing other HTML tags..."));

	alert(_("Localizing done!"));

There is just one function loaded(), which is called after the document is loaded (see the event in body tag of the HTML5 test page above). First we check if there is an URL parameter lang in case the user changed the page language with the links. Otherwise we don’t need to change the locale (the default browser locale of the user will be used automatically).

Afterwards we can start doing our translation by directly translating a string with the function _() or by using our function localizeHTMLTag(tagId) to translate the content of a HTML tag. That’s it! :-)

What About More Languages?

If you want to add more or other languages, you just need to add a new localization link in the HTML head section together with a JSON file containing the translations for the new language.

Why not Using Short Variable Names?

The author of this JavaScript internationalization library suggests to use short variable strings instead of the default translations. Therefore I want to give an explanation why I’m not doing this in my example as he is, of course, right that using the default translations adds some overhead to the project. But using short variable names would have at least these two disadvantages, too:

  • your HTML5 page would no longer work without a translation, because otherwise only the short variable names would be displayed. In my example project it would just display the default translation (English) when no internationalization system is available.
  • I still hope that there will be a standardized way to do internationalization for HTML5 projects. Then probably you will need to have the default translation inside the HTML tags as the de facto standard for doing e. g. translation of PHP projects is to use gettext files (.po). That’s also the way the mentioned proposal suggests to do it. Therefore when I want to switch to such a way of internationalization somewhen in the future, I don’t like to copy all default translations back into the HTML tags.

Download Example Project

If you like, you can download the source of my example project.


I’ve updated the example project as there was one comma too much in the JSON file which caused it to only work in Mozilla Firefox (not in Microsoft Internet Explorer and Google Chrome). That’s fixed now – thanks Margaret Wong for letting me know about that!

But please keep in mind that you have to upload the files to a webserver for testing as they probably won’t work in Internet Explorer and Chrome locally due to browser access restrictions. Anyway, the example project will work fine now when you upload it to a webserver.

What concept you’re using for localizing your HTML5 projects?

This post is also available in Deutsch.

3 thoughts on “Internationalization: How to Localize HTML5 Projects?

  1. Pingback: MunichJS: Speech About Internationalization of HTML5 Apps and Using Encapsulator |

  2. Hi,

    In order to get all JSON lang data from a server-side response, I have modified a bit your sample code.

    With this “feature”, you can use “key” instead of a real string in the code (html or js). So you can get all of strings from any Url witch respond the appropriate json response.

    Here, the function loaded() gets the value of lang attribute in HTML tag. Then put this value in String.locale. So localization aims to load the associated JSON file even no parameter found in URL.

    In the script.js :

    function loaded()
    //The default HTML lang
    var getDefaultLang = document.documentElement.lang;

    var lang = getParameterValue(“lang”);
    if (lang != “”) String.locale = lang;

    //Set if there’s no parameter in URL
    else String.locale = getDefaultLang;

    //Put key instead hard string, here a new format like #{string_localize} can be
    //better to read the code
    document.title = _(document.title);



    In the index.html file :


    fr.json :

    “inter_test”: “Test internationalisation…”,
    “string_text”: “Ceci est un test d’internationalisation !”,
    “string_subtitle”: “Avec sous titre”,
    “show”: “Voir en Anglais”,
    “string_show_french”: “Voir en Francais”,
    “string_localize_init”: “Init title du document…”,
    “string_localize_other”: “Init HTML Tags…”,
    “string_localize_done”: “Localisation terminée !”

    en.json :

    “inter_test”: “Internationalization Test”,
    “string_text”: “This is an Internationalization Test!”,
    “string_subtitle”: “With any subtitle.”,
    “show”: “Show in French”,
    “string_show_french”: “Show in English”,
    “string_localize_init”: “Localizing the document title…”,
    “string_localize_other”: “Localizing other HTML tags…”,
    “string_localize_done”: “Localizing done!”

    Pe@ce and thx for this pretty cool how to :)

Leave a Reply

Your email address will not be published. Required fields are marked *


You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>