
Comment traduire une application Next.js avec PolyLingo en moins de 30 minutes
By Robert
Comment traduire une application Next.js avec PolyLingo en moins de 30 minutes
À la fin de ce tutoriel, vous aurez un projet Next.js App Router multilingue fonctionnel : les chaînes extraites dans messages/en.json, des fichiers de locale traduits pour chaque langue dont vous avez besoin, next-intl servant le bon fichier par route, et un script Node unique que vous pouvez relancer chaque fois que votre contenu change.
Pas besoin de s'inscrire sur une plateforme de traduction. Pas de frais fixes par langue. Un seul appel API gère toutes vos langues cibles en une fois.
Ce dont vous aurez besoin :
- Un projet Next.js utilisant App Router (Next.js 14 ou 15)
- Node.js 18 ou plus récent
- Un compte PolyLingo gratuit et une clé API
Étape 1 : Obtenez votre clé API PolyLingo (5 minutes)
Créez un compte gratuit sur usepolylingo.com. Le niveau gratuit inclut 100 000 tokens par mois, ce qui suffit à traduire un fichier de locale de taille moyenne en plus de 10 langues plusieurs fois.
Une fois connecté, allez dans API keys sur le tableau de bord et créez une clé. Vous ne verrez la valeur complète qu'une seule fois, copiez-la immédiatement.
Ajoutez-la à votre projet en tant que variable d'environnement. Ne la commettez jamais dans le contrôle de version et ne l'exposez jamais dans le code côté client :
# .env.local
POLYLINGO_API_KEY="pl_your_key_here"
Vérifiez que l'API est accessible avant de continuer :
curl -sS "https://api.usepolylingo.com/v1/health"
Vous devriez recevoir un petit payload JSON avec "status": "ok".
Étape 2 : Installez next-intl et configurez le routage (10 minutes)
Installez la bibliothèque :
npm install next-intl
Créez un fichier i18n.ts à la racine de votre projet. Cela indique à next-intl quelles locales vous supportez et comment charger le bon fichier de messages pour chaque requête :
// 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,
}
})
Ajoutez un middleware pour préfixer les routes avec la locale :
// 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|.*\\..*).*)'],
}
Déplacez vos fichiers de page sous app/[locale]/. Mettez à jour votre layout racine pour recevoir le paramètre locale et envelopper les enfants avec 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>
)
}
Étape 3 : Extrayez vos chaînes dans un fichier JSON de messages (10 minutes)
Créez un dossier messages/ à la racine de votre projet. Ajoutez un fichier en.json avec vos chaînes sources. next-intl utilise une structure de clés imbriquées :
{
"Home": {
"title": "Welcome",
"cta": "Get started"
}
}
Mettez à jour vos pages pour utiliser useTranslations au lieu de chaînes codées en dur :
// 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>
)
}
Écrivez maintenant le script de traduction. Il lit messages/en.json, l'envoie à l'API PolyLingo avec format: "json", et écrit un fichier de sortie par locale cible. Le flag format: "json" indique à l'API de préserver la structure des clés et de ne traduire que les valeurs de chaîne — les clés imbriquées, tableaux et types non chaîne restent inchangés.
// scripts/translate-messages.mjs
// Exécutez avec : 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'] // étendez ce tableau pour ajouter plus de locales
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)
}
Exécutez-le :
node scripts/translate-messages.mjs
Vous devriez voir une sortie comme :
Wrote messages/de.json
Wrote messages/fr.json
Ouvrez ces fichiers et vérifiez-les. Vos clés seront identiques à celles de en.json. Seules les valeurs de chaîne auront changé.
Étape 4 : Testez rapidement les routes (5 minutes)
Démarrez votre serveur de développement :
npm run dev
Visitez http://localhost:3000 et http://localhost:3000/de. Le titre et le bouton devraient s'afficher en anglais et en allemand respectivement. Ajoutez plus de locales en étendant le tableau TARGETS dans le script et le tableau locales dans i18n.ts, puis relancez le script.
Vérifiez votre utilisation des tokens dans le tableau de bord PolyLingo sous Usage. Pour un petit fichier de locale traduit en deux langues, vous aurez utilisé quelques centaines de tokens sur votre quota mensuel.
Où aller à partir d'ici
Ajoutez plus de locales. Le script envoie une seule requête quel que soit le nombre d’entrées dans TARGETS. Ajouter le japonais, l’espagnol et l’arabe coûte un seul appel API, pas trois.
Intégrez-le dans CI. Ajoutez POLYLINGO_API_KEY comme secret de dépôt dans GitHub Actions et exécutez le script dans votre pipeline de build. Vos fichiers de locale restent synchronisés automatiquement chaque fois que en.json change.
Traduisez d’autres formats. Le même modèle de script fonctionne pour les pages de documentation Markdown (format: "markdown") et les modèles d’e-mails HTML (format: "html"). L’API préserve la structure dans tous les cas.
Utilisez le point de terminaison batch pour les projets plus importants. Si vous avez plusieurs fichiers JSON séparés (un par zone fonctionnelle, par exemple), POST /translate/batch accepte jusqu’à 100 éléments dans une seule requête, chacun avec son propre id et format.
Essayez gratuitement
Le niveau gratuit de PolyLingo inclut 100 000 tokens par mois. Pas de carte de crédit requise.
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"]
}'