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.

Set up a site

During translation you will use the demo sites to see your work while you are evolving. You cannot simply translate all those messages and believe that they are correct.

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

Go to your local project directory:

$ cd ~/mysite

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

# -*- coding: UTF-8 -*-
from __future__ import unicode_literals

from 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 the 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 your development server

Run the development server on the demo database:

$ go min9
$ python runserver

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


Find the translatable strings

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

Now you must locate these strings in the .po file.

Open another terminal window and go to the Lino repository.

$ cd ~/repositories/lino


Launch Poedit, specifying the .po file for the Spanish translation (international language code for Spanish is es):

$ 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.

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

$ cd ~/mysite
$ 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 will make a pull request to ask us to integrate your changes into the public Lino repositories.

More about pull requests in Basic git skills.

Create a demo user for your language

If Lino does not yet have a default demo administrator for your language (lino.modlib.users.fixtures.demo), then you need to create a local fixture which adds a demo user for your language. It's easy:

$ mkdir fixtures
$ touch fixtures/
$ nano fixtures/

The file should look as folloas:

# 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).