Architecture¶
How it works¶
django-traduire sits between django-modeltranslation and a translation API:
Your Django models
|
django-modeltranslation (creates title_fr, title_de, title_en, ...)
|
django-traduire (decides what to translate, writes the columns back)
|
chunking + richtext + htmltokens (makes the text fit, keeps the markup)
|
Translation backend (Google free / DeepL / Google Cloud / OpenAI / yours)
Core flow¶
- Discover fields — asks
modeltranslation.translatorwhich fields are registered on the model - Read source — reads the source language column (e.g.
title_fr) - Check targets — skips target columns that already have content (unless
overwrite=True) - Decide the mode — is this field rich text? (
HTML_FIELDS, field class, then content) - Group — one group per target language and mode, so one request carries as much as the provider allows
- Fit — plain text is chunked on natural boundaries; a rich-text document is planned instead of cut: structural markup is set aside and only the prose inside each block — a heading, a list item, a table cell — becomes a request, so every request fits the budget whatever the document's shape
- Translate — calls the backend's
translate_raw()once per request - Reassemble — answers are checked before they are trusted, pieces are glued back, markup restored, whitespace preserved
- Write back — measures the column, then saves with
update_fields
Steps 6 and 8 are the whole point of the split between translate_batch() and
translate_raw(): a backend author never writes them.
Pluggable backends¶
A backend implements one method and declares three limits:
class MyBackend(BaseBackend):
max_chars = 5000
max_texts = 20
supports_html = False
def translate_raw(self, texts, source, target, is_html=False) -> list[str]: ...
This design means:
- Batch efficiency — as few requests as the provider allows, not one per field
- Easy to extend — one method to add a new translation service
- Testable — swap in a fake backend, and assert on what it received
Modules¶
| Module | Responsibility |
|---|---|
translator |
what to translate, and writing it back safely |
conf |
reading and validating the TRADUIRE settings |
chunking |
cutting long text on natural boundaries, losslessly |
htmltokens |
reading a document as tokens and writing it back byte for byte |
richtext |
planning a document: what is structure, what is prose to send |
backends.base |
request budgeting, grouping, and the two rich-text strategies |
backends.* |
one provider each: build a request, read an answer |
exceptions |
TraduireError, ConfigurationError, BackendError |
Settings resolution¶
| Setting | Default | Fallback |
|---|---|---|
SOURCE_LANGUAGE |
None |
LANGUAGE_CODE (stripped of region) |
TARGET_LANGUAGES |
None |
All LANGUAGES except source |
BACKEND |
google_free.GoogleFreeBackend |
— |
AUTO_TRANSLATE |
False |
— |
HTML_MODE |
"auto" |
— |
MAX_CHARS |
None |
the backend's max_chars |
ON_TOO_LONG |
"truncate" |
— |
FAIL_SILENTLY |
True |
— |