You can take advantage of HTML bindings to localize your HTML documents with L20n.
We maintain a repository with L20n optimized for production use:
It's recommended to include the l20n.js file as the last script in the head
element.
<head> … <script src="l20n.js"></script> </head>
Use a localization manifest to define available languages and their resource files.
<link rel="localization" href="../locales/manifest.json">
An example of the manifest file (all keys are required):
{ "locales": [ "en-US", "pl"], "default_locale": "en-US", "resources": [ "../locales/{{locale}}/strings.l20n", "/shared/{{locale}}/date.l20n"¨ ] }
Use the data-l10n-id
attribute on an HTML element to mark it as localizable.
<p data-l10n-id="about"></p>
Notice that you don't have to put the text content in the HTML anymore (you still can if you want to). All content lives in the localization resources.
A safe subset of HTML elements (e.g. em
, sup
), attributes (e.g. title
) and entities can be used in translations. In addition to the pre-defined whitelists, any element found in the original source HTML is allowed in the translation as well. Consider the following source HTML:
<p data-l10n-id="save"> <input type="submit"> <a href="/main" class="btn-cancel"></a> </p>
Assume the following malicious translation:
<save """ <input value="Save" type="text"> or <a href="http://myevilwebsite.com" onclick="alert('pwnd!')" title="Back to the homepage">cancel</a>. """>
The result will be:
<p data-l10n-id="back"> <input value="Save" type="submit"> or <a href="/main" class="btn-cancel" title="Back to the homepage">cancel</a>. </p>
The input
element is not on the default whitelist but since it's present in the source HTML, it is also allowed in the translation. The value
attribute is allowed on input
elements, but type
is not. Similarly, href
and onclick
attributes are not allowed in translations and they are not inserted in the final DOM. However, the title
attribute is safe.
It is important to note that applying translations doesn't replace DOM elements, but only modifies their text nodes and their attributes. This makes it possible to use L20n in conjunction with MVC frameworks.
When all DOM nodes are localized, the document
element will fire a DocumentLocalized
event, which you can listen to:
document.addEventListener('DocumentLocalized', function() { // the DOM has been localized and the user sees it in their language YourApp.init(); });
You can expose important bits of data to the localization context in form of context data.
<script type="application/l10n-data+json"> { "newNotifications": 3, "user": { "name": "Jane", "gender": "feminine" } } </script>
This data will be available context-wide to all localized strings. For instance, a string could use the information about the user's gender to provide two variants of the translation, like in the example below. See L20n by Example to learn more about L20n's syntax.
<invited[$user.gender] { feminine: "{{ $user.name }} has invited you to her circles.", masculine: "{{ $user.name }} has invited you to his circles.", *unknown: "{{ $user.name }} has invited you to their circles." }>
Based on the context data defined above, this will produce:
Jane has invited you to her circles.
L20n can also operate in the so-called monolingual mode, when there is only one locale available. It doesn't have any specific locale code (internally, it's called i-default
in compliance to RFC 2277). There is no language negotiation nor locale fallback possible in the monolingual mode. L20n simply always uses this one default locale.
The monolingual mode may be useful when you first start a new project, when you want to test something quickly or when using server-side language negotiation.
In order to enable the monolingual mode, remove the manifest link
from your HTML. With no information about the available and the default locales, L20n will switch to the monolingual mode. You can then embed localization resources right in your HTML.
<script type="application/l20n"> <brandName "Firefox"> <about "About {{ brandName }}"> </script>
An alternative is to include localization resources in script
elements. Note that this still only works for a single language. We plan to add support for a Language Pack Service in the future that can tap into this scenario on the client side.
<script type="application/l20n" src="../locales/strings.l20n"></script>
Note that you currently cannot use the manifest file and manually add resources via script
tags at the same time (bug 923670).