
Como traduzir um aplicativo Next.js com PolyLingo em menos de 30 minutos
By Robert
Como traduzir um app Next.js com PolyLingo em menos de 30 minutos
Ao final deste tutorial, você terá um projeto Next.js App Router multilíngue funcionando: strings extraídas em messages/en.json, arquivos de localidade traduzidos para todos os idiomas que você precisar, next-intl servindo o arquivo correto por rota, e um único script Node que você pode executar novamente sempre que seu conteúdo mudar.
Nenhuma plataforma de tradução para se cadastrar. Nenhuma taxa fixa por idioma. Uma chamada de API lida com todos os seus idiomas de destino de uma vez.
O que você vai precisar:
- Um projeto Next.js usando o App Router (Next.js 14 ou 15)
- Node.js 18 ou superior
- Uma conta gratuita PolyLingo e chave de API
Passo 1: Obtenha sua chave de API PolyLingo (5 minutos)
Crie uma conta gratuita em usepolylingo.com. O plano gratuito inclui 100.000 tokens por mês, o que é suficiente para traduzir um arquivo de localidade de tamanho médio para mais de 10 idiomas várias vezes.
Depois de entrar, vá para API keys no painel e crie uma chave. Você verá o valor completo apenas uma vez, então copie imediatamente.
Adicione-a ao seu projeto como uma variável de ambiente. Nunca a comite no controle de versão e nunca a exponha no código do lado cliente:
# .env.local
POLYLINGO_API_KEY="pl_your_key_here"
Verifique se a API está acessível antes de continuar:
curl -sS "https://api.usepolylingo.com/v1/health"
Você deve receber um pequeno payload JSON com "status": "ok".
Passo 2: Instale next-intl e configure o roteamento (10 minutos)
Instale a biblioteca:
npm install next-intl
Crie um arquivo i18n.ts na raiz do seu projeto. Isso informa ao next-intl quais locais você suporta e como carregar o arquivo de mensagens correto para cada requisição:
// 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,
}
})
Adicione middleware para prefixar rotas com o local:
// 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|.*\\..*).*)'],
}
Mova seus arquivos de página para app/[locale]/. Atualize seu layout raiz para receber o parâmetro locale e envolver os filhos com 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>
)
}
Passo 3: Extraia suas strings para um arquivo JSON de mensagens (10 minutos)
Crie uma pasta messages/ na raiz do seu projeto. Adicione um arquivo en.json com suas strings fonte. next-intl usa uma estrutura de chave aninhada:
{
"Home": {
"title": "Welcome",
"cta": "Get started"
}
}
Atualize suas páginas para usar useTranslations em vez de strings codificadas:
// 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>
)
}
Agora escreva o script de tradução. Ele lê messages/en.json, envia para a API PolyLingo com format: "json", e escreve um arquivo de saída por local de destino. A flag format: "json" informa à API para preservar a estrutura das chaves e traduzir apenas os valores string — chaves aninhadas, arrays e tipos não string permanecem intactos.
// scripts/translate-messages.mjs
// Execute com: 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'] // estenda este array para adicionar mais locais
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)
}
Execute:
node scripts/translate-messages.mjs
Você deve ver uma saída como:
Wrote messages/de.json
Wrote messages/fr.json
Abra esses arquivos e verifique. Suas chaves serão idênticas às de en.json. Apenas os valores string terão mudado.
Passo 4: Teste rápido das rotas (5 minutos)
Inicie seu servidor de desenvolvimento:
npm run dev
Visite http://localhost:3000 e http://localhost:3000/de. O título e o botão devem aparecer em inglês e alemão, respectivamente. Adicione mais locais estendendo o array TARGETS no script e o array locales em i18n.ts, depois execute o script novamente.
Verifique o uso dos seus tokens no painel PolyLingo em Usage. Para um arquivo de localidade pequeno traduzido em dois idiomas, você terá usado algumas centenas de tokens do seu limite mensal.
Para onde ir a partir daqui
Adicione mais locais. O script envia uma única requisição independentemente de quantas entradas existam em TARGETS. Adicionar japonês, espanhol e árabe custa uma chamada de API, não três.
Integre ao CI. Adicione POLYLINGO_API_KEY como um segredo do repositório no GitHub Actions e execute o script como parte do pipeline de build. Seus arquivos de localidade ficam sincronizados automaticamente sempre que en.json mudar.
Traduza outros formatos. O mesmo padrão de script funciona para páginas de documentação Markdown (format: "markdown") e templates de email HTML (format: "html"). A API preserva a estrutura em todos os casos.
Use o endpoint batch para projetos maiores. Se você tiver múltiplos arquivos JSON separados (um por área de funcionalidade, por exemplo), POST /translate/batch aceita até 100 itens em uma única requisição, cada um com seu próprio id e format.
Experimente grátis
O plano gratuito do PolyLingo inclui 100.000 tokens por mês. Não é necessário cartão de crédito.
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"]
}'