Traducir un proyecto Django suele ser así: makemessages, abrir cada .po, copiar los msgid en un traductor o en ChatGPT, pegar los msgstr uno a uno, rezar para que no se rompa ningún %(name)s y correr compilemessages. Y repetirlo con cada texto nuevo.
En esta guía lo hacemos con un solo comando, python manage.py translate, usando el paquete translate-projects-django. Todo lo que ves abajo (terminal y archivos .po) es la salida real de una ejecución en un proyecto de prueba.
Qué necesitas
- Python 3.8 o superior y Django 3.2 o superior.
- GNU gettext (
xgettextymsgfmt), igual que para cualquier traducción en Django:sudo apt-get install gettextobrew install gettext. - Una cuenta gratis de Translate Projects con un proyecto y su API token (Primeros pasos).
- La API key de tu proveedor de IA (Claude, OpenAI, DeepSeek o Gemini). No hay planes ni tarjeta: pagas solo los tokens que uses a tu proveedor.
1. Instala el paquete
pip install translate-projects-django
2. Configura settings.py
import os
INSTALLED_APPS = [
# ...
"translate_projects_django",
]
MIDDLEWARE = [
# ...
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.locale.LocaleMiddleware",
"django.middleware.common.CommonMiddleware",
# ...
]
USE_I18N = True
LANGUAGE_CODE = "es" # idioma base
LANGUAGES = [
("es", "Español"),
("en", "English"),
("pt-br", "Português (Brasil)"),
("fr", "Français"),
]
LOCALE_PATHS = [BASE_DIR / "locale"]
TRANSLATE_PROJECTS_API_KEY = os.environ.get("TRANSLATE_PROJECTS_API_KEY")
Los códigos de Django (pt-br, zh-hans) se convierten solos a los de la API. LANGUAGE_CODE es tu idioma base y nunca se traduce.
3. Marca tus textos como siempre
No cambia nada de lo que ya haces en Django: gettext en Python y {% translate %} en las plantillas.
# views.py (ejemplo)
from django.utils.translation import gettext as _
def home(request):
message = _("Cerrar sesión")
{# templates/home.html (ejemplo) #}
{% load i18n %}
<h1>{% translate "Bienvenido a tu panel" %}</h1>
<p>{% blocktranslate %}Hola {{ name }}, tienes mensajes nuevos{% endblocktranslate %}</p>
4. Traduce
export TRANSLATE_PROJECTS_API_KEY=tu_token
python manage.py translate
Salida real (6 textos a inglés, portugués y francés):
[05:19:47 PM] 🎯 Start Generate Translations
📂 6 texts found in es
[05:19:48 PM] ✅ Sources unchanged, upload skipped
📝 Translating (en) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 0:00:00
📝 Translating (pt-br) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 0:00:00
📝 Translating (fr) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 0:00:00
[05:19:50 PM] ⏱ extract 0.0s · upload 0.4s · compile 0.0s · total 2.5s · 7 HTTP requests
en: 6 filled, 0 missing, 0 rejected · translate 1.4s · download 0.4s ·
write 0.0s
pt-br: 6 filled, 0 missing, 0 rejected · translate 1.6s · download 0.1s ·
fr: 6 filled, 0 missing, 0 rejected · translate 1.8s · download 0.3s ·
🎉 Translations completed ✅
Dos segundos y medio en total. El comando ejecuta makemessages, traduce hasta 3 idiomas en paralelo, escribe los .po y termina con compilemessages. Así queda el francés:
# locale/fr/LC_MESSAGES/django.po
#: demo/templates/demo.html:2
msgid "Bienvenido a tu panel"
msgstr "Bienvenue sur votre tableau de bord"
#: demo/templates/demo.html:3
#, python-format
msgid "Hola %(name)s, tienes mensajes nuevos"
msgstr "Bonjour %(name)s, vous avez de nouveaux messages"
#: demo/templates/demo.html:4
msgid "<b>Guardar</b> cambios"
msgstr "<b>Enregistrer</b> les modifications"
#: demo/templates/demo.html:5
#, python-format
msgid "100 %% gratis"
msgstr "100 %% gratuit"
#: demo/views.py:3
msgid "Cerrar sesión"
msgstr "Se déconnecter"
#: demo/views.py:3
msgid "Configuración de la cuenta"
msgstr "Paramètres du compte"
Archivos que genera
locale/
├── en/LC_MESSAGES/django.po ← y su django.mo
├── pt_BR/LC_MESSAGES/django.po
├── fr/LC_MESSAGES/django.po
└── .translate-projects.json ← caché
Haz commit de los .po y de .translate-projects.json para que otras máquinas y tu CI salten los idiomas que ya están al día.
Comandos útiles
python manage.py translate --locale en # solo un idioma
python manage.py translate --force # descarga todo otra vez
- Una segunda ejecución sin textos nuevos hace una sola petición y salta los idiomas completos: lo ya traducido no gasta tokens.
- No edites los
.poa mano: se reconstruyen en cada ejecución. Edita la traducción en el panel y corre con--force. - Limitación actual: los plurales (
ngettext,blocktranslate count) todavía no se traducen y quedan en el idioma base.
Errores comunes
- TRANSLATE_PROJECTS_API_KEY is not set in settings.py: exporta la variable y léela en
settings.py. - El idioma de origen no es el predeterminado:
LANGUAGE_CODEdebe ser el idioma por defecto del proyecto. - MISSING_API_KEY: configura proveedor, modelo y key de IA en el proyecto.
- CommandError: Can't find msguniq o xgettext: falta GNU gettext.
La guía completa está en doc.translateprojects.dev. Crea tu proyecto gratis y traduce tu proyecto Django hoy.