Многоязычность для headless CMS.
Polylang предоставил сайтам на WordPress полноценный многоязычный рабочий процесс. PolyLingo приносит этот рабочий процесс в Sanity, Contentful, Webflow, Framer и любую другую headless CMS — через REST API, который интегрируется за один день.
Многоязычность в headless CMS — нерешённая проблема.
Sanity имеет плагин интернационализации. Contentful поддерживает локали. Но ни один из них не переводит ваш контент — они просто хранят его на нескольких языках. Заполнение этих языковых слотов по-прежнему ручной процесс. Экспортируйте английский контент, пропускайте его через инструмент перевода, который ломает вашу структуру rich text или JSON, исправляйте результат, импортируйте обратно, повторяйте для каждого языка. Для активной команды контента, публикующей регулярно, такой рабочий процесс не масштабируется. Кроме того, для большинства небольших проектов он вообще отсутствует, поэтому контент просто никогда не переводится.
Архитектура headless CMS разделяет управление контентом и его доставку. Это хорошо для гибкости. Но создаёт пробел: CMS хранит языковые варианты, но никто не заполняет эти варианты переведённым контентом. Этот слой нужно создавать самостоятельно.
Большинство команд оказываются в одной из двух ситуаций: они переводят контент вручную, копируя его в DeepL и вставляя обратно (медленно, с ошибками, не масштабируется), или пишут кастомную интеграцию с API перевода, которую приходится поддерживать бесконечно. Ни один из вариантов не является хорошим решением. PolyLingo — чистый третий вариант.
PolyLingo — это слой перевода, которого не хватает вашей CMS.
PolyLingo интегрируется напрямую в ваш рабочий процесс публикации CMS. Настройте webhook, который срабатывает при публикации контента, передайте контент в PolyLingo, получите переводы для всех языков, запишите их обратно в CMS. Для Sanity это несколько строк в серверном действии. Для Contentful — обработчик webhook. Для кастомных решений — HTTP-запрос. Модель перевода понимает формат вашего контента — Markdown, HTML, JSON, rich text — и сохраняет структуру на протяжении всего процесса.
Паттерн одинаков для всех CMS: получить контент на исходном языке, вызвать PolyLingo API со всеми целевыми языками, записать переведённый контент обратно в CMS через её API управления. Это может быть скрипт на этапе сборки, задача CI или обработчик webhook — что подходит вашему рабочему процессу.
PolyLingo обрабатывает Markdown, HTML и простой текст, поэтому работает с любым форматом, который ваша CMS использует для богатого контента. Структурированные поля (заголовки, тело, выдержка) можно переводить отдельно, чтобы вы могли точно контролировать, какие поля переводятся.
Sanity + PolyLingo
Плагин Document Internationalization для Sanity создаёт связанные варианты документов для каждой локали. Скрипт ниже получает базовые документы на английском и автоматически создаёт переводы для каждого целевого языка.
Работает с паттерном i18n на уровне документа (один документ на локаль), а также с паттерном на уровне полей (все локали в одном документе). Для паттерна на уровне полей перебирайте поля, а не документы.
// scripts/translate-sanity.mjs
// Fetches published posts and translates each to all target languages
import { createClient } from '@sanity/client'
const sanity = createClient({
projectId: process.env.SANITY_PROJECT_ID,
dataset: 'production',
token: process.env.SANITY_TOKEN,
apiVersion: '2024-01-01',
useCdn: false,
})
const posts = await sanity.fetch(`*[_type == "post" && __i18n_lang == "en"]`)
for (const post of posts) {
const response = await fetch('https://api.usepolylingo.com/v1/translate', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.POLYLINGO_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
content: post.body_markdown,
format: 'markdown',
targets: ['es', 'fr', 'de', 'ja', 'zh'],
}),
})
const { translations } = await response.json()
for (const [lang, content] of Object.entries(translations)) {
await sanity.create({
_type: 'post',
__i18n_lang: lang,
__i18n_base: { _type: 'reference', _ref: post._id },
title: translations[lang + '_title'] || post.title,
slug: { current: `${post.slug.current}-${lang}` },
body_markdown: content,
})
}
}Contentful + PolyLingo
Contentful хранит варианты локалей как поля в одной записи. Скрипт ниже использует Contentful Management API для получения английских записей, их перевода и записи переведённого контента напрямую в поля, соответствующие локалям — без ручного копирования.
Contentful использует коды локалей BCP 47 (например, es-ES вместо es). Соответственно сопоставьте ISO 639-1 коды PolyLingo с вашей конфигурацией локалей Contentful.
// scripts/translate-contentful.mjs
// Translates Contentful entries to all target locales
import contentful from 'contentful-management'
const client = contentful.createClient({
accessToken: process.env.CONTENTFUL_MANAGEMENT_TOKEN,
})
const space = await client.getSpace(process.env.CONTENTFUL_SPACE_ID)
const env = await space.getEnvironment('master')
const entries = await env.getEntries({ content_type: 'blogPost', locale: 'en-US' })
for (const entry of entries.items) {
const enBody = entry.fields.body['en-US']
const response = await fetch('https://api.usepolylingo.com/v1/translate', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.POLYLINGO_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
content: enBody,
format: 'markdown',
targets: ['es-ES', 'fr-FR', 'de-DE'],
}),
})
const { translations } = await response.json()
for (const [locale, content] of Object.entries(translations)) {
entry.fields.body[locale] = content
}
await entry.update()
await entry.publish()
}Webflow + PolyLingo
Localization API Webflow (доступен на планах CMS и Business) поддерживает контент полей, специфичный для локали. Скрипт ниже получает элементы коллекции CMS, переводит поле с HTML-телом и записывает переводы обратно в каждый вариант локали через Webflow v2 API.
Webflow хранит поля rich text в формате HTML. Перевод HTML PolyLingo сохраняет всю разметку, сгенерированную Webflow — пользовательские классы, атрибуты и встроенные элементы — без изменений.
// scripts/translate-webflow.mjs
// Webflow Localization API + PolyLingo
const headers = {
'Authorization': `Bearer ${process.env.WEBFLOW_API_TOKEN}`,
'accept-version': '2.0.0',
'Content-Type': 'application/json',
}
// Fetch English CMS items
const itemsRes = await fetch(
`https://api.webflow.com/v2/collections/${process.env.WEBFLOW_COLLECTION_ID}/items`,
{ headers }
)
const { items } = await itemsRes.json()
for (const item of items) {
const response = await fetch('https://api.usepolylingo.com/v1/translate', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.POLYLINGO_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
content: item.fieldData['body-html'],
format: 'html',
targets: ['es', 'fr', 'de'],
}),
})
const { translations } = await response.json()
// Write translated content back to Webflow locale fields
for (const [lang, content] of Object.entries(translations)) {
await fetch(
`https://api.webflow.com/v2/collections/${process.env.WEBFLOW_COLLECTION_ID}/items/${item.id}/locales/${lang}`,
{ method: 'PATCH', headers, body: JSON.stringify({ fieldData: { 'body-html': content } }) }
)
}
}Что PolyLingo даёт пользователям headless CMS
- ✓Sanity — перевод при публикации через webhook, запись обратно в локали документа
- ✓Contentful — автоматический перевод записей при обновлении английской локали
- ✓Webflow — перевод элементов коллекции CMS через API
- ✓Любая headless CMS с API — паттерн интеграции одинаковый
- ✓Rich text, Markdown и HTML сохраняются корректно
- ✓Все 36 языков в одном запросе — без вызовов на каждый язык отдельно
- ✓Работает с любой CMS, у которой есть API управления
- ✓Контент можно переводить заново при каждой публикации — без ручной синхронизации
Стандартный многоязычный рабочий процесс CMS
Создайте контент на исходном языке
Создавайте и публикуйте контент на английском (или любом другом исходном языке). Ваша CMS хранит его как авторитетную версию. Вам не нужно менять редакционный процесс.
Запустите скрипт перевода
Запускайте скрипт вручную, по расписанию или через webhook, срабатывающий при публикации контента в CMS. Скрипт вызывает PolyLingo один раз на документ со всеми целевыми языками, затем записывает все переводы обратно в CMS за один проход.
Разверните — переведённый контент доступен
Ваш фронтенд читает контент, специфичный для локали, из CMS как обычно. Изменения в коде фронтенда не требуются. Переведённый контент отображается на правильном языке для каждого локального маршрута.
Для кого это создано
Команды контента на Sanity или Contentful
Ваши редакторы публикуют на английском. Переведённый контент автоматически появляется во всех локалях без необходимости взаимодействия команды с инструментами перевода.
Агентства, создающие многоязычные сайты
Каждому клиентскому сайту нужна поддержка многоязычности. PolyLingo даёт вам повторно используемую, оплачиваемую интеграцию, которая работает с любой headless CMS в вашем стеке.
E-commerce с локализованным контентом товаров
Описание товаров, страницы категорий и блог — всё переводится автоматически при публикации. Совместите с локализованным ценообразованием для полного локализованного опыта покупок.
Часто задаваемые вопросы о многоязычности в headless CMS
Работает ли PolyLingo с CMS, не перечисленными здесь?
Да. Любая CMS с API управления может быть интегрирована по тому же паттерну — получить контент, вызвать PolyLingo, записать обратно. Prismic, Storyblok, DatoCMS, Strapi, Ghost и Directus имеют API управления и работают с этим подходом. Примеры интеграций для Sanity, Contentful и Webflow выше иллюстрируют этот паттерн.
Можно ли переводить rich text с встроенными изображениями и ссылками?
Да. Перевод HTML сохраняет все встроенные элементы, включая изображения (атрибуты src и alt обрабатываются корректно), ссылки (href сохраняется, текст ссылки переводится) и iframe. Единственное исключение — контент, явно помеченный как непереводимый — например, блоки кода никогда не переводятся.
Как обрабатывать контент, который не должен переводиться?
Для структурированного контента с непереводимыми полями (slug, даты, технические идентификаторы) отправляйте только поля, которые хотите перевести. Для rich text с смешанными переводимыми и непереводимыми секциями используйте формат HTML — PolyLingo переведёт текст, сохраняя блоки кода и другие структурированные элементы автоматически.
Что делать, если в моей CMS есть вложенные типы контента?
Для глубоко вложенного контента (документы с ссылками на другие документы) переводите каждый тип документа отдельно. Это избегает циклических ссылок и даёт чёткий контроль над тем, какой контент переводится. Ссылки между документами поддерживаются CMS — PolyLingo работает только с содержимым полей, не затрагивая связи между документами.
Как поддерживать синхронизацию переводов при изменении исходного контента?
Рекомендуемый паттерн — запускать скрипт перевода при каждом событии публикации через webhook CMS. Это гарантирует обновление переведённого контента при изменении исходника. Для менее частых обновлений можно запускать скрипт по расписанию ночью или перед каждым продакшен-деплоем.
Можно ли помечать переводы как «требующие проверки» вместо автоматической публикации?
Это зависит от вашей CMS. Contentful и Sanity поддерживают состояния черновиков — вы можете записывать переводы как черновики, позволяя человеку проверять их перед публикацией каждой локали. Примеры скриптов выше используют немедленную публикацию; измените последний шаг, чтобы создавать черновики для рабочего процесса с проверкой.
Связанные руководства
Перевод HTML без нарушения разметки
Как PolyLingo обрабатывает HTML, сгенерированный CMS, с полным сохранением тегов.
Добавление многоязычности в Next.js
Комбинирование перевода контента headless CMS с переводом UI-строк через next-intl.
Альтернатива Polylang для современных стеков
Миграция многоязычного рабочего процесса с WordPress на headless setup.
Добавьте многоязычность в вашу headless CMS уже сегодня.
Бесплатный тариф. 100 000 токенов в месяц. Кредитная карта не требуется.
Начать бесплатный переводБесплатный тариф — 100 000 токенов в месяц. Работает с любой CMS.