# Manejo multilingüe en Django: Evitar que "Polish" se convierta en "polaco" (Marcadores contextuales)
Cuando se implementa el soporte multilingüe (i18n) de manera adecuada, es común encontrarse con situaciones como:
* Un botón con **“Polish”** (refinar la UI) se traduce como **“polaco”**
* El componente de selección de fechas muestra **“May”** que se traduce como un nombre propio en algunos idiomas
* El menú presenta **“Book”** solo como “libro”, sin la opción de “reservar”
La causa es sencilla:
> Las computadoras no comprenden el *contexto*. Si dos cadenas son idénticas, se tratan como la misma.
En este artículo, utilizaremos los **Marcadores contextuales** de Django para mantener el código fuente intacto y asignar traducciones distintas a la misma cadena.
---
## ¿Por qué ocurre esto? Funcionamiento básico de gettext {#sec-aff43a618865}
El sistema de traducción de Django se basa en **GNU gettext**. Su lógica es muy simple:
* Texto original → `msgid`
* Texto traducido → `msgstr`
* Si `msgid` es idéntico, siempre se usa el mismo `msgstr`
```po
# django.po
msgid "Polish"
msgstr "polaco"
```
Una vez que se crea esta asociación, cualquier aparición de “Polish” en el proyecto usará la misma traducción. Por eso, los dos usos de “Polish” (verbo y nombre de idioma) no se distinguen.
Para evitarlo, algunos desarrolladores modifican el código fuente:
```html
{% trans "Polish (verb)" %}
{% trans "Polish (language)" %}
```
Aunque la traducción sea correcta, el texto visible para el usuario se vuelve extraño y la reutilización se complica.
Lo que buscamos es:
* Mantener la cadena original `"Polish"`
* Añadir una explicación de su significado en el contexto
Los **Marcadores contextuales** son la solución.
---
## Solución en plantillas: `{% translate %}` + `context` {#sec-e28151952ba2}
En las plantillas de Django, el tag `{% translate %}` (o su versión antigua `{% trans %}`) acepta la opción `context` para diferenciar la misma cadena según su uso.
### 1) Código original (colisión) {#sec-40afc992a96b}
```html
{% load i18n %}
{% translate "Polish" %}
```
En el archivo `.po`, ambas líneas comparten `msgid "Polish"`, por lo que solo se puede traducir una vez.
### 2) Código mejorado (con contexto) {#sec-4fa05f04b9d3}
```html
{% load i18n %}
{% translate "Polish" context "language name" %}
```
Puntos clave:
* El texto después de `context` no se muestra al usuario.
* Es información meta para el sistema de traducción y los traductores.
* Se recomienda usar descripciones breves y claras.
### 3) También funciona con `{% blocktranslate %}` {#sec-c2a9f27dea01}
Para frases largas, se puede usar `{% blocktranslate %}` con `context`.
```html
{% load i18n %}
{% blocktranslate context "greeting message" with username=user.username %}
Hello {{ username }}
{% endblocktranslate %}
```
Esto permite reutilizar la misma frase con diferentes contextos.
---
## Solución en código Python: `pgettext` {#sec-3a9a008d3f99}
En vistas, modelos, formularios y demás código Python, se utilizan las funciones de la familia `pgettext`.
* `pgettext(context, message)`
* `pgettext_lazy(context, message)` – evaluación diferida
* `npgettext(context, singular, plural, number)` – plural + contexto
### 1) Ejemplo básico {#sec-27f89a09cea2}
```python
from django.utils.translation import pgettext
def my_view(request):
# 1. Mes "May"
month = pgettext("month name", "May")
# 2. Nombre propio "May"
person = pgettext("person name", "May")
# 3. Verbo modal "may"
verb = pgettext("auxiliary verb", "may")
```
Aunque el `msgid` sea el mismo, el `context` permite distintas traducciones.
### 2) Uso de `pgettext_lazy` en modelos {#sec-11832a96275e}
```python
from django.db import models
from django.utils.translation import pgettext_lazy
class Order(models.Model):
type = models.CharField(
verbose_name=pgettext_lazy("order model field", "Order type"),
max_length=20,
)
STATUS_CHOICES = [
("open", pgettext_lazy("order status", "Open")),
("opened", pgettext_lazy("log action", "Open")),
]
status = models.CharField(
max_length=20,
choices=STATUS_CHOICES,
)
```
### 3) Manejo de plurales con `npgettext` {#sec-ed84f3cf8d15}
```python
from django.utils.translation import npgettext
def get_notification(count):
return npgettext(
"user notification",
"You have %(count)d message",
"You have %(count)d messages",
count
) % {"count": count}
```
---
## ¿Cómo se ve en el archivo `.po`? {#sec-fb610023c81a}
Después de usar `context`, el comando de extracción añade `msgctxt`.
```bash
python manage.py makemessages -l ko
```
El archivo `.po` resultante:
```po
# django.po
# 1) "Polish" = verbo de refinar la UI
msgctxt "verb: to refine UI"
msgid "Polish"
msgstr "refinar"
# 2) "Polish" = idioma
msgctxt "language name"
msgid "Polish"
msgstr "polaco"
```
Aunque `msgid` sea idéntico, el `msgctxt` diferencia las entradas, lo que facilita la traducción y la gestión.
---
## Consejos para crear buenos contextos {#sec-df37b35ab408}
El contexto no se muestra al usuario, pero es la pista más valiosa para el traductor.
### 1) Describir el *rol* en la UI {#sec-9dfe29490c86}
* `"button label"`
* `"menu item"`
* `"tooltip"`
* `"error message"`
* `"form field label"`
### 2) Añadir el *concepto* cuando sea necesario {#sec-135dce4b280b}
* `"File"` → `"file menu item"`, `"uploaded file object"`
* `"Order"` → `"e-commerce order"`, `"sorting order"`
### 3) No incluir la traducción en el contexto {#sec-9197b1a38f27}
El contexto debe ser breve y en el idioma original (usualmente inglés).
---
## Cuándo usar marcadores contextuales {#sec-58e84d2a2b4c}
Considera usar `context`/`pgettext` cuando:
1. La cadena es corta (1–2 palabras) y aparece en varios lugares.
2. Se reutiliza con significados distintos (ej. "Open", "Book").
3. Los traductores no tienen acceso a la pantalla.
---
## Resumen {#sec-8cc5759d0812}

* Django asigna una única traducción a cada `msgid`.
* Los homónimos como "Polish", "May", "Book" suelen causar conflictos.
* No cambies la cadena original; usa `{% translate "…" context "…" %}` en plantillas y `pgettext`/`pgettext_lazy`/`npgettext` en Python.
* Así, el archivo `.po` tendrá `msgctxt`, permitiendo distintas traducciones y mejorando la calidad y mantenibilidad.
En la era del soporte multilingüe, los marcadores contextuales son una herramienta esencial para los desarrolladores de Django.
---
**Artículos relacionados**
- [Django: Diferencia entre gettext y gettext_lazy](/whitedec/2026/1/5/django-gettext-vs-gettext-lazy/)
- [Problemas al usar gettext_lazy como clave JSON y cómo solucionarlos](/whitedec/2025/4/26/gettext-lazy-json-key-problem-solution/)