lingo push
Отправляет исходные файлы в движок, дожидается завершения запуска и сохраняет результаты на диск.
lingo push [patterns...] [--key <pattern>] [--force] [--backfill-missing] [--yes] [--wait] [--estimate]Поведение по умолчанию — delta push#
Без аргументов lingo push работает в режиме только дельты:
- Вычисляет хеш для каждого исходного файла, подходящего под шаблоны
filesиз конфигурации - Сравнивает каждый хеш с lockfile, чтобы определить, какие исходники изменились
- Загружает изменённые исходники в движок как запуск
- Дожидается завершения запуска
- Записывает результаты на диск
- Сохраняет новые хеши исходников в lockfile
Если с момента последней успешной отправки ни один исходник не изменился, команда сразу завершается с ✓ Nothing to push. — без обращения к серверу и без расхода токенов.
Аргументы и флаги#
Позиционный аргумент: patterns... — push с ограниченной областью действия#
lingo push docs/en/about.md
lingo push 'docs/en/**/*.md' 'locales/en.json'Ограничивает push конкретными файлами (они должны уже соответствовать шаблонам в .lingo/config.json). Переключает команду в режим ограниченной области действия:
- Без сравнения с предыдущими исходниками — каждый подходящий исходник считается входящим в область действия, даже если он не изменился.
- На стороне сервера выполняется noop для целевых файлов, которые уже существуют и имеют совпадающие хеши исходников — движок пропускает их, а CLI помечает как кэшированные.
Используйте, если нужно перевести ровно один обновлённый файл без повторного хеширования всего проекта, или если нужно заново перевести одну страницу с помощью --force.
--key <pattern>#
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.login | auth.login и auth.login.title — но не auth.login_url |
auth | auth и всё его поддерево — но не 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#
lingo push docs/en/about.md --forceПереводит заново все подходящие целевые файлы, игнорируя существующие переводы и обходя серверное кэширование. Ограничьте область — позиционными паттернами или --backfill-missing — если не хотите затронуть весь проект: голый lingo push --force повторно переводит все настроенные паттерны, и единственное, что стоит на пути, — запрос подтверждения ниже.
В проекте, который ещё не переводился, перезаписывать нечего — --force здесь бесполезен. Лучше сразу используйте --backfill-missing: он только заполняет пробелы и никогда не запрашивает подтверждения.
По умолчанию --force запрашивает подтверждение перед запуском:
! --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#
lingo push --backfill-missingПереводит каждый целевой файл, которого ещё нет, по всем настроенным шаблонам. Эквивалентно push с ограниченной областью действия по всем шаблонам из конфигурации, но создаёт только отсутствующие файлы. Используйте после добавления новой локали в targetLocales или при первом push для нового проекта.
Используйте вместе с --force, чтобы заново перевести всё с нуля:
lingo push --backfill-missing --force --yes--yes / -y#
Пропускает запрос подтверждения --force. Без --force не работает, и рядом с --key тоже бесполезен — область видимости по ключам никогда не запрашивает подтверждения, так как затрагивает только те ключи, которые вы указали.
--estimate#
lingo push --estimate
lingo push 'docs/en/**/*.md' --estimateПоказывает примерную стоимость пуша и завершает работу без перевода. CLI прогоняет полный пайплайн — хеширование, вычисление дельты и загрузку исходных байтов, — чтобы сервер точно рассчитал дельту, а затем просит движок оценить стоимость запуска вместо его старта. Ничего не переводится, не записывается и не списывается; lock-файл и целевые файлы остаются нетронутыми.
Значения — это оценки, не точные цифры. --estimate сочетается с областью видимости и с --key / --force / --backfill-missing, так что можно заранее прикинуть стоимость именно того push, который вы собираетесь запустить.
Если исходные данные не изменились, --estimate завершается с ✓ Nothing to push. — как при обычном пуше.
Если запуск для тех же источников уже идёт, --estimate завершается с ошибкой, а не оценивает стоимость незавершённого запуска:
Error: Cannot estimate: existing group run_a8c... is already in 'running' state. Change a source file or wait for the run to finish.Вывод#
При успешном выполнении:
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:
✓ 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:
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#
- run: lingo push --backfill-missing --yes
- run: git add . && git commit -m "chore: refresh translations" && git push--backfill-missing — безопасный вариант по умолчанию: ничего не перезаписывает, а только заполняет недостающие файлы.
Переделать несколько строк#
lingo push --key auth.login --key billing.plan --waitПовторно переводит именно эти ключи после правки формулировки, не трогая остальные ключи в файле.
Итерация по одному файлу#
lingo push docs/en/onboarding.md -f -yЗаново переведите только один исходник после серьёзного изменения текста. Чтобы ускорить итерацию, пропустите запрос подтверждения.
Добавление новой локали#
После обновления targetLocales в .lingo/config.json:
lingo push --backfill-missingПереводит весь корпус в новую локаль, не затрагивая уже существующие переводы.