返回博客
Terminal output showing a translation script writing de.json and fr.json, alongside a folder tree and a browser rendering the German locale route.

如何在30分钟内使用PolyLingo翻译Next.js应用

By Robert

如何在30分钟内使用 PolyLingo 翻译 Next.js 应用

在本教程结束时,你将拥有一个可用的多语言 Next.js App Router 项目:字符串提取到 messages/en.json,为你需要的每种语言生成翻译后的本地化文件,next-intl 根据路由提供正确的文件,以及一个可以在内容更改时重新运行的单一 Node 脚本。

无需注册翻译平台。无每语言固定费用。一次 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,将其发送到 PolyLingo API,使用 format: "json",并为每个目标语言写入一个输出文件。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:3000http://localhost:3000/de。标题和按钮应分别以英语和德语显示。通过扩展脚本中的 TARGETS 数组和 i18n.ts 中的 locales 数组添加更多语言,然后重新运行脚本。

在 PolyLingo 仪表盘的 Usage 中检查你的令牌使用情况。对于一个小的本地化文件翻译成两种语言,你将使用几百个令牌,远低于每月额度。


后续步骤

添加更多语言。 脚本无论 TARGETS 中有多少条目,都只发送一次请求。添加日语、西班牙语和阿拉伯语只需一次 API 调用,而非三次。

集成到 CI。 在 GitHub Actions 中将 POLYLINGO_API_KEY 作为仓库密钥添加,并在构建流水线中运行脚本。每当 en.json 变化时,本地化文件会自动保持同步。

翻译其他格式。 同样的脚本模式适用于 Markdown 文档页面(format: "markdown")和 HTML 邮件模板(format: "html")。API 会保留所有结构。

大型项目使用批量端点。 如果你有多个独立的 JSON 文件(例如每个功能区一个),POST /translate/batch 支持一次请求最多 100 个条目,每个条目有自己的 idformat


免费试用

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"]
  }'

获取你的 API 密钥