Перейти к содержимому

Релизы и OTA

Экспорт — это файл, который вы коммитите. Релиз — снимок, который скачивает ваше приложение. Релизы нужны, чтобы поменять перевод, не выпуская новую сборку.

Со вкладки Релизы проекта или мутацией GraphQL createRelease. Релиз берёт утверждённые переводы проекта в том виде, в каком они прямо сейчас, и замораживает их.

ПолеЧто значит
versionПрисваивается автоматически, растёт в пределах проекта
name, descriptionВаши, чтобы сказать, что изменилось
splitByFilesГруппировать ли бандл по файлам — см. ниже
languagesКакие языки попали в бандл
segmentCountСколько ключей несёт самый полный язык

Внутрь попадают только переводы в статусе approved. Язык, который никто не дописал, окажется в релизе с готовыми ключами и без остальных, поэтому незаконченный язык релиз не блокирует — но прогресс перед выпуском посмотреть стоит.

По умолчанию бандл — плоское отображение ключа в значение, по отображению на язык, причём в исходном языке лежат исходные тексты:

{
"en": { "home.title": "Hello" },
"ru": { "home.title": "Привет" }
}

С splitByFiles ключи сгруппированы по файлу, из которого пришли:

{
"en": { "5f1c…": { "home.title": "Hello" } },
"ru": { "5f1c…": { "home.title": "Привет" } }
}

Плоская форма подходит, когда приложение грузит по словарю на язык, а разбитая — когда оно грузит по одному пространству имён за раз.

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

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

Этот отчёт стоит прочитать при первом релизе проекта, разложенного по многим файлам. Либо переименуйте конфликтующие ключи, либо переключите релиз в splitByFiles — и конфликт исчезнет.

У каждого проекта одна раздача: постоянный ключ доступа, который отдаёт его релизы по HTTP без авторизации.

Найти его можно в разделе Релизы → Раздача или запросом GraphQL releaseDistribution. Если ключ утёк, перевыпустите его — старый перестанет работать немедленно, и всем клиентам понадобится новый.

GET https://api.ownlate.com/public/v1/ota/{accessKey}/manifest
GET https://api.ownlate.com/public/v1/ota/{accessKey}/bundles
GET https://api.ownlate.com/public/v1/ota/{accessKey}/bundles/{language}

Манифест маленький, его дёшево опрашивать:

{ "version": 7, "languages": ["en", "ru", "de"], "publishedAt": "2026-08-20T09:31:00Z" }

Ручки бандлов отдают переводы — по всем языкам или по одному:

{
"version": 7,
"language": "ru",
"splitByFiles": false,
"publishedAt": "2026-08-20T09:31:00Z",
"translations": { "home.title": "Привет" }
}

Все три по умолчанию отдают последний релиз. Добавьте ?version=5, чтобы закрепиться на более раннем, — пригодится, когда старая сборка приложения ждёт ключи, которых в текущем релизе уже нет.

Ответы несут ETag, собранный из версии и времени публикации. Пришлите If-None-Match — и неизменившийся бандл ответит 304 Not Modified без тела. Бандлы сжимаются, если клиент сообщил, что принимает сжатие, и сжатая форма тоже кешируется.

Разумный клиент запрашивает манифест при запуске, сравнивает версию с сохранённой и скачивает бандл только при расхождении.