Internationalization (i18n)¶
See also
Preferred packages for Internationalization (i18n)
Treat the source language as “developer” English, using the language code en_US. Then, translate the “developer” English to “proper” English, using the language code en.
Note
If using the source language as “proper” English, then replace en_US with en in the commands and templates below.
Reference:
Non-English as a Source Language (Transifex)
Django Translation
Install dependencies¶
pip install -r docs/requirements.txt sphinx-intl
pip install -r requirements.txt
pip install ocdsextensionregistry[cli] sphinx-intl
pip install babel
If you use a translation tool:
Install the Crowdin CLI:
npm install -g @crowdin/cli
Set the Crowdin personal access token in the .crowdin.yml file in your home directory:
api_token: ...
Install the Transifex Client.
Initialize tool configuration¶
If you use a translation tool:
Create the project on Crowdin.
In the project’s Customize Tabs settings, disable all except Sources, Members and Activity.
Add managers to the project.
Find the project’s ID:
crowdin project list -i 1
Create the configuration file, using
manage.pyfrom data-support:path/to/manage.py update-crowdinyml-files --project-id PROJECT_ID
sphinx-intl create-txconfig
Mark strings to translate¶
When using Django, use its translation functions and template tags. Otherwise, use gettext.gettext().
Configure message extraction¶
When using Django, this step is already done. Otherwise, create a pyproject.toml file, for example:
[[tool.babel.mappings]]
method = "python"
pattern = "**.py"
[[tool.babel.mappings]]
method = "jinja2"
pattern = "**.html"
Extract strings to translate¶
Whenever text in the interface is added or updated, you must extract the strings to translate from the code files into PO files by running:
django-admin makemessages --no-obsolete -l en_US
If you are not using a translation tool, update the translation files. For example:
django-admin makemessages --no-obsolete -l en -l es
sphinx-build -nW --keep-going -q -b gettext docs/ docs/_build/gettext
If you are not using a translation tool, update the translation files:
sphinx-intl update -p docs/_build/gettext -d docs/locale
make extract
If you are not using a translation tool, update the translation files:
sphinx-intl update -p build/locale -d locale
pybabel extract -F pyproject.toml -o messages.pot .
pybabel update -N -i messages.pot -d locale
Update tool configuration¶
If you use a translation tool, whenever a new PO file is added, you must update its configuration.
Using manage.py from data-support:
# Sphinx:
path/to/manage.py update-crowdinyml-files -p docs/_build/gettext -d docs/locale
# Standard or Extensions:
path/to/manage.py update-crowdinyml-files -p build/locale -d locale
Translate with a tool¶
Push the PO files:
crowdin push sources
tx push -s
If you made local changes to translations, push the translations. For example:
crowdin push translations --import-eq-suggestions -l es-ES
tx push -t -l es
When ready, pull the translations with:
crowdin pull translations
tx pull -f -a
Compile the PO files to MO files¶
python manage.py compilemessages
sphinx-intl build -d docs/locale
This step isn’t required.
sphinx-intl build -d locale
pybabel compile -f -d locale
Continuous integration¶
Repositories that support multiple locales should test that translation files are complete. To do that, the workflow extracts messages, updates catalogs, and then counts incomplete translations.
Note
These workflows only run on push for the main branch, so that feature branches don’t fail until a PR is created.
Create a .github/workflows/i18n.yml file.
For a Django application, reuse the i18n-django workflow. Change the python-version to match the version used to compile the requirements_dev.txt file.
name: Translations
on:
pull_request: {}
push:
branches: [main]
jobs:
i18n:
uses: open-contracting/.github/.github/workflows/i18n-django.yml@main
permissions:
contents: read
with:
source: en_US
python-version: '{{ cookiecutter.python_version }}'
For a Babel project, reuse the i18n-babel workflow. Change the command as needed:
name: Translations
on:
pull_request: {}
push:
branches: [main]
jobs:
i18n:
uses: open-contracting/.github/.github/workflows/i18n-babel.yml@main
permissions:
contents: read
with:
command: |
pybabel extract -F pyproject.toml -o messages.pot .
pybabel update -N -i messages.pot -d locale
Warning
If your default branch is not named main, edit the push: key.
Note
If you use the jinja2 extractor, install jinja2 with pip.