Wagtail Translate
Wagtail Translate adds machine translation to Wagtail.
It listens for Wagtail's copy_for_translation_done
signal. Wagtail emits this signal after it copies an object to another locale.
Wagtail Translate sends the supported content to a translation backend and applies the result to the copy.
Wagtail Simple Translation is a good fit for this workflow. It provides the user interface to copy content to another locale.
Wagtail Translate collects the content from a page or snippet in one translation document structured as HTML. This document keeps titles, fields, rich text, and StreamField blocks together. It gives the backend maximum context while preserving data that should not be translated.
For example, the title The match can describe a sports game or a stick used to
start a fire. Content elsewhere on the page tells the backend whether to use
Le match or L’allumette in French.
Wagtail Translate validates the returned document and restores the preserved data. It then updates the copied object.
Wagtail Translate includes backends for:
- DeepL
- OpenAI-compatible LLMs, including Ollama models
- ROT13 for tests and demonstrations
You can also write your own custom backend.
Wagtail Translate is developed and tested on Python 3.14. Python versions >=3.10 should work but are not tested.
Internationalisation and Simple Translation
Configure your project for authoring content in multiple languages.
See Wagtail documentation on internationalization and Simple Translation.
For short:
# settings.py
INSTALLED_APPS = [
# ...
"wagtail.contrib.simple_translation",
"wagtail.locales",
# ...
]
USE_I18N = True
WAGTAIL_I18N_ENABLED = True
LANGUAGE_CODE = "en"
WAGTAIL_CONTENT_LANGUAGES = LANGUAGES = [
("en", "English"),
("fr", "French"),
]
MIDDLEWARE = [
# ...
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.locale.LocaleMiddleware",
# ...
]
# urls.py
from django.conf.urls.i18n import i18n_patterns
from django.urls import include, path
from wagtail import urls as wagtail_urls
urlpatterns += i18n_patterns(
path("", include(wagtail_urls)),
)
Run migrations: python manage.py migrate.
Create locales at: /admin/locales/new/.
Installation
Install Wagtail Translate:
pip install wagtail-translate
Add to to INSTALLED_APPS and define a WAGTAIL_TRANSLATE_TRANSLATOR.
# settings.py
INSTALLED_APPS = [
# ...
"wagtail_translate",
"wagtail_translate.default_behaviour",
# ...
]
WAGTAIL_TRANSLATE_TRANSLATOR = "wagtail_translate.translators.rot13.ROT13HTMLDocumentTranslator"
In the Wagtail admin interface, go to the homepage, in the dot-dot-dot-menu, choose "Translate".
The contents should be translated! 🥳
Translation backends
DeepL
Install the DeepL extra:
pip install "wagtail-translate[deepl]"
Add the backend and API key to your settings:
WAGTAIL_TRANSLATE_TRANSLATOR = (
"wagtail_translate.translators.deepl.DeepLHTMLDocumentTranslator"
)
WAGTAIL_TRANSLATE_DEEPL_KEY = "your-api-key"
OpenAI-compatible LLM
Install the LLM extra:
pip install "wagtail-translate[llm]"
The backend uses an OpenAI-compatible Chat Completions API. The default endpoint is a local Ollama server.
Configure a local model:
WAGTAIL_TRANSLATE_TRANSLATOR = (
"wagtail_translate.translators.openai_compatible.LLMHTMLDocumentTranslator"
)
WAGTAIL_TRANSLATE_LLM_MODEL = "translategemma:27b"
WAGTAIL_TRANSLATE_LLM_BASE_URL = "http://localhost:11434/v1/"
WAGTAIL_TRANSLATE_LLM_API_KEY = "ollama"
ROT13
ROT13HTMLDocumentTranslator replaces each letter with the letter 13 positions
later in the alphabet. Applying ROT13 twice restores the original text.
This backend is deterministic and does not use an external service. Use it for tests and demonstrations, not for real translations.
Default behaviour
The wagtail_translate.default_behaviour app adds the copy_for_translation_done signal handler.
The handler initiates the translation and saves the Wagtail object.
Use a custom app if you'd like to customize. For more details:
Development and testing
Install the package with its test dependencies:
make install
Activate the virtual environment:
source .venv/bin/activate
Run all checks and tests:
make test
Fix code style:
make fix-codestyle
Demo project
Use the tests/testproject Django and Wagtail project for manual tests and
demonstrations:
python tests/testproject/manage.py migrate
python tests/testproject/manage.py createsuperuser
python tests/testproject/manage.py createcontent
python tests/testproject/manage.py runserver
The createcontent command resets the demo page tree. It then creates pages
with ambiguous words, rich text, nested StreamField blocks, images, documents,
and related snippets.
The demo uses the ROT13 backend by default. Change the translator settings in
tests/testproject/settings.py to test DeepL or a local LLM.
Release
GitHub Actions publishes a release to PyPI when a v* tag is pushed.
Update the project version with uv:
uv version 1.0.0
git add pyproject.toml
git commit -m "Release 1.0.0"
git tag v1.0.0
git push
git push origin v1.0.0
The Git tag must match the package version with a v prefix. For example,
version = "1.0.0" uses the tag v1.0.0.
You can create a GitHub Release after you push the tag. If GitHub creates the tag, make sure that the version commit is already on the target branch.
Build and inspect the package locally before a release:
uv build
This command writes the release artifacts to dist/. Check the generated files
and make sure that they contain the package modules:
tar -tf dist/wagtail_translate-*.tar.gz
unzip -l dist/wagtail_translate-*.whl
Metadata
Release files for wagtail-translate 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| wagtail_translate-1.0.0.tar.gz | 13.7 kB | Without provenance | Details for wagtail_translate-1.0.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| wagtail_translate-1.0.0-py3-none-any.whl | Python 3 | none | any | Details for wagtail_translate-1.0.0-py3-none-any.whl |
Total release size: 29.9 kB
Release files / wagtail_translate-1.0.0.tar.gz
| Download URL | wagtail_translate-1.0.0.tar.gz |
|---|---|
| Size | 13.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9d76ccd78199e3741aa65d6f01e47ba3901222c83d74f0caba80f7c5accfc997
|
|
BLAKE2b-256 checksum How to use checksums |
746fb41809e69bd2da50b565f509fbc0fcaf5ad66b8976264572191f36d9cc5f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.1 {"installer":{"name":"uv","version":"0.13.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / wagtail_translate-1.0.0-py3-none-any.whl
| Download URL | wagtail_translate-1.0.0-py3-none-any.whl |
|---|---|
| Size | 16.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
330f217b31a5e0faed611bc5798e348162ccbb78e4618ad7c1ea2dcb23cc5065
|
|
BLAKE2b-256 checksum How to use checksums |
91f5901c011d90bffa5e0498b8b20d80f5b3248a6d859564a09fcf422e9e4a3f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.1 {"installer":{"name":"uv","version":"0.13.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Security for wagtail-translate 1.0.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.