lingo push

Max PrilutskiyГенеральный директор и соучредительUpdated 19 дней назад · 6 min read

Отправляет исходные файлы в движок, дожидается завершения запуска и сохраняет результаты на диск.

text
lingo push [patterns...] [--key <pattern>] [--force] [--backfill-missing] [--yes] [--wait] [--estimate]

Поведение по умолчанию — delta push#

Без аргументов lingo push работает в режиме только дельты:

  1. Вычисляет хеш для каждого исходного файла, подходящего под шаблоны files из конфигурации
  2. Сравнивает каждый хеш с lockfile, чтобы определить, какие исходники изменились
  3. Загружает изменённые исходники в движок как запуск
  4. Дожидается завершения запуска
  5. Записывает результаты на диск
  6. Сохраняет новые хеши исходников в lockfile

Если с момента последней успешной отправки ни один исходник не изменился, команда сразу завершается с ✓ Nothing to push. — без обращения к серверу и без расхода токенов.

Аргументы и флаги#

Позиционный аргумент: patterns... — push с ограниченной областью действия#

bash
lingo push docs/en/about.md
lingo push 'docs/en/**/*.md' 'locales/en.json'

Ограничивает push конкретными файлами (они должны уже соответствовать шаблонам в .lingo/config.json). Переключает команду в режим ограниченной области действия:

  • Без сравнения с предыдущими исходниками — каждый подходящий исходник считается входящим в область действия, даже если он не изменился.
  • На стороне сервера выполняется noop для целевых файлов, которые уже существуют и имеют совпадающие хеши исходников — движок пропускает их, а CLI помечает как кэшированные.

Используйте, если нужно перевести ровно один обновлённый файл без повторного хеширования всего проекта, или если нужно заново перевести одну страницу с помощью --force.

--key <pattern>#

bash
lingo push --key auth.login
lingo push --key auth.login --key billing.plan
lingo push --key "auth.*"

Повторно переводит только ключи, которые охватывает паттерн, объединяет их с существующим переводом, а все остальные ключи оставляет байт в байт неизменными. Можно повторять — по одному --key на каждый паттерн.

Область видимости по ключам игнорирует diff источника, поэтому ключ, чей исходный текст не менялся, всё равно переводится заново. В этом и суть флага: официальный способ переделать несколько строк после правки формулировки, смены модели или обновления глоссария — не платя за весь файл.

--force ничего лишнего не добавляет и отключает запрос подтверждения для всего файла.

Что происходит с каждым ключом#

Указан в --keyЕсть в переводеРезультат
дадапереведён заново
данетпереведён и добавлен
нетдасуществующий перевод сохранён
нетнетне записан вовсе

Последняя строка — вот что отличает область видимости по ключам от обычного push. Ключ, добавленный в источник после последнего полного push, не попадает в перевод как исходный текст — он просто пропускается, и следующий обычный lingo push переведёт его.

Как работает сопоставление паттернов#

ПаттернОхватывает
auth.loginauth.login и auth.login.title — но не auth.login_url
authauth и всё его поддерево — но не authority
"auth.*"всё под auth, включая auth.login_url, но не auth
"auth*"всё перечисленное плюс authority — без каких-либо границ

Паттерн сопоставляется с ключом точно, как префикс с границей ., /, - или [, либо как glob. Элементы массивов доступны через границу скобок, поэтому nav.items охватывает nav.items[0].title.

Берите glob-паттерны в кавычки. Иначе их раскроет оболочка: в zsh голый --key auth.* либо завершится с ошибкой no matches found, либо — если в директории окажется файл вроде auth.json — тихо превратится в его имя. Значение через запятую — не список: --key "a,b" — это один буквальный паттерн, который ничему не соответствует. Повторите флаг нужное количество раз.

Что не поддерживается#

Область видимости по ключам явно сообщает о проблемах и пропускает их, вместо того чтобы молча делать больше, чем вы просили:

  • Локаль без существующего перевода. Объединять не с чем — локаль называется и пропускается. Сначала переведите её с помощью --backfill-missing, затем используйте --key.
  • Форматы, в которых нельзя пропустить ключ — форматы документов, где ключи смещаются при редактировании, и xcode-stringsdict, которому необходимы все категории множественного числа для корректной работы файла. Полный список — в Formats. Такие файлы пропускаются с предупреждением, так что в одном push могут оказаться файлы обоих типов; отправляйте их без --key.
  • Паттерн, которому ничего не соответствует, сообщает об этом явно, а не делает вид, что всё уже актуально.

Позиционные элементы сохраняют исходный текст даже в рамках области видимости — элементы массивов, элементы Android <string-array>, количества <plurals> — потому что удаление одного изменит нумерацию остальных.

Lockfile не обновляется#

Запуск с областью видимости по ключам переводит часть файла, поэтому намеренно не трогает хеш источника в lockfile. Всё остальное, что изменилось в этом файле, остаётся в очереди — и следующий обычный lingo push это подхватит.

--force / -f#

bash
lingo push docs/en/about.md --force

Переводит заново все подходящие целевые файлы, игнорируя существующие переводы и обходя серверное кэширование. Ограничьте область — позиционными паттернами или --backfill-missing — если не хотите затронуть весь проект: голый lingo push --force повторно переводит все настроенные паттерны, и единственное, что стоит на пути, — запрос подтверждения ниже.

В проекте, который ещё не переводился, перезаписывать нечего — --force здесь бесполезен. Лучше сразу используйте --backfill-missing: он только заполняет пробелы и никогда не запрашивает подтверждения.

По умолчанию --force запрашивает подтверждение перед запуском:

text
! --force will retranslate every target for pattern(s): docs/en/about.md and
  overwrite existing translations. Continue? (Yes, retranslate / Cancel)

Передайте --yes / -y, чтобы пропустить запрос подтверждения (удобно для CI).

Чтобы переделать несколько строк, а не целые файлы, используйте --key — платите только за те ключи, которые указали.

--backfill-missing#

bash
lingo push --backfill-missing

Переводит каждый целевой файл, которого ещё нет, по всем настроенным шаблонам. Эквивалентно push с ограниченной областью действия по всем шаблонам из конфигурации, но создаёт только отсутствующие файлы. Используйте после добавления новой локали в targetLocales или при первом push для нового проекта.

Используйте вместе с --force, чтобы заново перевести всё с нуля:

bash
lingo push --backfill-missing --force --yes

--yes / -y#

Пропускает запрос подтверждения --force. Без --force не работает, и рядом с --key тоже бесполезен — область видимости по ключам никогда не запрашивает подтверждения, так как затрагивает только те ключи, которые вы указали.

--estimate#

bash
lingo push --estimate
lingo push 'docs/en/**/*.md' --estimate

Показывает примерную стоимость пуша и завершает работу без перевода. CLI прогоняет полный пайплайн — хеширование, вычисление дельты и загрузку исходных байтов, — чтобы сервер точно рассчитал дельту, а затем просит движок оценить стоимость запуска вместо его старта. Ничего не переводится, не записывается и не списывается; lock-файл и целевые файлы остаются нетронутыми.

Значения — это оценки, не точные цифры. --estimate сочетается с областью видимости и с --key / --force / --backfill-missing, так что можно заранее прикинуть стоимость именно того push, который вы собираетесь запустить.

Если исходные данные не изменились, --estimate завершается с ✓ Nothing to push. — как при обычном пуше.

Если запуск для тех же источников уже идёт, --estimate завершается с ошибкой, а не оценивает стоимость незавершённого запуска:

text
Error: Cannot estimate: existing group run_a8c... is already in 'running' state. Change a source file or wait for the run to finish.

Вывод#

При успешном выполнении:

text
Pushing source files to localization engine…
✓ Run run_a8c...: localized 12 target file(s), 4 already up-to-date, uploaded 1 new artifact(s).

Сводка включает:

  • Локализовано N целевых файлов — движок создал новые переводы, а CLI записал их на диск.
  • N уже актуальны — попадания в серверный кэш (исходник совпал, целевой файл переиспользован).
  • Загружено N новых артефактов — исходники, которых движок раньше не видел (двоичный или объёмный контент сохраняется один раз и затем переиспользуется по ссылке).
  • Пропущено N целевых файлов (локальные правки) — локальные хеши целевых файлов расходятся с lockfile. Перезапустите с --force, чтобы перезаписать их.

Если ошибка возникает для отдельных целевых файлов, CLI выводит ошибку для каждого из них и завершается с ненулевым кодом — удобно для CI:

text
✓ Run run_a8c...: localized 10 target file(s).
  2 target(s) failed:
    locales/de.json: rate limit on engine; retry later
    locales/fr.json: timeout

С --estimate:

text
Estimating push cost…
› Estimated cost: ~$1.87 (12 target(s), ~48,000 output tokens — estimate, not a quote)
  de: ~$0.9350 (6 target(s), ~24,000 tokens)
  fr: ~$0.9350 (6 target(s), ~24,000 tokens)
  4 target(s) already up-to-date — no cost.
✓ Estimate complete — nothing was translated. Run `lingo push` to start the translation.

Логика повторных попыток#

Lockfile обновляется только после полностью успешного запуска. При частичном сбое (например, если по одной локали произошёл тайм-аут) хеши исходников в lockfile остаются без изменений, поэтому следующий lingo push повторит ту же разницу — без ручного сброса.

Если движок завершится с ошибкой до начала перевода (авторизация, валидация), ничего не будет записано, а lockfile останется без изменений.

Типовые сценарии#

CI: перевод при merge#

yaml
- run: lingo push --backfill-missing --yes
- run: git add . && git commit -m "chore: refresh translations" && git push

--backfill-missing — безопасный вариант по умолчанию: ничего не перезаписывает, а только заполняет недостающие файлы.

Переделать несколько строк#

bash
lingo push --key auth.login --key billing.plan --wait

Повторно переводит именно эти ключи после правки формулировки, не трогая остальные ключи в файле.

Итерация по одному файлу#

bash
lingo push docs/en/onboarding.md -f -y

Заново переведите только один исходник после серьёзного изменения текста. Чтобы ускорить итерацию, пропустите запрос подтверждения.

Добавление новой локали#

После обновления targetLocales в .lingo/config.json:

bash
lingo push --backfill-missing

Переводит весь корпус в новую локаль, не затрагивая уже существующие переводы.