Файлы, форматы и экспорт
Строки проекта приходят файлами и уходят файлами. Эта страница — про оба направления.
Поддерживаемые форматы
Заголовок раздела «Поддерживаемые форматы»| Формат | Расширения | Что сохраняется |
|---|---|---|
| JSON | .json | Вложенность и массивы; формы множественного числа i18next (_one, _other…) становятся одним сегментом с множественным числом |
| Flutter ARB | .arb | Метаданные @key становятся описанием и записываются обратно целиком; @@locale сегментом не становится |
| YAML | .yaml, .yml | Вложенность, блочные скаляры, языковой корень Rails (en:), множественное число как one:/other: |
| gettext | .po, .pot | Значения, разбитые на несколько строк, msgctxt, msgid_plural с msgstr[n], комментарии #., fuzzy |
| Ресурсы Android | .xml | <string>, <plurals>, <string-array>, translatable="false", комментарии, разметка |
| Строки Apple | .strings | Комментарии как описания, экранирование, пустые значения |
| Множественное число Apple | .stringsdict | Одна переменная множественного числа на ключ |
| Xcode String Catalog | .xcstrings | Все языки каталога, комментарии, состояния, вариации множественного числа |
| XLIFF | .xliff, .xlf | 1.2 и 2.0: resname, заметки, maxwidth, translate="no", состояния |
| CSV | .csv | Заголовок называет колонки: ключ, описание, максимальная длина, по колонке на язык |
| Markdown | .md, .mdx | По сегменту на блок, правится как Markdown |
Формат берётся из расширения, а файл с расширением не из этого списка отклоняется с сообщением, где перечислены допустимые. Размер файла ограничен 10 МБ; проект крупнее переезжает импортом проекта.
Вложенные структуры превращаются в ключи через точку, поэтому такой файл:
{ "home": { "title": "Привет", "cta": "Начать" } }даёт ключи home.title и home.cta. Именно их ищет ваш код, а экспорт записывает файл обратно вложенным, в том виде, в каком он пришёл.
Ключ уникален в пределах своего файла. И в auth.json, и в home.json может быть title; в одном файле дважды его быть не может. Запись gettext с контекстом получает ключ из контекста и текста вместе, поэтому Open в меню и Open на двери остаются двумя сегментами.
Загрузка
Заголовок раздела «Загрузка»Загрузка исходного файла создаёт по сегменту на каждый ключ. Повторная загрузка того же файла — с тем же именем и в той же папке — это и есть способ отправлять изменения:
- У существующего ключа обновляется исходный текст.
- Ключ, которого больше нет в файле, удаляется из проекта и возвращается вместе с переводами, если файл снова его содержит.
- Новый ключ добавляется.
- Порядок в файле становится порядком сегментов, поэтому вставленный в середину блок остаётся в середине, а не прыгает в конец.
- Описание, ограничение длины или пометка «не переводится», которые несёт файл, сохраняются у сегмента.
Загрузка записывается целиком или не записывается вовсе.
Импорт готовых переводов
Заголовок раздела «Импорт готовых переводов»Загрузите файл, указав целевой язык, — и он читается как переводы, а не как источник: значения сопоставляются по ключу с сегментами одного файла и записываются в этот язык. Это файл, который вы выбрали, а иначе файл с тем же именем в той же папке, единственный файл с таким именем или тот, по которому названа загрузка, — de.yml находит en.yml, values-de/strings.xml находит values/strings.xml, auth.json.xliff находит auth.json. Если ничто из этого не решает вопрос, загрузка отклоняется, а не раскладывается по файлам с общим ключом.
Статус импортированного перевода берётся из файла, если файл его несёт: единица XLIFF с пометкой final или approved="yes" приходит утверждённой, запись gettext с fuzzy приходит на проверку. Без статуса новый перевод ждёт проверки. Перевод, у которого изменился текст, возвращается на проверку, даже если был утверждён; тот же самый текст свой статус не теряет. Утверждённые слова засчитываются в лимит тарифа, и загрузка, которая вышла бы за лимит, отклоняется целиком.
Это путь для переезда из другого инструмента: сначала отправьте исходный файл, потом по файлу на язык, либо перенесите весь проект импортом проекта.
Файлы лежат в папках внутри проекта, и файл опознаётся именем и путём: locales/en.json и mobile/en.json — два разных файла.
- Переименование папки одной операцией переносит все файлы под ней.
- Слияние дубликатов убирает файлы с одинаковыми именем и путём, созданные дважды, — обычный итог того, что один и тот же файл отправили два пайплайна раньше, чем у любого из них появился идентификатор файла.
Экспорт
Заголовок раздела «Экспорт»Экспорт записывает утверждённые переводы обратно в файл, в том формате и в той структуре, в которых файл был загружен: файл Android возвращается ресурсами Android, YAML для Rails — под запрошенным языком, вложенный JSON — вложенным.
| Что | Где |
|---|---|
| Один файл, один язык | Вкладка «Файлы» → Экспорт либо GET /v1/workspaces/{id}/segments/export?fileId=… |
| Все файлы на всех языках ZIP-архивом | Вкладка «Файлы» → Экспорт всех либо GET /v1/workspaces/{id}/segments/export-zip |
| Прямо в репозиторий | ownlate pull или интеграция с репозиторием |
| Бандлом для рантайма | Релизы и OTA |
Без файла экспорт сливает весь проект в один файл указанного формата (по умолчанию json). Файлы берутся в порядке пути и имени, и ключ, который есть в нескольких файлах, получает значение из последнего из них.
Сегменты с множественным числом записываются в синтаксисе формата: суффиксами i18next в JSON, msgid_plural в gettext, <plurals> в Android, вариацией в .stringsdict и .xcstrings.
Две настройки меняют то, что окажется в файле:
- Подстановка источника — передайте исходный язык, и непереведённые ключи будут записаны с исходным текстом, а не пропущены. Пригодится, когда отсутствие ключа ломает приложение; выключите, когда лучше увидеть дырку.
- Непереводимые сегменты всегда пишутся с исходным текстом, что бы вы ни просили.