Escollos¶
Este sitio está traducido a treinta y cinco idiomas, y todos ellos se produjeron ejecutando el ciclo que enseña esta documentación. Es un corpus pequeño para los estándares del sector y aun así bastó para caer en casi todas las trampas que hacen que la i18n sea más difícil de lo que parece.
Cada sección de abajo es algo que salió mal aquí de verdad, qué aspecto tenía en su momento y dónde está la línea entre lo que la biblioteca comprueba por ti y lo que sigue siendo criterio tuyo.
Renombrar una variable retraduce una frase¶
El msgid es la clave del catálogo, y un nombre interpolado está dentro de
ella. Mover una constante al ámbito de módulo y ponerla en mayúsculas como pide
el estilo de Python —de author a AUTHOR— convirtió
Copyright © 2026 {author} · MIT License en un mensaje que ningún catálogo
había visto nunca. Todas las traducciones de esa línea habrían vuelto a pasar
por el ciclo fuzzy, en todos los idiomas, por un renombrado que no cambiaba
nada que un lector pudiera ver.
La biblioteca no te lo impedirá: ambas grafías son nombres de marcador válidos. Lo que sí hace es que el nombre merezca protegerse: una interpolación tiene que ser un nombre simple, así que lo que queda en la clave del catálogo es una palabra que un traductor puede leer, no una expresión.
El caso simétrico es seguro por construcción. Las conversiones y los
especificadores de formato no forman parte del msgid, así que ajustar
{amount:,.2f} a {amount:,.0f} no cambia ninguna clave ni invalida ninguna
traducción en ningún idioma.
nplurals=2 no significa dos cadenas distintas¶
El turco, el húngaro, el persa y el bengalí declaran los cuatro dos formas
plurales, y en los cuatro las dos formas de un mensaje con cantidad son
legítimamente la misma cadena: el sustantivo permanece en singular tras un
numeral, así que {n} sayfa vale igual para una página que para diez. Quien
revise el texto y «corrija» esa duplicación rompe la traducción.
El error contrario es igual de fácil. La tercera forma del letón existe solo
para el cero; la segunda del esloveno es un dual, para exactamente dos;
la última del rumano exige la palabra de que las dos primeras no pueden
llevar. Rellenar esos huecos con un singular y un plural produce un catálogo
que es incorrecto solo para las cantidades que nadie prueba.
Peor aún: el orden de los huecos no es semántico. El galés indexa sus cinco
formas de modo que msgstr[0] es el caso general y msgstr[1] es el singular.
Rellenarlas en la secuencia obvia coloca el singular justo donde lo encontrará
todo mensaje sin cantidad.
La biblioteca no asume nada de esto, y esa es precisamente la idea: la regla de plural del idioma de destino vive en la cabecera de su propio catálogo, y la regla de unión/intersección permite que una traducción tenga más formas, o menos, que el origen. Lo que sí comprueba es lo único que puede comprobarse sin conocer el idioma: que cada forma conserve los marcadores que necesita.
Dos formas pueden ser idénticas por un motivo¶
El irlandés tiene cinco formas plurales y, en el informe de compilación de este
sitio, varias se escriben igual. No es un desliz de copiar y pegar:
leathanach empieza por l, y ninguna de las dos mutaciones iniciales que
provocan los numerales irlandeses se escribe sobre la l. Las formas siguen
haciendo un trabajo real —la raíz alterna entre leathanach y leathanaigh, y
las cantidades superiores a diez vuelven al singular—, pero ningún sustantivo
que signifique «página» mostraría el contraste.
Cualquier comprobación que marque como sospechosas las formas duplicadas marcará irlandés correcto. Aquí el único revisor posible es una persona que conozca el idioma.
Un mensaje solo puede concordar con una cantidad¶
El informe de compilación de este sitio dice cuántas páginas se renderizaron y
cuánto tardó. Escribirlo como «Renderizadas {n} páginas en {seconds} segundos»
parece inofensivo y no es traducible: gettext selecciona una forma a partir de
una cantidad, y esa cantidad es n. La palabra segundos tendría que
concordar con un número que el mecanismo de plurales nunca llega a ver.
La solución es que la segunda magnitud sea un símbolo de unidad en lugar de una
palabra, y los símbolos de unidad también se localizan: los catálogos de este
sitio llevan s, с, ث, שנ׳ y mp, y la tipografía francesa, española y
sueca quiere un espacio antes del símbolo donde el inglés no lo pone. Nada de
eso es asunto de la biblioteca; pero darse cuenta de que un mensaje necesita
dos concordancias sí lo es, y la única herramienta para ello es escribir el
mensaje de otra manera.
Editar una frase en inglés edita gramática ajena¶
La página de inicio decía «all ten language editions». Quitar el número —una edición de una sola palabra en inglés, hecha porque el número se quedaba obsoleto una y otra vez— convirtió un sujeto plural en singular. El español, el italiano, el portugués, el ruso, el ucraniano, el griego, el neerlandés y el hebreo tuvieron todos que volver a concordar el verbo; varios necesitaron cambiar también el participio.
Una edición del origen que en inglés parece trivial no lo es aguas abajo.
Marcarla como fuzzy, que es lo que hace pybabel update, es el mecanismo que
da a cada traductor la oportunidad de darse cuenta.
Las diferencias invisibles sobreviven a cualquier copiar y pegar¶
La guía cita un diagnóstico que contiene (nаme) —un escape deliberado, porque
el carácter que nombra es una а cirílica que ningún lector distingue de la
latina—. Quienes tradujeron este sitio convirtieron ese escape en el carácter
real cinco veces distintas, en cinco idiomas diferentes, y cada una de ellas
produjo una página que parecía correcta y estaba mal.
Esto sí lo detecta la biblioteca, y es la razón de que los diagnósticos tengan la forma que tienen: un marcador cuyas letras mezclan sistemas de escritura se informa dos veces, una de forma legible y otra escapada, porque la forma escapada es la única grafía que las distingue. Un espacio de no separación dentro de las llaves se imprime por punto de código por la misma razón. El comprobador de catálogos rechaza el mensaje antes de que pueda publicarse.
No vacío no es traducido¶
Un catálogo generado con sus msgids copiados en los msgstr pasa todas las comprobaciones ingenuas: nada está vacío, nada es fuzzy, el conjunto de mensajes coincide exactamente. Una edición de este sitio se publicó así durante varias horas. Y también ocho páginas de otra edición que eran copias byte a byte del origen en inglés, cosa que supera una comprobación que compare los bloques de código entre ambas, porque son el mismo archivo.
Ninguna de las dos cosas puede verlas una biblioteca de traducción. Ambas son
baratas de comprobar, pero no exigiendo que cada entrada difiera de su origen:
OK, los nombres de producto, los nombres propios, las siglas y los
identificadores de código se traducen a sí mismos, y una comprobación que lo
prohíba producirá falsos positivos para siempre.
Mide en cambio la proporción, sobre un catálogo entero o una página entera, y envía los valores atípicos a una persona. La propia prueba de este sitio hace exactamente eso: compara las líneas de prosa de cada edición con el origen en inglés y falla por encima del 25 % de líneas idénticas. La edición falsificada estaba en el 87 %; toda traducción genuina se sitúa entre el 4 % y el 8 %, que es la pequeña cola de líneas que coinciden legítimamente, como las URL y la salida citada de programas. Las dos poblaciones están lo bastante separadas como para que el umbral no necesite ser preciso.
El catálogo no es lo único traducido¶
Dos de los fallos de aquí no tuvieron nada que ver con gettext.
Traducir un encabezado cambia el ancla que se genera a partir de él, así que todos los enlaces entre páginas que apuntan a esa sección se rompen —en silencio y solo en ese idioma—. Este sitio fija el ancla inglesa en todos los encabezados, y una prueba deriva la lista esperada de la página en inglés.
Y el generador del sitio incluye traducciones de interfaz para sesenta y ocho idiomas, entre los que no están ni el suajili ni el irlandés. Sin ellas la compilación no degrada a inglés: el include de la plantilla falla y la edición no puede construirse en absoluto. Dos archivos propios de este repositorio existen para llenar ese hueco.
Tus herramientas también tienen errores¶
El paso de CI que recomienda esta documentación para detectar catálogos
obsoletos, pybabel update --check, no puede hacer ese trabajo en ningún
proyecto que use pgettext o npgettext. En Babel 2.18.0 informa de que todos
los catálogos con un msgctxt están desactualizados, en cada ejecución. La
comparación pasa por Catalog.is_identical, que busca cada mensaje por la clave
con la que está almacenado, y para un mensaje con contexto esa clave es el par
(id, context), que Catalog.get no acepta. La búsqueda no devuelve nada y los
catálogos nunca resultan iguales:
>>> from babel.messages.catalog import Catalog
>>> c = Catalog(locale="ja")
>>> c.add("Guide", "ガイド", context="navigation")
<Message 'Guide' (flags: [])>
>>> c.is_identical(c)
False
Se descubrió aquí al intentar usarlo, se comunicó aguas arriba, y la comprobación de repuesto está en la página de producción.
La lección general es la incómoda: una puerta que siempre está en rojo es peor que no tener puerta, porque el equipo acaba desactivándola. Verifica que tu comprobación de CI puede pasar de verdad antes de confiar en que falle.
Para qué sirve la biblioteca, en una línea¶
Casi toda esta página es criterio que ninguna herramienta puede asumir por ti. Lo que una herramienta sí puede hacer es garantizar que una traducción no pueda cambiar la estructura de la frase que traduce —no pueda eliminar un valor, inventarse uno, reformatearlo ni acceder a tus objetos— y decirlo en una frase sobre la que pueda actuar quien tenga que arreglarlo. Eso es todo lo que promete esta biblioteca, y el resto de este sitio es cómo lo cumple.