Skip to content

Model Translation

TranslateBot Django integrates with django-modeltranslation to automatically translate database content.

Overview

django-modeltranslation adds language-specific fields to your models. For example, a title field becomes title_en, title_de, title_nl, etc. TranslateBot can automatically populate these translated fields.

Installation

1. Install with modeltranslation support

pip install translatebot-django[modeltranslation]
poetry add translatebot-django[modeltranslation]
uv add translatebot-django[modeltranslation]

2. Configure Django

settings.py
INSTALLED_APPS = [
    "modeltranslation",  # Must be before django.contrib.admin
    "django.contrib.admin",
    # ...
    "translatebot_django",
]

LANGUAGES = [
    ("en", "English"),
    ("de", "German"),
    ("nl", "Dutch"),
]

3. Register Models for Translation

Create a translation.py file in your app:

myapp/translation.py
from modeltranslation.translator import register, TranslationOptions
from .models import Article, Product


@register(Article)
class ArticleTranslationOptions(TranslationOptions):
    fields = ("title", "content", "description")


@register(Product)
class ProductTranslationOptions(TranslationOptions):
    fields = ("name", "description")

4. Run Migrations

python manage.py makemigrations
python manage.py migrate

This creates the language-specific database columns.

Usage

Translate All Models

python manage.py translate --target-lang nl --models

Translate Specific Models

python manage.py translate --target-lang nl --models Article Product

Preview Mode

python manage.py translate --target-lang nl --models --dry-run

Re-translate Existing Content

python manage.py translate --target-lang nl --models --overwrite

How It Works

  1. Discovers all models registered with django-modeltranslation
  2. Finds fields that need translation (empty target language fields)
  3. Reads content from the source language field
  4. Translates using the configured AI model, in batches
  5. Updates the database using efficient bulk operations, saving each batch as soon as it is translated (one transaction per model)

FileField and ImageField fields are skipped: their columns hold file paths, not text. A translated SlugField is turned back into a valid slug (respecting allow_unicode) and shortened to the field's max_length at a word boundary.

Example

Model Definition

models.py
from django.db import models


class Article(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    published = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.title

Translation Registration

translation.py
from modeltranslation.translator import register, TranslationOptions
from .models import Article


@register(Article)
class ArticleTranslationOptions(TranslationOptions):
    fields = ("title", "content")

Database Schema

After migrations, your database has:

Column Type
title CharField
title_en CharField
title_de CharField
title_nl CharField
content TextField
content_en TextField
content_de TextField
content_nl TextField

Translation Command

python manage.py translate --target-lang de --models Article

Output:

🔍 Gathering translatable model fields...
â„šī¸  Found 50 model fields to translate
  â€ĸ Article: 50 field(s)
🔄 Translating model fields with gpt-6-luna (2 batches)...
✓ Article.title: 'Getting started' → 'Erste Schritte'
...
  💾 Saved batch 1/2
...
  💾 Saved batch 2/2

============================================================
✨ Successfully translated 50 model field(s)

Source Language Detection

For each record, TranslateBot picks the source text in this order:

  1. The default language field (title_en when MODELTRANSLATION_DEFAULT_LANGUAGE is en)
  2. The base field (title), if the default language field is empty. This covers rows created before modeltranslation was installed, or written with queryset.update(). The default language field is filled with this value when the translation is saved, like modeltranslation's update_translation_fields command does.
  3. The first other populated language field (title_de, etc.)
  4. Records with no source content are skipped

This ensures translations work even when content was entered through language-specific fields.

Per-app TRANSLATING.md files only apply to .po files. Model field translation uses the project-level TRANSLATING.md only.

Combining with PO Translation

You can translate both PO files and model fields in separate commands:

# Translate PO files
python manage.py translate --target-lang nl

# Translate model fields
python manage.py translate --target-lang nl --models

Or translate everything at once by running both:

python manage.py translate --target-lang nl && \
python manage.py translate --target-lang nl --models

Best Practices

Use Dry Run

Always preview with --dry-run before modifying your database.

Backup Your Database

Create a database backup before bulk translations.

Translate in Batches

For large datasets, consider translating specific models at a time.

Saved per batch

Each batch is saved as soon as it is translated, in one transaction per model. If an error occurs, everything saved before it stays saved; rerunning the command translates only the fields that are still empty. With --overwrite, a rerun starts over from the first batch.

Next Steps