Internationalization of HTML pages for my Google Chrome Extension

Building from ahmd0's answer. Use a data attribute to allow a hard-coded fallback.

<!DOCTYPE html>
<html>
    <head>
        <title data-localize="__MSG_app_title__">My Default Title</title>
    </head>
    <body>
        <a href="http://example.com/" title="__MSG_prompt001__" data-localize="__MSG_link001__">Default link text</a>

        <script src="localize.js"></script>
    </body>
</html>

Then provide the usual translation in _locales\en\messages.json:

{
    "app_title": {
        "message": "MyApp",
        "description": "Name of the extension"
    },
    "link001": {
        "message": "My link",
        "description": "Link name for the page"
    },
    "prompt001": {
        "message": "Click this link",
        "description": "User prompt for the link"
    }
}

And finally your localize.js will perform the actual localization:

function replace_i18n(obj, tag) {
    var msg = tag.replace(/__MSG_(\w+)__/g, function(match, v1) {
        return v1 ? chrome.i18n.getMessage(v1) : '';
    });

    if(msg != tag) obj.innerHTML = msg;
}

function localizeHtmlPage() {
    // Localize using __MSG_***__ data tags
    var data = document.querySelectorAll('[data-localize]');

    for (var i in data) if (data.hasOwnProperty(i)) {
        var obj = data[i];
        var tag = obj.getAttribute('data-localize').toString();

        replace_i18n(obj, tag);
    }

    // Localize everything else by replacing all __MSG_***__ tags
    var page = document.getElementsByTagName('html');

    for (var j = 0; j < page.length; j++) {
        var obj = page[j];
        var tag = obj.innerHTML.toString();

        replace_i18n(obj, tag);
    }
}

localizeHtmlPage();

The hard-coded fallback avoids the i18n tags being visible while the JavaScript does the replacements. Hard-coding seems to negate the idea of internationalisation, but until Chrome supports i18n use directly in HTML we need to use JavaScript.


Plain an simple:


{
  "exmaple_key": {
    "message": "example_translation"
  }
}


<sometag data-locale="example_key">fallback text</sometag>


document.querySelectorAll('[data-locale]').forEach(elem => {
  elem.innerText = chrome.i18n.getMessage(elem.dataset.locale)
})


What you would do is this.

First, in your HTML use the same syntax as Chrome requires anywhere else. So your basic popup.html will be:

<!DOCTYPE html>
<html>
<head>
<title>__MSG_app_title__</title>
</head>
<body>

<a href="http://example.com/" title="__MSG_prompt001__">__MSG_link001__</a>

<!-- Need to call our JS to do the localization -->
<script src="popup.js"></script>
</body>
</html>

Then provide the usual translation in _locales\en\messages.json:

{
    "app_title": {
        "message": "MyApp",
        "description": "Name of the extension"
    },
    "link001": {
        "message": "My link",
        "description": "Link name for the page"
    },
    "prompt001": {
        "message": "Click this link",
        "description": "User prompt for the link"
    }
}

And finally your popup.js will perform the actual localization:

function localizeHtmlPage()
{
    //Localize by replacing __MSG_***__ meta tags
    var objects = document.getElementsByTagName('html');
    for (var j = 0; j < objects.length; j++)
    {
        var obj = objects[j];

        var valStrH = obj.innerHTML.toString();
        var valNewH = valStrH.replace(/__MSG_(\w+)__/g, function(match, v1)
        {
            return v1 ? chrome.i18n.getMessage(v1) : "";
        });

        if(valNewH != valStrH)
        {
            obj.innerHTML = valNewH;
        }
    }
}

localizeHtmlPage();