# General Translation Knowledge Base: General Translation frente a GNU gettext: ¿necesitas ambos?
URL: https://generaltranslation.com/es/kb/general-translation-vs-gettext.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: Conserva GNU gettext para la extracción y el renderizado, y añade General Translation para generar y mantener los archivos PO. General Translation incorpora las notas para traductores y el contexto de los mensajes en la generación, aplica una terminología compartida y ofrece a los revisores un editor en el panel de control. Tus llamadas actuales a gettext y tus catálogos compilados siguen como están.
Category: Internacionalización
Last updated: 2026-10-16
Authors: Kevin Wu, Jackie Chen
Published: 2026-10-16

GNU gettext es el conjunto de herramientas en el que todavía se apoya la mayor parte de la traducción de software. Envuelves las cadenas visibles para el usuario en `_()` o `gettext()`, `xgettext` las extrae a una plantilla POT, `msginit` crea un archivo PO para cada idioma, `msgmerge` actualiza esos archivos cuando cambia el origen y `msgfmt` los compila en los archivos `.mo` que tu programa carga en tiempo de ejecución. Los programas en C, la extensión gettext de PHP, el módulo `gettext` de Python, WordPress, Django y Babel usan este formato. Lo que gettext deja en tus manos es casi toda la traducción: desde la versión 1.0 puede generar borradores de entradas con un LLM local, pero cada `msgstr` de cada archivo PO lo terminas tú, tus traductores o un servicio. General Translation no reemplaza ninguna parte de este conjunto de herramientas; su CLI escribe esos archivos PO a partir de tu plantilla, así que el resto de tu configuración de gettext se queda como está.

## Lo que gettext hace bien

* **El texto de origen es la clave.** En el código se escribe `_("Inbox")`, no un nombre de clave, y una cadena sin traducción [recurre al texto de origen](https://www.gnu.org/software/gettext/manual/html_node/Interface-to-gettext.html) en lugar de producir un error.
* **Reglas de plural por idioma.** Cada archivo PO incluye una [cabecera `Plural-Forms` con la regla del idioma](https://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html), y `msginit` la rellena por ti. El polaco tiene una regla de tres formas y tres huecos `msgstr[n]` en cada entrada en plural.
* **El contexto viaja con la cadena.** `msgctxt` (de `pgettext`) [distingue «Archive» como verbo de «Archive» como sustantivo](https://www.gnu.org/software/gettext/manual/html_node/Contexts.html), los comentarios `#.` transmiten notas a los traductores (`xgettext --add-comments`), las líneas `#:` apuntan al origen y opciones como `python-format` permiten que `msgfmt --check` rechace una traducción que rompa un marcador de posición.
* **Actualizaciones seguras.** `msgmerge` [conserva las traducciones existentes cuando cambia la plantilla](https://www.gnu.org/software/gettext/manual/html_node/msgmerge-Invocation.html) y marca como fuzzy las entradas cuyo origen ha cambiado, y guarda el origen anterior para poder compararlo (`--previous`).
* **Borradores con un LLM local.** Desde la versión 1.0, [`msgpre` y `spit` pretraducen archivos PO](https://www.gnu.org/software/gettext/manual/html_node/Pretranslating.html) con un LLM instalado localmente a través de ollama, como punto de partida que luego revisa un traductor.
* **Compatibilidad universal.** PO es el formato que leen y escriben editores de PO como Poedit y la mayoría de los sistemas de gestión de traducciones (TMS), y las herramientas son [software libre](https://www.gnu.org/software/gettext/manual/html_node/Licenses.html) (GPL, con la biblioteca de tiempo de ejecución bajo LGPL).

## Lo que gettext deja en tus manos

Este es un pequeño script de Python que usa el módulo `gettext` de la biblioteca estándar:

```python title="inbox.py"
import gettext, sys

lang = sys.argv[1]
count = int(sys.argv[2])
t = gettext.translation("inbox", localedir="locale", languages=[lang], fallback=True)
_ = t.gettext

# TRANSLATORS: encabezado de la página de la bandeja de entrada
print(_("Inbox"))
print(t.ngettext("You have %d unread message.", "You have %d unread messages.", count) % count)
print(t.pgettext("email verb", "Archive"))
```

El flujo de trabajo de gettext, con [GNU gettext 1.0](https://lists.gnu.org/archive/html/info-gnu/2026-01/msg00007.html):

```bash
xgettext --language=Python --keyword=pgettext:1c,2 --add-comments=TRANSLATORS -o po/inbox.pot inbox.py
msginit --no-translator --locale=pl_PL.UTF-8 -i po/inbox.pot -o po/pl.po
# alguien rellena todos los msgstr de po/pl.po
msgfmt --check -o locale/pl/LC_MESSAGES/inbox.mo po/pl.po
```

Una vez completado el archivo en polaco, `python3 inbox.py pl 5` imprime &quot;Masz 5 nieprzeczytanych wiadomości.&quot;. Luego alguien cambia &quot;unread message&quot; por &quot;new message&quot; en el código. `xgettext` y `msgmerge --update --previous` arrastran la traducción polaca anterior y la marcan como fuzzy, porque ahora traduce un texto distinto:

```text title="po/pl.po"
#: inbox.py:10
#, fuzzy, python-format
#| msgid "You have %d unread message."
#| msgid_plural "You have %d unread messages."
msgid "You have %d new message."
msgid_plural "You have %d new messages."
msgstr[0] "Masz %d nieprzeczytaną wiadomość."
msgstr[1] "Masz %d nieprzeczytane wiadomości."
msgstr[2] "Masz %d nieprzeczytanych wiadomości."
```

`msgfmt` [omite las entradas fuzzy](https://www.gnu.org/software/gettext/manual/html_node/msgfmt-Invocation.html) (indica &quot;2 translated messages, 1 fuzzy translation&quot;), así que el mismo comando ahora muestra &quot;You have 5 new messages.&quot; en inglés, en medio de una pantalla en polaco. La traducción antigua al polaco sigue diciendo &quot;unread&quot;, por lo que hay que actualizarla. General Translation puede generar esa actualización a partir de la nueva plantilla como parte de tu compilación.

## Traducir catálogos de gettext con General Translation

La CLI de General Translation lee tu plantilla POT, traduce cada entrada y genera un archivo PO para cada idioma de destino. Configura `gt.config.json` para que apunte a la plantilla e indica dónde debe guardarse el archivo de cada idioma. Esta configuración se verificó con `gt` 2.26.5:

```json title="gt.config.json"
{
  "defaultLocale": "en",
  "locales": ["de", "pl", "pt_BR"],
  "customMapping": {
    "pt_BR": { "code": "pt-BR" }
  },
  "files": {
    "pot": {
      "include": ["po/inbox.pot"],
      "transform": {
        "match": "^po/inbox\\.pot$",
        "replace": "po/{locale}.po"
      },
      "transformationFormat": "PO"
    }
  }
}
```

* **`pot` lee archivos PO y POT**, y `"transformationFormat": "PO"` hace que la salida sean archivos `.po` traducidos. (Consulta la [referencia del formato PO / POT](/docs/cli/reference/formats/po-pot-files)).
* **`transform` define el nombre de la salida.** `{locale}` es la configuración regional tal cual aparece en `locales`, así que obtienes `po/pl.po` y `po/pt_BR.po`. (Consulta [`transform`](/docs/cli/reference/config#files)).
* **Conserva los nombres de configuración regional de gettext.** [`customMapping`](/docs/cli/reference/config#custom-mapping) vincula `pt_BR` con el código de configuración regional estándar `pt-BR`. El mismo patrón sirve para otras estructuras, como `languages/my-plugin.pot` y `languages/my-plugin-de_DE.po` en un plugin de WordPress.

Con la CLI configurada (consulta el [Inicio rápido de la CLI](/docs/cli/quickstart)), el flujo de trabajo queda así:

```bash
xgettext --language=Python --keyword=pgettext:1c,2 --add-comments=TRANSLATORS -o po/inbox.pot inbox.py
msgconv --to-code=UTF-8 -o po/inbox.pot po/inbox.pot
npx gt translate
msgfmt --check -o locale/pl/LC_MESSAGES/inbox.mo po/pl.po
```

`xgettext` deja `charset=CHARSET` como marcador de posición en la cabecera de la plantilla, y `msgconv` lo establece en UTF-8, igual que haría `msginit` con un archivo de idioma. [`npx gt translate`](/docs/cli/reference/commands/translate) envía cada entrada acompañada, como contexto, de todo lo que el archivo PO sabe sobre ella: el `msgctxt`, los comentarios para traductores `#.`, las referencias `#:` y las opciones de formato. En las entradas plurales, General Translation escribe la cabecera `Plural-Forms` del idioma de destino, rellena todas las posiciones `msgstr[n]` que exige la cabecera (tres para el polaco, seis para el árabe) y comprueba que los marcadores de posición como `%d` se mantengan intactos.

Cuando cambia un `msgid`, General Translation genera una traducción del nuevo texto en la siguiente ejecución; las entradas sin cambios reutilizan sus traducciones anteriores. Importa las traducciones PO existentes con [`npx gt upload`](/docs/cli/reference/commands/upload) antes de tu primera ejecución de generación. Si después haces cambios en un editor PO local, [`npx gt save-local`](/docs/cli/reference/commands/save-local) los guarda en la plataforma antes de que vuelvas a generar.

Más allá de rellenar `msgstr`, lo que aporta General Translation es el resto de la plataforma. Un glosario y prompts personalizados en un [grupo de contexto](/docs/platform/dashboard/guides/defining-context-for-translations) mantienen la coherencia de términos y tono en tus archivos PO y en cualquier otra superficie que traduzcas; los revisores pueden [revisar y editar](/docs/platform/dashboard/guides/reviewing-translations) cada entrada PO, con las formas plurales del idioma de destino, en el panel de control; y la CLI se ejecuta en CI para que cada lanzamiento salga con catálogos actualizados.

Ejecuta la CLI de Node.js en tu compilación y luego compila su salida PO con `msgfmt`. Tu aplicación sigue cargando las traducciones compiladas de forma local.

## GNU gettext frente a General Translation: comparativa rápida

| Característica                                      | GNU gettext                                                                                | General Translation                                                                    |
| --------------------------------------------------- | ------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------- |
| Extrae cadenas del código                           | Sí, `xgettext`                                                                             | Lee tu plantilla POT existente                                                         |
| Crea un archivo por idioma                          | Sí, `msginit`                                                                              | Sí, a partir de la plantilla, para cada configuración regional definida                |
| Escribe traducciones                                | Genera borradores con un LLM local desde la versión 1.0, para que un traductor los termine | Sí, con [`npx gt translate`](/docs/cli/reference/commands/translate)                   |
| Cuando cambia una cadena de origen                  | `msgmerge` la marca como fuzzy hasta que alguien la revise                                 | Se vuelve a traducir en la siguiente ejecución; las entradas sin cambios se reutilizan |
| Formas plurales                                     | `msginit` escribe la cabecera; tú rellenas cada forma                                      | Escribe la cabecera y rellena todas las formas                                         |
| Contexto para la traducción                         | `msgctxt`, comentarios del traductor, referencias, opciones                                | Lo mismo, además del glosario y los prompts personalizados                             |
| Compila y busca traducciones en tiempo de ejecución | Sí, `msgfmt` y el tiempo de ejecución de gettext                                                       | Mantiene tu compilador y tiempo de ejecución de gettext                                            |
| Coste                                               | Software libre                                                                             | [Traducción con pago por uso](https://generaltranslation.com/pricing)                  |

## Cuándo usar cada uno

Usa gettext por sí solo cuando los traductores o un TMS ya rellenan tus archivos PO, cuando una persona debe escribir cada traducción antes de publicarla o cuando tu compilación no puede ejecutar Node.js. Añade General Translation si quieres que todos los archivos PO se traduzcan a todos los idiomas en cuanto cambie la plantilla, con todas las formas plurales completas y una terminología coherente, sin tener que esperar a una ronda de traducción.

No hay nada que migrar: General Translation conserva tus llamadas a `_()`, tu plantilla, tus archivos PO y tu tiempo de ejecución. Sustituye el paso manual entre `msgmerge` y `msgfmt`. (Para configuraciones específicas de cada framework, consulta [General Translation frente al framework de traducción de Django](/kb/general-translation-vs-django-i18n) y [General Translation frente a Babel y Flask-Babel](/kb/general-translation-vs-flask-babel)).

## Conclusiones clave

* GNU gettext extrae, fusiona, compila y busca traducciones, y desde la versión 1.0 puede generar borradores con un LLM local, pero no las completa. Las cadenas nuevas y modificadas aparecen en el idioma de origen hasta que alguien las traduce o las revisa.
* La CLI de General Translation traduce una plantilla POT a un archivo PO por idioma mediante la clave `pot`, `"transformationFormat": "PO"`, un `transform` para la ruta de salida y `customMapping` para nombres como `pt_BR`.
* Para cada entrada plural, General Translation escribe la cabecera `Plural-Forms` del idioma de destino y todas las posiciones `msgstr[n]`, y usa `msgctxt` y los comentarios para traductores como contexto. `msgfmt` y tu tiempo de ejecución de gettext no cambian.

## Related questions

- [General Translation frente al framework de traducción de Django: ¿necesitas ambos?](https://generaltranslation.com/es/kb/general-translation-vs-django-i18n.mdx): Usa el framework de traducción de Django y General Translation de forma conjunta. Django se encarga de la extracción de mensajes, la selección del idioma y el renderizado. General Translation rellena sus archivos PO, incluidas las formas plurales, con la terminología de tu producto y la revisión en el panel de control. Tus plantillas y patrones de URL siguen igual, y las traducciones se actualizan a la par que tu código.
- [General Translation frente a Babel y Flask-Babel: ¿cuál deberías usar?](https://generaltranslation.com/es/kb/general-translation-vs-flask-babel.mdx): Babel da formato a fechas, números y monedas para cualquier configuración regional y gestiona catálogos de gettext, y Flask-Babel lo integra con Flask, pero ninguno de los dos traduce tus cadenas. La CLI de General Translation rellena los archivos PO de Babel para cada idioma, formas plurales incluidas, para que puedas seguir usando Flask-Babel y dejar de traducir catálogos a mano.
- [¿Por qué usar General Translation en lugar de un TMS (Smartling, Lokalise, Phrase, Crowdin o Transifex)?](https://generaltranslation.com/es/kb/general-translation-vs-tms.mdx): Un sistema de gestión de traducciones (TMS) como Smartling, Lokalise, Phrase, Crowdin o Transifex coordina a los traductores, pero los ingenieros siguen teniendo que extraer las cadenas, enviarlas, esperar las traducciones y volver a integrarlas en el producto. General Translation traduce el contenido de tu código junto con su contexto, incluye todos los idiomas en cada lanzamiento y funciona con bibliotecas de código abierto, sin dependencia de proveedor.
- [General Translation vs. Weblate: ¿cuál deberías usar?](https://generaltranslation.com/es/kb/general-translation-vs-weblate.mdx): Weblate es una plataforma de localización autoalojable y basada en Git, pensada para traducir los archivos de un repositorio junto con una comunidad o un equipo. General Translation integra la generación de traducciones en el desarrollo y los lanzamientos mediante JSX marcado y contexto compartido del producto. Conserva tus archivos de gettext o adopta la redacción inline para eliminar también el mantenimiento del catálogo de origen.
- [¿Cuál es el mejor software de localización para desarrolladores?](https://generaltranslation.com/es/kb/best-localization-software.mdx): Busca un único sistema que cubra todo el flujo, desde la biblioteca de i18n en tu código hasta la traducción y la entrega, en lugar de ir uniendo por separado una biblioteca, un sistema de gestión de traducciones y un proveedor de traducción.

## Previous and next questions

- Previous question: [General Translation frente a Babel y Flask-Babel: ¿cuál deberías usar?](https://generaltranslation.com/es/kb/general-translation-vs-flask-babel.mdx)
- Next question: [General Translation frente al framework de traducción de Django: ¿necesitas ambos?](https://generaltranslation.com/es/kb/general-translation-vs-django-i18n.mdx)

## Sitemap

See the [Knowledge Base sitemap](https://generaltranslation.com/es/kb/sitemap.md) for every article.
