# General Translation Knowledge Base: General Translation и GNU gettext: нужны ли оба?
URL: https://generaltranslation.com/ru/kb/general-translation-vs-gettext.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: Оставьте GNU gettext для извлечения и рендеринга, а General Translation подключите для генерации и сопровождения PO-файлов. General Translation учитывает при генерации заметки для переводчиков и контекст сообщений, применяет общую терминологию и предоставляет рецензентам редактор в панели управления. Существующие вызовы gettext и скомпилированные каталоги остаются на месте.
Category: Интернационализация
Last updated: 2026-10-16
Authors: Kevin Wu, Jackie Chen
Published: 2026-10-16

GNU gettext — набор инструментов, на котором до сих пор держится бо́льшая часть перевода программного обеспечения. Вы оборачиваете видимые пользователю строки в `_()` или `gettext()`, `xgettext` извлекает их в шаблон POT, `msginit` создаёт PO-файл для каждого языка, `msgmerge` обновляет эти файлы при изменении источника, а `msgfmt` компилирует их в файлы `.mo`, которые программа загружает во время выполнения. Этот формат используют программы на C, расширение gettext для PHP, модуль `gettext` в Python, WordPress, Django и Babel. Но бо́льшую часть самого перевода gettext оставляет вам: начиная с версии 1.0 он умеет готовить черновики записей с помощью локальной LLM, однако каждый `msgstr` в каждом PO-файле доводите до ума вы, ваши переводчики или сторонний сервис. General Translation не заменяет ни один из этих инструментов: его CLI создаёт PO-файлы на основе вашего шаблона, а остальная настройка gettext остаётся прежней.

## В чём gettext силён

* **Ключом служит исходный текст.** В коде пишется `_("Inbox")`, а не имя ключа, а для строки без перевода [выводится исходный текст](https://www.gnu.org/software/gettext/manual/html_node/Interface-to-gettext.html), а не ошибка.
* **Правила множественного числа для каждого языка.** Каждый PO-файл содержит [заголовок `Plural-Forms` с правилом для своего языка](https://www.gnu.org/software/gettext/manual/html_node/Plural-forms.html), и `msginit` заполняет его за вас. Для польского задаётся правило с тремя формами и три слота `msgstr[n]` в каждой записи с множественным числом.
* **Контекст хранится вместе со строкой.** `msgctxt` (из `pgettext`) [позволяет различать «Archive»-глагол и «Archive»-существительное](https://www.gnu.org/software/gettext/manual/html_node/Contexts.html), комментарии `#.` передают заметки переводчикам (`xgettext --add-comments`), строки `#:` указывают на место в исходниках, а флаги вроде `python-format` позволяют `msgfmt --check` отклонить перевод, в котором сломана подсказка.
* **Безопасные обновления.** `msgmerge` [сохраняет существующие переводы при изменении шаблона](https://www.gnu.org/software/gettext/manual/html_node/msgmerge-Invocation.html) и помечает записи с изменившимся источником как fuzzy, сохраняя прежний исходный текст для сравнения (`--previous`).
* **Черновики от локальной LLM.** Начиная с версии 1.0, [`msgpre` и `spit` выполняют предварительный перевод PO-файлов](https://www.gnu.org/software/gettext/manual/html_node/Pretranslating.html) с помощью локально установленной LLM через ollama. Результат служит отправной точкой, которую затем проверяет переводчик.
* **Повсеместная поддержка.** PO-файлы читают и записывают PO-редакторы вроде Poedit и большинство систем управления переводами (TMS), а сами инструменты — [свободное ПО](https://www.gnu.org/software/gettext/manual/html_node/Licenses.html) (GPL; библиотека среды выполнения распространяется под LGPL).

## Что gettext перекладывает на вас

Вот небольшой скрипт на Python, использующий модуль `gettext` из стандартной библиотеки:

```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: заголовок страницы «Входящие»
print(_("Inbox"))
print(t.ngettext("You have %d unread message.", "You have %d unread messages.", count) % count)
print(t.pgettext("email verb", "Archive"))
```

Рабочий процесс gettext в [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
# кто-нибудь заполняет все msgstr в po/pl.po
msgfmt --check -o locale/pl/LC_MESSAGES/inbox.mo po/pl.po
```

Как только польский файл будет заполнен, `python3 inbox.py pl 5` выведет «Masz 5 nieprzeczytanych wiadomości.» Затем кто-то меняет в коде «unread message» на «new message». `xgettext` и `msgmerge --update --previous` переносят старый польский вариант и помечают его как fuzzy, поскольку теперь это перевод другого текста:

```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` [пропускает нечёткие (fuzzy) записи](https://www.gnu.org/software/gettext/manual/html_node/msgfmt-Invocation.html) (и сообщает &quot;2 translated messages, 1 fuzzy translation&quot;), поэтому та же команда теперь выводит &quot;You have 5 new messages.&quot; по-английски — прямо посреди польского экрана. В старом польском переводе по-прежнему написано «непрочитанных», так что его нужно обновить. General Translation может сгенерировать обновлённый перевод из нового шаблона прямо в процессе сборки.

## Перевод каталогов gettext с помощью General Translation

CLI от General Translation считывает ваш POT-шаблон, переводит каждую запись и создаёт PO-файл для каждого языка перевода. Укажите в `gt.config.json` путь к шаблону и место, куда сохранять файл для каждого языка. Эта конфигурация проверена на `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` читает файлы PO и POT**, а `"transformationFormat": "PO"` задаёт формат вывода — переведённые файлы `.po`. (См. [справочник по формату PO / POT](/docs/cli/reference/formats/po-pot-files).)
* **`transform` задаёт имена выходных файлов.** `{locale}` подставляет локаль точно в том виде, в каком она записана в `locales`, поэтому на выходе получаются `po/pl.po` и `po/pt_BR.po`. (См. [`transform`](/docs/cli/reference/config#files).)
* **Сохраняйте имена локалей gettext.** [`customMapping`](/docs/cli/reference/config#custom-mapping) сопоставляет `pt_BR` со стандартным кодом локали `pt-BR`. Этот же паттерн подходит и для других структур, например для `languages/my-plugin.pot` и `languages/my-plugin-de_DE.po` в плагине WordPress.

После настройки CLI (см. [Быстрый старт CLI](/docs/cli/quickstart)) рабочий процесс выглядит так:

```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` оставляет `charset=CHARSET` в заголовке шаблона как подсказку, а `msgconv` заменяет его на UTF-8 — так же, как это сделал бы `msginit` для языкового файла. [`npx gt translate`](/docs/cli/reference/commands/translate) отправляет каждую запись вместе со всем, что о ней известно из PO-файла, в качестве контекста: `msgctxt`, комментарии для переводчиков `#.`, ссылки `#:` и флаги формата. Для записи с формами множественного числа General Translation прописывает заголовок `Plural-Forms` языка перевода и заполняет все слоты `msgstr[n]`, которых требует этот заголовок (три для польского, шесть для арабского), а также проверяет, что подсказки вроде `%d` сохраняются без изменений.

Если `msgid` меняется, при следующем запуске General Translation сгенерирует перевод нового текста; для неизменённых записей используются прежние переводы. Перед первым запуском генерации импортируйте существующие переводы из PO-файлов с помощью [`npx gt upload`](/docs/cli/reference/commands/upload). Если позже вы правите файлы в локальном PO-редакторе, [`npx gt save-local`](/docs/cli/reference/commands/save-local) сохранит эти правки на платформе перед очередной генерацией.

Но General Translation не ограничивается заполнением `msgstr` — он предоставляет весь остальной стек. Glossary и пользовательские промпты в [контекстной группе](/docs/platform/dashboard/guides/defining-context-for-translations) обеспечивают единообразие терминологии и тона во всех PO-файлах и любых других областях взаимодействия с пользователем, которые вы переводите. Рецензенты могут [проверять и редактировать](/docs/platform/dashboard/guides/reviewing-translations) каждую запись PO — с учётом форм множественного числа языка перевода — в панели управления, а CLI работает в CI, так что каждый релиз выходит с актуальными каталогами.

Запускайте CLI для Node.js в процессе сборки, а затем компилируйте полученные PO-файлы с помощью `msgfmt`. Приложение, как и раньше, загружает скомпилированные переводы локально.

## GNU gettext и General Translation: краткое сравнение

| Возможность                                      | GNU gettext                                                                             | General Translation                                                                 |
| ------------------------------------------------ | --------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
| Извлечение строк из кода                         | Да, `xgettext`                                                                          | Использует ваш существующий шаблон POT                                              |
| Создание файла для каждого языка                 | Да, `msginit`                                                                           | Да, на основе шаблона, для каждой настроенной локали                                |
| Создание переводов                               | С версии 1.0 готовит черновики с помощью локальной LLM, которые дорабатывает переводчик | Да, с помощью [`npx gt translate`](/docs/cli/reference/commands/translate)          |
| После изменения исходной строки                  | `msgmerge` помечает её как fuzzy до проверки                                            | Переводится заново при следующем запуске; неизменённые записи используются повторно |
| Формы множественного числа                       | `msginit` записывает заголовок; каждый слот заполняете вы                              | Записывает заголовок и заполняет все слоты                                          |
| Контекст для перевода                            | `msgctxt`, комментарии переводчика, ссылки, флаги                                       | То же самое, а также Glossary и пользовательские промпты                            |
| Компиляция и поиск переводов во время выполнения | Да, `msgfmt` и среда выполнения gettext                                                 | Сохраняет ваш компилятор и среду выполнения gettext                                 |
| Стоимость                                        | Свободное ПО                                                                            | [Оплата перевода по факту использования](https://generaltranslation.com/pricing)    |

## Когда что использовать

Используйте только gettext, если ваши PO-файлы уже заполняют переводчики или TMS, если каждый перевод должен написать человек до выпуска или если в вашей сборке нельзя запустить Node.js. Подключите General Translation, если хотите, чтобы каждый PO-файл переводился на все языки сразу после изменения шаблона — с заполненными слотами множественного числа и единообразной терминологией, — не дожидаясь очередного раунда перевода.

Мигрировать ничего не нужно: General Translation сохраняет ваши вызовы `_()`, шаблон, PO-файлы и среду выполнения. Он заменяет ручной этап между `msgmerge` и `msgfmt`. (Варианты настройки для конкретных фреймворков см. в статьях [General Translation и фреймворк перевода Django](/kb/general-translation-vs-django-i18n) и [General Translation и Babel с Flask-Babel](/kb/general-translation-vs-flask-babel).)

## Основные выводы

* GNU gettext извлекает, объединяет, компилирует и находит переводы, а начиная с версии 1.0 умеет готовить их черновики с помощью локальной LLM, но до конца работу не доводит. Новые и изменённые строки остаются на языке-источнике, пока кто-нибудь их не переведёт или не проверит.
* CLI General Translation переводит шаблон POT в отдельный PO-файл для каждого языка. Для этого используются ключ `pot`, параметр `"transformationFormat": "PO"`, `transform` для пути выходного файла и `customMapping` для имён вроде `pt_BR`.
* Для каждой записи с формами множественного числа General Translation прописывает заголовок `Plural-Forms` для языка перевода и заполняет все слоты `msgstr[n]`, используя `msgctxt` и комментарии переводчика в качестве контекста. `msgfmt` и ваша среда выполнения gettext остаются без изменений.

## Related questions

- [General Translation и фреймворк переводов Django: нужны ли оба?](https://generaltranslation.com/ru/kb/general-translation-vs-django-i18n.mdx): Используйте фреймворк переводов Django вместе с General Translation. Django отвечает за извлечение сообщений, выбор языка и рендеринг. General Translation заполняет его PO-файлы, включая формы множественного числа, с учётом терминологии вашего продукта и проверки в панели управления. Ваши шаблоны и URL-шаблоны остаются прежними, а переводы обновляются вместе с кодом.
- [General Translation или Babel и Flask-Babel: что выбрать?](https://generaltranslation.com/ru/kb/general-translation-vs-flask-babel.mdx): Babel форматирует даты, числа и валюты для любой локали и управляет каталогами gettext, а Flask-Babel интегрирует его с Flask, но ни один из них не переводит ваши строки. CLI General Translation заполняет PO-файлы Babel для всех языков, включая формы множественного числа, поэтому вы можете и дальше использовать Flask-Babel, но больше не переводить каталоги вручную.
- [Почему стоит выбрать General Translation вместо TMS (Smartling, Lokalise, Phrase, Crowdin или Transifex)?](https://generaltranslation.com/ru/kb/general-translation-vs-tms.mdx): Система управления переводами (TMS), например Smartling, Lokalise, Phrase, Crowdin или Transifex, координирует работу переводчиков, но инженерам всё равно приходится извлекать строки, отправлять их на перевод, ждать результатов и встраивать переводы обратно в продукт. General Translation переводит контент прямо в вашем коде с учётом контекста, выпускает все языки с каждым релизом и работает на библиотеках с открытым исходным кодом без привязки к поставщику.
- [General Translation или Weblate: что выбрать?](https://generaltranslation.com/ru/kb/general-translation-vs-weblate.mdx): Weblate — это платформа локализации на основе Git, которую можно развернуть на собственном сервере. Она создана для перевода файлов репозитория силами сообщества или команды. General Translation встраивает генерацию переводов в разработку и релизы, опираясь на размеченный JSX и общий контекст продукта. Оставьте свои файлы gettext или перейдите на написание текста непосредственно в коде — тогда отпадёт и необходимость поддерживать каталог исходных сообщений.
- [Какое ПО для локализации лучше всего подходит разработчикам?](https://generaltranslation.com/ru/kb/best-localization-software.mdx): Ищите единую систему, которая охватывает весь конвейер — от библиотеки интернационализации в вашем коде до перевода и доставки, — а не собирайте по частям отдельную библиотеку, систему управления переводами и поставщика переводов.

## Previous and next questions

- Previous question: [Можно ли реализовать i18n без файлов перевода?](https://generaltranslation.com/ru/kb/i18n-without-translation-files.mdx)
- Next question: [General Translation и Rails I18n: нужны ли оба?](https://generaltranslation.com/ru/kb/general-translation-vs-rails-i18n.mdx)

## Sitemap

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