ヘッドレスCMSの多言語対応。
PolylangはWordPressサイトに完全な多言語ワークフローを提供しました。PolyLingoはそのワークフローをSanity、Contentful、Webflow、Framer、その他すべてのヘッドレスCMSに、午後のうちに統合できるREST APIを通じてもたらします。
ヘッドレスCMSの多言語対応は未解決の問題です。
Sanityには国際化プラグインがあります。Contentfulにはロケールがあります。しかしどちらもコンテンツを翻訳するのではなく、単に複数言語で保存しているだけです。その言語スロットを埋める作業は依然として手動です。英語のコンテンツをエクスポートし、リッチテキストやJSON構造を壊す翻訳ツールにかけ、出力を修正し、再インポートし、すべての言語で繰り返す。頻繁に公開する活発なコンテンツチームにとって、このワークフローはスケールしません。また、多くの小規模セットアップでは存在しないため、コンテンツはまったく翻訳されないままです。
ヘッドレスCMSのアーキテクチャはコンテンツ管理と配信を分離しています。これは柔軟性に優れていますが、ギャップも生みます。CMSは言語バリアントを保存しますが、そのバリアントに翻訳コンテンツを埋めるものがありません。そのレイヤーは自分で構築する必要があります。
ほとんどのチームは2つの状況に陥ります。DeepLにコピー&ペーストして手動翻訳(遅くてエラーが多くスケールしない)、または翻訳APIとのカスタム統合を作り永続的に保守する。どちらも良い解決策ではありません。PolyLingoはクリーンな第三の選択肢です。
PolyLingoはあなたのCMSに欠けている翻訳レイヤーです。
PolyLingoはCMSの公開ワークフローに直接統合されます。コンテンツ公開時に発火するWebhookを設定し、コンテンツをPolyLingoに渡し、すべての言語の翻訳版を受け取り、CMSに書き戻します。Sanityではサーバーアクションの数行、ContentfulではWebhookハンドラー、カスタムセットアップではHTTPコールです。翻訳モデルはMarkdown、HTML、JSON、リッチテキストなどのコンテンツフォーマットを理解し、構造を保持します。
パターンはすべてのCMSで一貫しています。ソース言語のコンテンツを取得し、すべての対象言語でPolyLingo APIを呼び出し、管理API経由で翻訳コンテンツをCMSに書き戻す。これはビルド時スクリプト、CIジョブ、Webhookハンドラーとして実行可能で、ワークフローに合わせて選べます。
PolyLingoはMarkdown、HTML、プレーンテキストを扱うため、CMSがリッチコンテンツに使うフォーマットに対応します。構造化フィールド(見出し、本文、抜粋)は個別に翻訳でき、どのフィールドを翻訳するか細かく制御可能です。
Sanity + PolyLingo
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管理APIを使い英語エントリーを取得、翻訳し、翻訳済みコンテンツをロケール固有フィールドに直接書き込みます。手動のコピー&ペーストは不要です。
ContentfulはBCP 47ロケールコード(例:es-ES)を使います。PolyLingoのISO 639-1コードを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
WebflowのLocalization API(CMSおよびビジネスプランで利用可能)はロケール固有のフィールドコンテンツをサポートします。以下のスクリプトはCMSコレクションアイテムを取得し、HTML本文フィールドを翻訳し、Webflow v2 API経由で各ロケールバリアントに書き戻します。
WebflowはリッチテキストフィールドをHTMLとして保存します。PolyLingoのHTML翻訳は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がヘッドレスCMSユーザーに提供するもの
- ✓Sanity — 公開時にWebhook経由で翻訳し、ドキュメントのロケールに書き戻す
- ✓Contentful — 英語ロケール更新時にエントリーを自動翻訳
- ✓Webflow — API経由でCMSコレクションアイテムを翻訳
- ✓APIを持つあらゆるヘッドレスCMS — 統合パターンは同じ
- ✓リッチテキスト、Markdown、HTMLをすべて正しく保持
- ✓36言語すべてを一度のリクエストで — 言語ごとの呼び出し不要
- ✓管理APIを持つあらゆるCMSに対応
- ✓公開ごとに再翻訳可能 — 手動同期不要
標準的な多言語CMSワークフロー
ソース言語でコンテンツを書く
英語(またはソース言語)でコンテンツを作成・公開します。CMSはこれを権威あるバージョンとして保存します。編集ワークフローを変更する必要はありません。
翻訳スクリプトを起動する
スクリプトを手動、スケジュール、またはCMSの公開イベントでトリガーされるWebhook経由で実行します。スクリプトはドキュメントごとに一度PolyLingoを呼び出し、すべての対象言語の翻訳を取得し、一括でCMSに書き戻します。
デプロイ — 翻訳済みコンテンツが公開される
フロントエンドは通常通りCMSからロケール固有のコンテンツを読み込みます。フロントエンドコードの変更は不要です。翻訳コンテンツは各ロケールルートで正しい言語で表示されます。
対象ユーザー
SanityやContentfulのコンテンツチーム
編集者は英語で公開します。翻訳コンテンツは編集チームが翻訳ツールに触れることなく自動的にすべてのロケールに表示されます。
多言語サイトを構築する代理店
すべてのクライアントサイトに多言語対応が必要です。PolyLingoはあらゆるヘッドレスCMSで使える再利用可能で請求可能な統合を提供します。
ローカライズされた商品コンテンツを持つEコマース
商品説明、カテゴリーページ、ブログコンテンツが公開時に自動翻訳されます。ロケール固有の価格設定と組み合わせて完全にローカライズされたショッピング体験を提供します。
ヘッドレスCMS多言語に関するよくある質問
PolyLingoはここにないCMSでも使えますか?
はい。管理APIを持つCMSなら同じパターンで統合可能です。コンテンツ取得、PolyLingo呼び出し、書き戻し。Prismic、Storyblok、DatoCMS、Strapi、Ghost、Directusも管理APIを持ち、この方法で動作します。上記のSanity、Contentful、Webflowの統合例がパターンを示しています。
埋め込み画像やリンクを含むリッチテキストも翻訳できますか?
はい。HTML翻訳は画像(srcとalt属性を正しく処理)、リンク(href保持、リンクテキスト翻訳)、iframeなどすべての埋め込み要素を保持します。非翻訳指定されたコンテンツ(例:コードブロック)は翻訳されません。
翻訳すべきでないコンテンツはどう扱いますか?
非翻訳フィールド(スラッグ、日付、技術的識別子)を持つ構造化コンテンツの場合、翻訳したいフィールドだけを送信してください。翻訳可能と非翻訳部分が混在するリッチテキストはHTML形式を使い、PolyLingoがコードブロックなどの構造要素を保持しつつテキストを翻訳します。
CMSにネストされたコンテンツタイプがある場合は?
深くネストされたコンテンツ(他ドキュメントへの参照を含む)はドキュメントタイプごとに独立して翻訳してください。循環参照を避け、翻訳対象を明確に制御できます。ドキュメント間の参照はCMSが管理し、PolyLingoはフィールドコンテンツのみを扱います。
ソースコンテンツが変わったとき翻訳を同期するには?
推奨パターンはCMSのWebhookで公開イベントごとに翻訳スクリプトをトリガーすることです。これによりソース変更時に翻訳が更新されます。更新頻度が低い場合は夜間スケジュールや本番デプロイ前の実行も有効です。
翻訳を自動公開ではなく「レビューが必要」とマークする方法は?
CMSによります。ContentfulとSanityはドラフト状態をサポートし、翻訳コンテンツを公開ではなくドラフトとして書き込み、各ロケールの公開前に人間のレビューを可能にします。上記スクリプト例は即時公開ですが、最終ステップをドラフト作成に変更すればレビュー用ワークフローになります。