Instructions for translators

Here is how your can help translating Lino into your own language.

Before starting to translate, you must have installed a contributor environment of Lino.


You are going to edit a series of .po files which are part of the Lino source code. Each Lino repository has its own series of .po files. Their place is given by the locale_dir setting (see Project configuration settings). Here are some examples:

To edit these .po files you can use either your preferred text editor or a tool like Poedit. We recommend the latter. On Debian you install it with apt-get install poedit.

Adding support for a new language to translate

Before you can start translating to a language, you must check whether the repository already has translation files for your language.

If you want to translate to a language for which Lino does not yet have any translations,

Every repository has a list of languages for which it provides translations. This list is in the languages parameter in the repository's file. You can add your language there.

Lino uses the same language codes as Django. You can see the list of available languages in django/conf/

After adding a language, you must run inv mm, which will ask your configuration before creating the new catalog files.

Set up a site

Let's say for example that you want to translate to Spanish.

Don't simply translate all the messages in the django.po files because

  • some translations depend on the context. It's better that you see where a message is being used before you decide how to translate it.

  • you won't need to translate all the messages. It's more efficient to focus on the most important ones.

That's why we recommend that you use a demo project to see your work while you are evolving.

Go to some local project directory (e.g. the one you created in Installing a Lino developer environment):

$ go first

Change your project's file once more so that it looks as follows:

# -*- coding: UTF-8 -*-

from lino_book.projects.min9.settings import *

class Site(Site):
    title = "My Lino Mini site"
    languages = 'en es'

SITE = Site(globals())

That is, you specify your own language distribution (in the setting) consisting of English as first language and Spanish (your language) as second. The first language cannot currently be your language because some demo fixtures would fail (docs/tickets/108).

If your language is not yet covered for Lino, then you must Create a demo user for your language before going on.

Initialize the demo database:

$ python prep

Run the development server:

$ python runserver

Point your browser to view the application. Log in as the Spanish user.


Find the strings that you want to translate

The translatable strings on this page (gettext and Poedit call them "messages") are for example the menu labels ("Contacts", "Products" etc), but also content texts like "Welcome", "Hi, Rodrigo!" or "This is a Lino demo site."

Now you must find out which django.po file contains these strings. Open another terminal window and use grep to find the file:

$ grep -H Contacts ~/repositories/lino/lino/locale/es/LC_MESSAGES/*.po
/home/repositories/work/lino/lino/locale/es/LC_MESSAGES/django.po:#~ msgid "Contacts"
$ grep -H Contacts ~/repositories/xl/lino_xl/lib/xl/locale/es/LC_MESSAGES/*.po
/home/luc/repositories/xl/lino_xl/lib/xl/locale/es/LC_MESSAGES/django.po:msgid "Contacts"
/home/luc/repositories/xl/lino_xl/lib/xl/locale/es/LC_MESSAGES/django.po:msgid "Client Contacts"
/home/luc/repositories/xl/lino_xl/lib/xl/locale/es/LC_MESSAGES/django.po:#~ msgid "Contacts"


Launch Poedit on the django.po file for the Spanish translation:

$ poedit lino/locale/es/LC_MESSAGES/django.po

It looks similar to this screenshot:


Translate one or a few messages. In our example we translated the following message:

Hi, %(first_name)s!


¡Hola, %(first_name)s!

Save your work in Poedit. Poedit will automatically compile the django.po file into a corresponding file.

Now you should first touch your file in order to tell runserver that something has changed. Open a third terminal window and type:

$ go first
$ touch

This will cause the server process (which is running in the first terminal window) to reload and to rewrite any cache files.

Refresh your browser page:


Submit your work

When you are satisfied with your work, you must make a pull request to ask us to integrate your changes into the public Lino repositories.

More about pull requests in Git cheat sheet.

Create a demo user for your language

If Lino does not yet have a default site manager user for your language (lino.modlib.users.fixtures.demo), then pm prep will say a warning:

No demo user for language 'bn'.

This means that you should create a local fixture that creates it. It's easy:

$ mkdir fixtures
$ touch fixtures/
$ nano fixtures/

The file should look as follows:

# This is needed only if Lino does not yet have a default demo
# administrator for your language.

from django.conf import settings
from lino.modlib.users.choicelists import UserTypes

def objects():
    yield settings.SITE.user_model(username="es_demo_root", language="es",

Trucs et astuces

Voici un pitfall: la traduction du string suivant:

msgid "%(person)s has been unregistered from %(course)s"

ne doit pas être:

msgstr "%(personne)s a été désinscrit du %(cours)"

mais bien:

msgstr "%(person)s a été désinscrit du %(course)s"

C.-à-d. les mots-clés entre parenthèses sont des variables, et il ne faut pas les modifier.

À noter également que le s derrière la parenthèse ne sera pas imprimé mais est obligatoire (il indique à Python qu'il s'agit d'un remplacement de type string).