
PolyLingoでNext.jsアプリを30分以内に翻訳する方法
By Robert
PolyLingoで30分以内にNext.jsアプリを翻訳する方法
このチュートリアルの終わりには、動作する多言語対応のNext.js App Routerプロジェクトが完成しています。文字列はmessages/en.jsonに抽出され、必要なすべての言語の翻訳済みロケールファイルが用意され、next-intlがルートごとに適切なファイルを提供し、コンテンツが変更されるたびに再実行できる単一のNodeスクリプトがあります。
翻訳プラットフォームへの登録は不要です。言語ごとの固定料金もありません。1回のAPIコールで全てのターゲット言語を一括処理します。
必要なもの:
- App Routerを使用したNext.jsプロジェクト(Next.js 14または15)
- Node.js 18以降
- 無料のPolyLingoアカウントとAPIキー
ステップ1: PolyLingo APIキーを取得する(5分)
usepolylingo.comで無料アカウントを作成します。無料プランでは月に100,000トークンが含まれており、中規模のロケールファイルを10言語以上に何度も翻訳するのに十分です。
ログインしたら、ダッシュボードのAPI keysに移動してキーを作成します。キーの完全な値は一度しか表示されないため、すぐにコピーしてください。
プロジェクトの環境変数として追加します。バージョン管理にコミットしたり、クライアント側コードで公開しないでください:
# .env.local
POLYLINGO_API_KEY="pl_your_key_here"
APIが利用可能かどうかを確認します:
curl -sS "https://api.usepolylingo.com/v1/health"
"status": "ok"を含む小さなJSONペイロードが返ってくるはずです。
ステップ2: next-intlをインストールしてルーティングを設定する(10分)
ライブラリをインストールします:
npm install next-intl
プロジェクトルートにi18n.tsファイルを作成します。これはnext-intlにサポートするロケールと、各リクエストに対して正しいメッセージファイルを読み込む方法を伝えます:
// i18n.ts
import { getRequestConfig } from 'next-intl/server'
export const locales = ['en', 'de', 'fr'] as const
export type Locale = (typeof locales)[number]
export const defaultLocale: Locale = 'en'
export default getRequestConfig(async ({ requestLocale }) => {
let locale = await requestLocale
if (!locale || !locales.includes(locale as Locale)) {
locale = defaultLocale
}
return {
locale,
messages: (await import(`./messages/${locale}.json`)).default,
}
})
ミドルウェアを追加してルートにロケールのプレフィックスを付けます:
// middleware.ts
import createMiddleware from 'next-intl/middleware'
import { locales, defaultLocale } from './i18n'
export default createMiddleware({
locales: [...locales],
defaultLocale,
localePrefix: 'as-needed',
})
export const config = {
matcher: ['/((?!api|_next|.*\\..*).*)'],
}
ページファイルをapp/[locale]/の下に移動します。ルートレイアウトを更新してlocaleパラメータを受け取り、子要素をNextIntlClientProviderでラップします:
// app/[locale]/layout.tsx
import { NextIntlClientProvider } from 'next-intl'
import { getMessages } from 'next-intl/server'
export default async function LocaleLayout({
children,
params,
}: {
children: React.ReactNode
params: Promise<{ locale: string }>
}) {
const { locale } = await params
const messages = await getMessages()
return (
<html lang={locale}>
<body>
<NextIntlClientProvider messages={messages}>
{children}
</NextIntlClientProvider>
</body>
</html>
)
}
ステップ3: 文字列をJSONメッセージファイルに抽出する(10分)
プロジェクトルートにmessages/フォルダを作成します。en.jsonファイルにソース文字列を追加します。next-intlはネストされたキー構造を使用します:
{
"Home": {
"title": "Welcome",
"cta": "Get started"
}
}
ページを更新して、ハードコードされた文字列の代わりにuseTranslationsを使います:
// app/[locale]/page.tsx
import { useTranslations } from 'next-intl'
export default function HomePage() {
const t = useTranslations('Home')
return (
<main>
<h1>{t('title')}</h1>
<button type="button">{t('cta')}</button>
</main>
)
}
次に翻訳スクリプトを書きます。これはmessages/en.jsonを読み込み、format: "json"を指定してPolyLingo APIに送信し、ターゲットロケールごとに1つの出力ファイルを書き出します。format: "json"フラグはAPIにキー構造を保持し、文字列値のみを翻訳するよう指示します。ネストされたキー、配列、非文字列型はそのまま返されます。
// scripts/translate-messages.mjs
// 実行コマンド: node scripts/translate-messages.mjs
import fs from 'node:fs'
import path from 'node:path'
const API_KEY = process.env.POLYLINGO_API_KEY
const API_URL = (process.env.POLYLINGO_API_URL || 'https://api.usepolylingo.com/v1').replace(/\/$/, '')
const TARGETS = ['de', 'fr'] // 必要に応じてロケールを追加してください
const enPath = path.join('messages', 'en.json')
const en = JSON.parse(fs.readFileSync(enPath, 'utf8'))
const res = await fetch(`${API_URL}/translate`, {
method: 'POST',
headers: {
Authorization: `Bearer ${API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
content: JSON.stringify(en),
format: 'json',
targets: TARGETS,
model: 'standard',
}),
})
if (!res.ok) {
const err = await res.text()
throw new Error(`PolyLingo ${res.status}: ${err}`)
}
const { translations } = await res.json()
for (const locale of TARGETS) {
const out = path.join('messages', `${locale}.json`)
fs.writeFileSync(out, JSON.stringify(JSON.parse(translations[locale]), null, 2) + '\n')
console.log('Wrote', out)
}
実行します:
node scripts/translate-messages.mjs
以下のような出力が表示されます:
Wrote messages/de.json
Wrote messages/fr.json
これらのファイルを開いて確認してください。キーはen.jsonと同一で、文字列の値だけが翻訳されています。
ステップ4: ルートの動作確認(5分)
開発サーバーを起動します:
npm run dev
http://localhost:3000とhttp://localhost:3000/deにアクセスします。見出しとボタンがそれぞれ英語とドイツ語で表示されるはずです。スクリプトのTARGETS配列とi18n.tsのlocales配列にロケールを追加し、スクリプトを再実行してさらに多くの言語を追加できます。
PolyLingoダッシュボードのUsageでトークン使用量を確認してください。小さなロケールファイルを2言語に翻訳した場合、月間付与トークンの数百トークンを使用した程度です。
次に進むには
ロケールを追加しましょう。 スクリプトはTARGETSにいくつエントリがあっても1回のリクエストで送信します。日本語、スペイン語、アラビア語を追加してもAPIコールは1回だけです。
CIに組み込みましょう。 GitHub ActionsのリポジトリシークレットにPOLYLINGO_API_KEYを追加し、ビルドパイプラインの一部としてスクリプトを実行します。en.jsonが変更されるたびにロケールファイルが自動的に同期されます。
他のフォーマットも翻訳しましょう。 同じスクリプトパターンはMarkdownドキュメントページ(format: "markdown")やHTMLメールテンプレート(format: "html")にも使えます。APIはすべてのケースで構造を保持します。
大規模プロジェクトにはバッチエンドポイントを使いましょう。 複数のJSONファイル(機能ごとに1つなど)がある場合、POST /translate/batchは最大100件のアイテムを1回のリクエストで受け付け、それぞれにidとformatを指定できます。
無料で試す
PolyLingoの無料プランは月に100,000トークンが含まれています。クレジットカードは不要です。
curl -sS -X POST "https://api.usepolylingo.com/v1/translate" \
-H "Authorization: Bearer $POLYLINGO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "{\"Home\":{\"title\":\"Welcome\",\"cta\":\"Get started\"}}",
"format": "json",
"targets": ["de", "fr", "es", "ja"]
}'