• Как устроено
  • Быстрый старт
  • Доступ и токен
    • Страницы
      • Frontmatter
      • Синтаксис markdown
      • Переводы страниц
    • Фреймы
      • Вставки onpress/
      • Бинды data-op-bind
      • Сборка и копии
    • Готовые фреймы
      • assistant
      • outline
      • faq
      • article
      • docs
      • site__header
      • site__footer
      • article__faq
      • landing
      • assistant__chat
      • site__404
      • news
      • news__category
      • news__post
      • news__more
      • news__share
      • author__page
      • author__byline
      • author__card
      • author__avatar
      • author__socials
      • author__head
      • home
      • pricing
    • Данные
      • Повторитель onpress/repeat
  • Стили
  • Меню
  • Сайдбар документации
  • Языки сайта
  • Настройки и кэш
  • SEO
  • Медиа
  • Сайты и домены
  • Пользователи и профиль
  • Дашборд и вход
    • Рецепты
      • Сайт с нуля
      • Раздел документации
      • Лендинг
      • FAQ
      • Свой фрейм из готового
      • Многоязычный сайт
      • Поменять меню
      • Перенести страницу
      • Картинки в статье
      • Список из данных
      • Сменить оформление
    • Справочник API
      • Страницы
      • Переводы
      • Фреймы
      • Данные
      • Меню
      • Сайдбар документации
      • Стили
      • Настройки, главная, кэш
      • Языки
      • SEO
      • Медиа
      • Сайты
      • Пользователи и профиль
      • Вход и служебное
    • Ошибки и проблемы
      • Коды ошибок
OnPress OnPress
  • Документация
  • Контакты
Войти
  • Как устроено
  • Быстрый старт
  • Доступ и токен
    • Страницы
      • Frontmatter
      • Синтаксис markdown
      • Переводы страниц
    • Фреймы
      • Вставки onpress/
      • Бинды data-op-bind
      • Сборка и копии
    • Готовые фреймы
      • assistant
      • outline
      • faq
      • article
      • docs
      • site__header
      • site__footer
      • article__faq
      • landing
      • assistant__chat
      • site__404
      • news
      • news__category
      • news__post
      • news__more
      • news__share
      • author__page
      • author__byline
      • author__card
      • author__avatar
      • author__socials
      • author__head
      • home
      • pricing
    • Данные
      • Повторитель onpress/repeat
  • Стили
  • Меню
  • Сайдбар документации
  • Языки сайта
  • Настройки и кэш
  • SEO
  • Медиа
  • Сайты и домены
  • Пользователи и профиль
  • Дашборд и вход
    • Рецепты
      • Сайт с нуля
      • Раздел документации
      • Лендинг
      • FAQ
      • Свой фрейм из готового
      • Многоязычный сайт
      • Поменять меню
      • Перенести страницу
      • Картинки в статье
      • Список из данных
      • Сменить оформление
    • Справочник API
      • Страницы
      • Переводы
      • Фреймы
      • Данные
      • Меню
      • Сайдбар документации
      • Стили
      • Настройки, главная, кэш
      • Языки
      • SEO
      • Медиа
      • Сайты
      • Пользователи и профиль
      • Вход и служебное
    • Ошибки и проблемы
      • Коды ошибок
Страницы
Markdown
Открыть в ИИ
  • Открыть в ChatGPT
  • Открыть в Claude
  • Открыть в Gemini
  • Открыть в Perplexity
  • Открыть в Grok
  • Открыть в DeepSeek

Языки и переводы страниц

Многоязычность в OnPress — это Polylang. У каждой страницы есть язык, а переводы одной страницы объединены в группу: из группы строятся hreflang в <head> и переключатель языков onpress/lang-switcher. Языки самого сайта (какие есть, какой основной, как попадают в адрес) описаны на странице языки сайта; здесь — всё, что касается страниц.

Язык страницы и адрес

Язык задаётся полем lang при публикации. Без него страница попадает в язык сайта по умолчанию, и ответ предупреждает об этом.

Адрес страницы не основного языка начинается с префикса языка: русская страница /o-nas/ на сайте с основным английским открывается по /ru/o-nas/. Основной язык обычно без префикса (настройка hide_default). В ответах API это разведено по двум полям: url — путь в дереве без префикса (/o-nas/), link — настоящий адрес (https://site/ru/o-nas/). В GET /pages и в системных источниках url уже с префиксом — это адрес, по которому страницу отдаёт сайт.

Одинаковый слаг в разных языках — норма. /o-nas/ и /ru/o-nas/ — две разные страницы с одним слагом. Поэтому всё, что ищет страницу по слагу, делает это с учётом языка: публикация ищет существующую страницу своего языка, GET /pages/{слаг}?lang=ru — русскую. Без lang голый слаг означает страницу основного языка.

Опубликовать перевод

Возьмите оригинал в формате заготовки под перевод:

curl -s -H "Authorization: Bearer $OP_TOKEN" \
  "$API/site/$SITE/pages/o-nas/markdown?as=translation_source" | jq -r .markdown > o-nas.ru.md

Вместо id во frontmatter будет translation_of с id оригинала, status не будет. Поменяйте lang, name, текст и, если нужно, slug и url:

---
name: "О компании"
slug: "o-nas"
url: "/o-nas/"
lang: "ru"
translation_of: 6703
frame: "article"
---

Текст на русском.

Опубликуйте обычным POST /pages/markdown. Страница создаётся и вступает в группу оригинала в одной транзакции: либо и то и другое, либо ничего.

{
  "success": true,
  "updated": false,
  "id": 6711,
  "lang": "ru",
  "url": "/o-nas/",
  "link": "https://example.onpress.pro/ru/o-nas/",
  "translations": { "ru": 6711, "en": 6703 },
  "translation_group": { "origin": { "id": 6703, "lang": "en" }, "term_id": 170, "created": true, "changed": true, "unlinked": [] }
}

Правила translation_of:

  • значение — id, слаг или путь оригинала; путь может быть с языковым префиксом;
  • обязателен lang, и он должен отличаться от языка оригинала;
  • группа дополняется, а не заменяется: третий язык встаёт рядом с первыми двумя;
  • если в группе уже была страница этого языка, она выходит из группы, и ответ предупреждает;
  • повторная публикация того же перевода даёт translation_group.changed: false.

Не копируйте id оригинала в перевод. Выгрузка обычного вида кладёт во frontmatter id; перевод с забытым id перезаписал бы оригинал. Такой запрос отклоняется 409 lang_mismatch — поэтому для переводов и существует ?as=translation_source.

Когда перевод не привязывается

КодКогдаЧто делать
422 translation_link_failedссылка не сработала; причина в reason: polylang_missing (на сайте нет языков), lang_required (нет lang), origin_not_found, origin_has_no_language, same_languageисправить ссылку; или link_soft: true, чтобы опубликовать без привязки — причина придёт в translation_link_error
409 translation_link_failedссылка верна, но в группе есть страницы, чей язык не совпадает с ключом; список в rejectedпривести группу в порядок ручкой PUT /pages/{ref}/translations
409 translation_group_conflictпубликация нашла существующую страницу по слагу, а та уже состоит в другой группе с другими страницамиперенос между группами — отдельная операция: DELETE /pages/{ref}/translations, затем привязать
409 front_page_group_conflictто же, и страница — главная своего языкаглавные меняются только через PUT /site/front-page

Управлять группой напрямую

Ручки под /pages/{ref}/translations. {ref} — id, слаг или путь с тильдами (ru~o-nas для /ru/o-nas/).

Посмотреть группу:

curl -s -H "Authorization: Bearer $OP_TOKEN" "$API/site/$SITE/pages/6444/translations" | jq '{translations, missing_languages}'
{ "translations": { "en": 6444, "ru": 6445 }, "missing_languages": [] }

Положить группу целиком — карта «язык → страница»; кого нет в карте, тот выходит из группы:

curl -s -X PUT "$API/site/$SITE/pages/6444/translations" \
  -H "Authorization: Bearer $OP_TOKEN" -H 'Content-Type: application/json' \
  -d '{"translations": {"en": 6444, "ru": "/ru/o-nas/"}}' | jq '{changed, group, unlinked}'
{ "changed": true, "group": { "term_id": 172, "created": true }, "unlinked": [] }

Повтор той же карты — changed: false, ничего не пишется, поэтому миграция может присылать группы на каждом прогоне.

Добавить один перевод, сохранив остальную группу:

curl -s -X POST "$API/site/$SITE/pages/6444/translations/ru" \
  -H "Authorization: Bearer $OP_TOKEN" -H 'Content-Type: application/json' \
  -d '{"page": 6445}' | jq '{linked, translations}'

Вывести страницу из группы (она остаётся опубликованной со своим языком):

curl -s -X DELETE "$API/site/$SITE/pages/6445/translations" -H "Authorization: Bearer $OP_TOKEN" | jq '{was_in, remaining, group_deleted}'

Все проверки выполняются до записи, и неудачная не пишет ничего: 409 translations_rejected (неизвестный язык, нет страницы, язык страницы не совпадает с ключом, одна страница дважды), 409 page_in_other_group (страница из другой группы — сначала выведите её), 409 same_language, 409 page_language_mismatch, 409 page_has_no_language. После каждой изменившей группу записи все затронутые страницы, включая выпавшие, получают событие обновления: пересобираются hreflang и сбрасывается их кэш.

Что строится из группы

  • hreflang в <head> каждой страницы группы — собирает SEO-плагин по группе.
  • Переключатель onpress/lang-switcher во фрейме показывает только языки, на которых страница существует и опубликована (scope: "page", по умолчанию). У страницы без переводов он не выводится вовсе. scope: "site" показывает все языки сайта: где перевод есть, ссылка ведёт на него, где нет — на главную этого языка.
  • Главные страницы языков: главная сайта хранит страницу основного языка, остальные языки получают главной её переводы из той же группы.

Остальное с языковым измерением

Язык есть не только у страниц. Меню стоят в области темы отдельно на каждый язык (меню). Набор данных может иметь вариант на язык: faq и faq@ru (наборы данных). Сайдбар документации строится по языку страницы (сайдбар). Фреймы общие для всех языков, а всё языкозависимое в них (меню, подписи вставок, повторители) собирается на языке страницы.

Страницы без языка

Страница без терма языка на многоязычном сайте не открывается: WordPress уводит её редиректом саму на себя. Сейчас API ставит язык всегда, но старые страницы без языка чинит отдельная ручка:

curl -s -X POST "$API/site/$SITE/pages/language" \
  -H "Authorization: Bearer $OP_TOKEN" -H 'Content-Type: application/json' \
  -d '{"missing": true, "lang": "ru", "dry_run": true}' | jq '{total, changed, pages}'

missing: true берёт все опубликованные страницы без языка (statuses расширяет выборку), pages: [ … ] — конкретные страницы, lang — какой язык ставить (без него — основной). Уберите dry_run, чтобы записать. Ручка ставит только язык и в группы переводов не лезет.

arrow_backНазад
Синтаксис markdown
Далееarrow_forward
Фреймы
На этой странице
  • Язык страницы и адрес
    • Опубликовать перевод
      • Когда перевод не привязывается
        • Управлять группой напрямую
          • Что строится из группы
            • Остальное с языковым измерением
              • Страницы без языка
              OnPress
              OnPress
              ИП Зуев И.В. ИНН: 360408359441
              © 2026
              политика конфиденциальности публичная оферта
              • visa
              • mastercard
              • sber
              • tpay