Vous faites l’i18n Next.js de la mauvaise façon
L’internationalisation en JavaScript a convergé vers une convention bancale : extraire chaque chaîne visible par l’utilisateur dans un fichier JSON, lui attribuer une clé, puis référencer cette clé dans vos composants. t('home.hero.title') au lieu du texte lui‑même. Votre UI vit à un endroit, votre contenu à un autre.
Ça marche. Des milliers d’applications sont mises en production de cette façon. Mais l’expérience développeur n’est pas excellente.
Lire t('checkout.summary.total') lors d’une revue de code ne vous dit rien — vous devez ouvrir un fichier JSON pour voir ce qui a changé. Il faut inventer les clés, les structurer en espaces de noms, et les garder synchronisées. Des traductions obsolètes s’accumulent parce que personne ne sait vraiment quelles clés sont encore utilisées. Le problème est suffisamment répandu pour qu’il existe des catégories entières d’outils dédiés à le gérer : des extensions d’IDE qui suggèrent automatiquement des clés, des générateurs de types qui les valident, des linters qui signalent celles qui ne sont plus utilisées. Ces outils résolvent un problème créé par un paradigme mal conçu.
Le composant <T>
Le contenu ne devrait pas être séparé de l’endroit où il est utilisé. Un composant qui affiche un titre, un paragraphe et un bouton devrait être l’unique source de vérité pour ce que ces éléments affichent — pas un proxy qui pointe vers des chaînes stockées ailleurs. Quand votre code et vos traductions sont deux systèmes parallèles, ils finissent par diverger. Inévitablement.
Et si la bibliothèque fonctionnait dans l’autre sens — en s’adaptant à votre code plutôt qu’en vous demandant de le restructurer ? Voici à quoi i18n devrait ressembler.
import { T } from 'gt-next';
function Hero() {
return (
<T>
<h1>Ship your product worldwide</h1>
<p>Reach every market without rewriting your app.</p>
</T>
);
}Entourez votre JSX avec <T>. Le texte anglais reste exactement là où vous l’avez écrit. Quand un utilisateur visite le site en espagnol ou en japonais, le contenu à l’intérieur de <T> est traduit — structure, mise en forme, tout compris.
Pas de clés. Pas de fichiers JSON. Pas de références croisées. Votre code est la source de vérité.
Configuration
La syntaxe ci‑dessus provient de gt-next, une bibliothèque i18n open source pour Next.js App Router. Pour commencer, il suffit d’exécuter une seule commande :
npx gtx-cli@latest initL’assistant de configuration installe les dépendances, encapsule votre configuration Next.js avec withGTConfig, ajoute GTProvider à votre layout racine, crée un gt.config.json avec vos locales, configure des clés d’API de développement pour le rechargement à chaud des traductions et configure le stockage des traductions sur un réseau de diffusion de contenu (CDN) — le tout de manière interactive.
Une fois cela fait, encapsulez le contenu dans <T>, lancez votre serveur de développement et utilisez le composant <LocaleSelector> pour basculer entre les langues :
import { LocaleSelector } from 'gt-next';
function Header() {
return (
<header>
<nav>{/* ... */}</nav>
<LocaleSelector />
</header>
);
}Les traductions sont générées à la demande en environnement de développement, ce qui vous permet d’afficher immédiatement votre application dans n’importe quelle langue.
Déploiement
En production, les traductions sont pré‑générées.
-
Obtenez une clé d’API de production sur dash.generaltranslation.com. Les clés de production commencent par
gtx-api-(différentes des clésgtx-dev-utilisées en local). -
Ajoutez l’étape de traduction à votre build :
{
"scripts": {
"build": "npx gtx-cli translate --publish && next build"
}
}La commande translate analyse l’ensemble de votre code pour toutes les utilisations de <T>, génère les traductions et les publie sur un CDN (Content Delivery Network, réseau de diffusion de contenu). Au moment du build de votre application, toutes les locales sont prêtes.
Prochaines étapes
- Composants de variables — gérez le contenu dynamique à l’intérieur de
<T>avec<Var>,<Num>et<Currency> - Composants conditionnels — affichez du contenu de manière conditionnelle en fonction de la locale avec
<Plural>et<Branch> useGTetgetGT— traduisez des chaînes simples pour les attributs, les espaces réservés (placeholders) et les métadonnées- Mode autonome — utilisez gt-next sans la plateforme General Translation