Skip to content


Subversion checkout URL

You can clone with
Download ZIP
Fetching contributors…
Cannot retrieve contributors at this time
237 lines (165 sloc) 7.25 KB


The site is fully localizable. Localization files are not shipped with the code distribution, but are available on SVN:

git svn clone locale
# or
svn checkout locale

.lang files

Bedrock supports a workflow similar to gettext. You extract all the strings from the codebase, then merge them into each locale to get them translated.

The files containing the strings are called ".lang files" and end with a .lang extension.

To extract all the strings from the codebase, run:

$ ./ l10n_extract

That will use gettext to get all the needed localizations from python and html files, and will convert the result into a bunch of .lang files inside locale/templates. This directory represents the "reference" set of strings to be translated, and you are free to modify or split up .lang files here as needed (just make sure they are being reference correctly, from the code, see :ref:`Which .lang file should it use? <which-lang>`).

To merge new strings into locale directories, run:

$ ./ l10n_merge

If you want to merge only specific locales, you can pass any number of them as arguments:

$ ./ l10n_merge fr de

Translating with .lang files

To translate a string from a .lang file, simply use the gettext interface.

In a jinja2 template:

<div>{{ _('Hello, how are you?') }}<div>

<div>{{ _('<a href="%s">Click here</a>')|format('') }}</div>

<div>{{ _('<a href="%(url)s">Click here</a>')|format(url='') }}</div>

Note the usage of variable substitution in the latter examples. It is important not to hardcode URLs or other parameters in the string. jinja's format filter lets us apply variables outsite of the string.

There's another way to translate content within jinja2 templates. If you need a big chunk of content translated, you can put it all inside a trans block.

{% trans %}
  <div>Hello, how are you</div>
{% endtrans %}

{% trans url='' %}
  <div><a href="{{ url }}">Click here</a></div>
{% endtrans %}

Note that it also allows variable substitution by passing variables into the block and using template variables to apply them.

Which .lang file should it use?

Translated strings are split across several .lang files to make it easier to manage separate projects and pages. So how does the system know which one to use when translating a particular string?

  • All translations from Python files are put into main.lang. This should be a very limited set of strings and most likely should be available to all pages.
  • Templates always load in main.lang, base.lang, and newsletter.lang
  • Additionally, each template has its own .lang file, so a template at mozorg/firefox.html would use the .lang file at <locale>/mozorg/firefox.lang.
  • Templates can override which lang files are loaded. The above 3 global ones are always loaded, but instead of loading <locale>/mozorg/firefox.lang, the template can specify a list of additional lang files to load with a template block:
{% add_lang_files "foo" "bar" %}

That will make the page load foo.lang and bar.lang in addition to main.lang, base.lang, and newsletter.lang.

When strings are extracted from a template, that are added to the template-specific .lang file. If the template explicitly specifies .lang files like above, it will add the strings to the first .lang file specified, so extracted strings from the above template would go into foo.lang.

l10n blocks

Bedrock also has a block-based translation system that works like the {% block %} template tag, and marks large sections of translatable content. This should not be used very often; lang files are the preferred way to translate content. However, there may be times when you want to control a large section of a page and customize it without caring very much about future updates to the English page.

A Localizers' guide to l10n blocks

Let's look at how we would translate an example file from English to German.

The English source template, created by a developer, lives under apps/appname/templates/appname/example.html and looks like this:

{% extends "base.html" %}

{% block content %}
  <img src="someimage.jpg">

  {% l10n foo, 20110801 %}
  <h1>Hello world!</h1>
  {% endl10n %}


  {% l10n bar, 20110801 %}
  <p>This is an example!</p>
  {% endl10n %}
{% endblock %}

The l10n blocks mark content that should be localized. Realistically, the content in these blocks would be much larger. For a short string like above, please use lang files. We'll use this trivial code for our example though.

The l10n blocks are named and tagged with a date (in ISO format). The date indicates the time that this content was updated and needs to be translated. If you are changing trivial things, you shouldn't update it. The point of l10n blocks is that localizers completely customize the content, so they don't care about small updates. However, you may add something important that needs to be added in the localized blocks; hence, you should update the date in that case.

When the command ./ l10n_extract is run, it generates the corresponding files in the locale folder (see below for more info on this command).

The german version of this template is created at locale/de/templates/appname/example.html. The contents of it are:

{% extends "appname/example.html" %}

{% l10n foo %}
<h1>Hello world!</h1>
{% endl10n %}

{% l10n bar %}
<p>This is an example!</p>
{% endl10n %}

This file is an actual template for the site. It extends the main template and contains a list of l10n blocks which override the content on the page.

The localizer just needs to translate the content in the l10n blocks.

When the reference template is updated with new content and the date is updated on an l10n block, the generated l10n file will simply add the new content. It will look like this:

{% extends "appname/example.html" %}

{% l10n foo %}
<h1>This is an English string that needs translating.</h1>
{% was %}
<h1>Dies ist ein English string wurde nicht.</h1>
{% endl10n %}

{% l10n bar %}
<p>This is an example!</p>
{% endl10n %}

Note the was block in foo. The old translated content is in there, and the new content is above it. The was content is always shown on the site, so the old translation still shows up. The localizer needs to update the translated content and remove the ``was` block.

Generating the locale files

./ l10n_check

This command will check which blocks need to be translated and update the locale templates with needed translations. It will copy the English blocks into the locale files if a translation is needed.

You can specify a list of locales to update:

./ l10n_check fr
./ l10n_check fr de es
Jump to Line
Something went wrong with that request. Please try again.