无头CMS + PolyLingo

无头CMS的多语言支持。

Polylang为WordPress网站提供了完整的多语言工作流程。PolyLingo通过REST API将该工作流程带到Sanity、Contentful、Webflow、Framer及所有其他无头CMS——只需一个下午即可集成。

Sanity
完整集成示例
Contentful
完整集成示例
Webflow
完整集成示例
36
目标语言

无头CMS多语言支持是一个未解决的问题。

Sanity有国际化插件。Contentful有语言环境。但它们都不翻译您的内容——只是以多种语言存储。填充这些语言槽仍然是手动过程。导出英文内容,使用会破坏富文本或JSON结构的翻译工具翻译,修正输出,导入回去,针对每种语言重复。对于定期发布的活跃内容团队,这种工作流程无法扩展。对于大多数较小的设置,这种流程根本不存在,意味着内容根本不会被翻译。

无头CMS架构将内容管理与内容交付分离。这有利于灵活性。但也造成了一个空白:CMS存储语言变体,但没有任何东西填充这些语言变体的翻译内容。您必须自己构建这层。

大多数团队最终处于两种情况之一:手动翻译内容,复制到DeepL再粘贴回来(慢、易错、无法扩展),或者编写自定义集成调用翻译API并需长期维护。两者都不是好方案。PolyLingo是一个干净的第三种选择。

PolyLingo是您的CMS缺失的翻译层。

PolyLingo直接集成到您的CMS发布工作流程。设置一个内容发布时触发的Webhook,将内容传给PolyLingo,接收每种语言的翻译版本,再写回CMS。对于Sanity,只需几行服务器操作代码。对于Contentful,是一个Webhook处理程序。对于自定义设置,是一个HTTP调用。翻译模型理解您的内容格式——Markdown、HTML、JSON、富文本——并始终保留结构。

该模式在每个CMS中一致:获取源语言内容,调用PolyLingo API并传入所有目标语言,通过CMS管理API写回翻译内容。此过程可作为构建时脚本、CI任务或Webhook处理程序运行——根据您的工作流程选择。

PolyLingo支持Markdown、HTML和纯文本,因此适用于您的CMS用于富内容的任何格式。结构化字段(标题、正文、摘要)可单独翻译,给予您对翻译字段的细粒度控制。

🟠

Sanity + PolyLingo

Sanity的文档国际化插件为每个语言环境创建链接的文档变体。下面的脚本获取英文基础文档,并自动为每个目标语言创建翻译变体。

支持文档级i18n模式(每个语言一个文档)和字段级模式(所有语言在一个文档中)。字段级模式请循环字段而非文档。

scripts/translate-sanity.mjs
// 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管理API获取英文条目,翻译后直接写入语言特定字段——无需手动复制粘贴。

Contentful使用BCP 47语言代码(例如es-ES而非es)。请相应映射PolyLingo的ISO 639-1代码到您的Contentful语言环境配置。

scripts/translate-contentful.mjs
// 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

Webflow的本地化API(CMS和商务计划可用)支持语言特定字段内容。下面的脚本获取CMS集合项,翻译HTML正文字段,并通过Webflow v2 API写回每个语言变体。

Webflow将富文本字段存储为HTML。PolyLingo的HTML翻译保留所有Webflow生成的标记——自定义类、属性和嵌入元素——不受影响。

scripts/translate-webflow.mjs
// 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为无头CMS用户带来的功能

  • Sanity — 通过Webhook在发布时翻译,写回文档语言环境
  • Contentful — 英文语言环境更新时自动翻译条目
  • Webflow — 通过API翻译CMS集合项
  • 任何带API的无头CMS — 集成模式相同
  • 富文本、Markdown和HTML均正确保留
  • 一次请求支持全部36种语言 — 无需逐语言调用
  • 支持任何带管理API的CMS
  • 每次发布都可重新翻译内容——无需手动同步

标准多语言CMS工作流程

1

用源语言撰写内容

用英文(或您的源语言)创建并发布内容。您的CMS将其存储为权威版本。您无需更改编辑工作流程。

2

触发翻译脚本

手动运行脚本、定时运行,或通过CMS内容发布事件触发的Webhook运行。脚本每个文档调用PolyLingo一次,传入所有目标语言,然后一次性写回所有翻译。

3

部署——翻译内容上线

您的前端照常从CMS读取语言特定内容。无需更改前端代码。翻译内容会在对应语言路由正确显示。

适用对象

✍️

Sanity或Contentful的内容团队

您的编辑人员用英文发布。翻译内容自动出现在所有语言环境,无需编辑团队使用翻译工具。

🏢

构建多语言网站的代理机构

您构建的每个客户网站都需要多语言支持。PolyLingo为您提供可复用、可计费的集成,适用于您技术栈中的任何无头CMS。

🌍

拥有本地化产品内容的电商

产品描述、分类页面和博客内容——发布时自动翻译。结合语言特定定价,提供完整本地化购物体验。

关于无头CMS多语言的常见问题

PolyLingo支持这里未列出的CMS吗?

支持。任何带管理API的CMS都可以用相同模式集成——获取内容,调用PolyLingo,写回。Prismic、Storyblok、DatoCMS、Strapi、Ghost和Directus都有管理API,适用此方法。上面Sanity、Contentful和Webflow的集成示例说明了该模式。

我可以翻译带嵌入图片和链接的富文本吗?

可以。HTML翻译保留所有嵌入元素,包括图片(正确处理src和alt属性)、链接(保留href,翻译链接文本)和iframe。唯一例外是明确标记为不翻译的内容——例如代码块永不翻译。

如何处理不应翻译的内容?

对于带有不可翻译字段(slug、日期、技术标识符)的结构化内容,只发送需要翻译的字段。对于富文本中混合可翻译和不可翻译部分,使用HTML格式——PolyLingo会自动翻译文本内容,同时保留代码块和其他结构元素。

如果我的CMS有嵌套内容类型怎么办?

对于深度嵌套内容(文档引用其他文档),请独立翻译每种文档类型。这样避免循环引用,并让您清晰控制翻译内容。文档间引用由CMS维护——PolyLingo只处理字段内容,不触及文档关系。

源内容变更时如何保持翻译同步?

推荐模式是在每次发布事件通过CMS webhook触发翻译脚本。确保源内容变更时翻译内容同步更新。对于更新频率较低的内容,夜间定时运行脚本或每次生产部署前运行同样有效。

有没有办法标记翻译为“需要审核”而非自动发布?

这取决于您的CMS。Contentful和Sanity都支持草稿状态——您可以将翻译内容写为草稿而非发布,允许人工审核后再上线。上面脚本示例使用立即发布;您可修改最后一步改为创建草稿,实现审核流程。

今天就为您的无头CMS添加多语言支持。

免费套餐。每月50,000个令牌。无需信用卡。

免费开始翻译

免费套餐——每月50,000令牌。支持任何CMS。

无头CMS的多语言支持 — Sanity、Contentful及更多 — PolyLingo | PolyLingo