CLI поддерживает восемнадцать форматов файлов. Формат определяется по расширению файла; чтобы переопределить его, укажите format в записи files[] — или для трёх форматов, которым это всегда нужно (yaml-openapi, yaml-root-key, android).
| Формат | Расширения | Значение format | Примечания |
|---|---|---|---|
| JSON | .json | json | Пары ключ-значение. Поддерживает управление ключами. |
| JSONC | .jsonc | jsonc | JSON с комментариями. Комментарии сохраняются и заодно работают как заметки для переводчика. |
| YAML | .yaml, .yml | yaml | Обычный YAML. Переводятся все строковые значения; ключи и структура сохраняются. |
| OpenAPI YAML | .yaml, .yml | yaml-openapi | Спецификации OpenAPI. Явно задайте format — иначе обычный .yaml будет автоматически определён как yaml. |
| YAML с корневым ключом локали | .yaml, .yml | yaml-root-key | Локаль — корневой ключ YAML (Rails config/locales). Корневой ключ переписывается под целевую локаль. Укажите format явно. |
| Markdown | .md | md | Основной текст переводится; frontmatter — только если включить отдельно. |
| MDX | .mdx | mdx | Markdown + JSX. Свойства компонентов — только по явному включению. |
| Markdoc | .mdoc | markdoc | Markdown + теги. Frontmatter и атрибуты тегов. |
| TypeScript | .ts, .mts, .cts | typescript | Модули локалей (export default { … }). Строковые литералы переводятся; код сохраняется. |
| Gettext PO | .po | po | Переводится msgstr; msgid, комментарии и заголовки сохраняются. |
| Flutter ARB | .arb | flutter | Переводятся строковые значения; метаданные @ и {placeholders} сохраняются. |
| Android | .xml | android | strings.xml. Явно задайте format — .xml автоматически не определяется. |
| Строки Xcode | .strings | xcode-strings | Переводятся значения; ключи сохраняются. |
| Каталог строк Xcode | .xcstrings | xcode-xcstrings | Один файл содержит все локали — целевые локали записываются обратно в тот же файл (см. ниже). |
| Xcode stringsdict | .stringsdict | xcode-stringsdict | Переводятся строки с формами множественного числа; управляющие ключи формата сохраняются. |
| XLIFF | .xlf, .xliff | xliff | <source> сохраняется, <target> записывается для каждой единицы. Поддерживаются версии 1.2 и 2.0. |
| SubRip | .srt | srt | Текст субтитров переводится; индексы и тайм-коды остаются без изменений. |
| PHP | .php | php | Laravel return [ … ]. Переводятся строковые значения; ключи, числа и структура сохраняются. |
Посмотрите весь процесс целиком
Демо-проект — небольшой Sandbox, в котором собраны форматы документов и данных: JSON, JSONC, Markdown, MDX, Markdoc и OpenAPI YAML — каждый с нужной конфигурацией. Клонируйте его с помощью npx degit lingodotdev/lingo.dev/demo/new-cli my-lingo-demo и запустите push. Форматы приложений и Фреймворков в нём не представлены — для них в примерах проектов есть отдельный репозиторий на каждый фреймворк, а фрагменты конфигурации ниже покрывают остальные форматы.
npx degit lingodotdev/lingo.dev/demo/new-cli my-lingo-demo
cd my-lingo-demoJSON и JSONC#
Обычный перевод пар ключ-значение. Переводятся все строковые значения, если управление ключами не говорит иначе.
{ "pattern": "content/en/app.json", "lockedKeys": ["meta.version"] }JSONC дополнительно сохраняет комментарии, которые движок использует как контекст — подробнее см. в разделе заметки для переводчика.
{ "pattern": "content/en/settings.jsonc", "preservedKeys": ["featureFlags"] }Markdown, MDX и Markdoc#
Основной текст переводится по умолчанию. Frontmatter и встроенные компоненты не переводятся, пока вы явно это не включите.
Frontmatter#
Перечислите поля frontmatter, которые нужно переводить, с помощью translateFrontmatterFields:
{
"pattern": "content/en/guide.md",
"translateFrontmatterFields": ["title", "description"]
}Свойства компонентов MDX#
В MDX можно переводить определённые свойства у определённых компонентов с помощью translateComponentProps:
{
"pattern": "content/en/landing.mdx",
"translateFrontmatterFields": ["title"],
"translateComponentProps": [{ "component": ["Hero", "Callout"], "props": ["title", "body"] }]
}Это переведёт свойства title и body у <Hero> и <Callout>, а все остальные свойства оставит без изменений.
Markdoc#
Markdoc работает так же, как Markdown: frontmatter и атрибуты тегов сохраняются:
{
"pattern": "content/en/changelog.mdoc",
"translateFrontmatterFields": ["title"]
}YAML#
Обычный YAML автоматически определяется по .yaml/.yml — переводятся все строковые значения, а ключи и структура сохраняются:
{ "pattern": "content/en/strings.yaml" }Со спецификациями OpenAPI ситуация особая: они используют расширение .yaml, но требуют явного format, чтобы движок переводил только пользовательские поля (summaries, descriptions) и оставлял без изменений ключи схем, paths и operation IDs:
{ "pattern": "content/en/api.yaml", "format": "yaml-openapi" }Файлы локалей в стиле Rails — ещё один особый случай: локаль здесь является корневым ключом YAML (en:), а целевой файл должен начинаться с ключа целевой локали (es:). Для них тоже укажите format явно:
{ "pattern": "config/locales/en.yml", "format": "yaml-root-key" }Форматы приложений и фреймворков#
PO, Flutter ARB, Xcode .strings, Xcode .stringsdict, модули локалей TypeScript, XLIFF, SubRip и PHP работают по одному и тому же принципу: переводится только переводимый текст, а всё структурное сохраняется (ключи, ID, метаданные, плейсхолдеры, тайм-коды, код, форматирование). Все они автоматически определяются по расширению — достаточно указать шаблон исходного файла:
{ "pattern": "lib/l10n/app_en.arb" }
{ "pattern": "locales/en.po" }
{ "pattern": "Localizable.strings" }
{ "pattern": "l10n/en.xlf" }Для одного из них нужно явно указать format, потому что по расширению его слишком сложно определить автоматически:
{ "pattern": "res/values/strings.xml", "format": "android" }Каталоги строк Xcode#
Файл .xcstrings (String Catalog) содержит все локали в одном файле. Отдельного пути вывода для каждой локали здесь нет — CLI читает исходную локаль и записывает все целевые обратно в тот же файл:
{ "pattern": "Localizable.xcstrings" }Строки, помеченные "shouldTranslate": false в каталоге, пропускаются: CLI не переводит и не изменяет их.
Пути вывода#
Шаблон указывает путь к исходному файлу; все целевые пути строятся на его основе. Действуют четыре правила — по порядку:
- Сегмент пути или имя файла полностью является локалью — стандартный случай.
content/en/app.json→content/de/app.json,locales/en.json→locales/de.json. - Локаль в конце сегмента или имени файла — для платформ, которые именуют файлы именно так: Android, Xcode
.strings/.stringsdict, Flutter иyaml-root-key.res/values-en/→res/values-de/,app_en.arb→app_de.arb,devise.en.yml→devise.de.yml. - Зарезервированное имя языка по умолчанию на платформе — без локали в пути. Простой
res/values/в Android становитсяres/values-de/, аBase.lprojв Xcode —de.lproj. - String Catalog — целевой путь совпадает с исходным, так как все локали хранятся в одном файле.
Android — единственная платформа, где целевые пути не соответствуют BCP 47: CLI записывает квалификатор ресурса в том виде, который Android понимает напрямую, поэтому pt-BR попадает в values-pt-rBR/, а zh-Hans — в values-b+zh+Hans/.
Если ни одно правило не сработало — исходная локаль нигде в пути не встречается — CLI сам создаёт рядом с файлом каталог <locale>/, а lingo push сообщает, что это лишь предположение. Такое предупреждение — сигнал, что шаблон задан неверно. См. Конфигурация.
Переходите с legacy CLI?#
Большинство форматов из legacy CLI уже поддерживаются в текущем CLI (PO, XLIFF, строки Android/Xcode, Flutter ARB и другие — см. таблицу выше). Некоторые менее распространённые форматы (например, CSV, HTML, MJML, .properties) пока ещё не поддерживаются; пока ваш формат не появится, ориентируйтесь на документацию legacy CLI.
