Posez votre question et obtenez un résumé du document en referencant cette page et le Provider AI de votre choix
Le contenu de cette page a été traduit à l'aide d'une IA.
Voir la dernière version du contenu original en anglaisSi vous avez une idée d’amélioration pour améliorer cette documentation, n’hésitez pas à contribuer en submitant une pull request sur GitHub.
Lien GitHub de la documentationCopier le Markdown du doc dans le presse-papiers
i18next VS Intlayer: Benchmark d'internationalisation (i18n) React & Next.js

i18next est le framework d'i18n le plus utilisé de l'écosystème JavaScript. À travers react-i18next et next-i18next, il alimente une grande partie des applications React et Next.js. Intlayer est une alternative basée sur un compilateur, découpée par composant.
Cet article les compare sur des mesures concrètes plutôt que sur des listes de fonctionnalités. Les chiffres proviennent de Benchmark Bloom, une suite open source qui compile la même application avec chaque bibliothèque et enregistre ce que le navigateur télécharge réellement.
tl;dr:i18nextest le runtime le plus lourd du benchmark: +77 KB gzip par page sur Next.js dans la configuration naïve, +22 KB après l'optimisation complète par namespaces + lazy loading. Intlayer n'ajoute que +0.3 KB. Chaque configuration d'i18next en dehors de celle entièrement compartimentée (scoped) envoie ~90% des chaînes des pages distantes; Intlayer n'envoie 0% par défaut. Changer de langue avec un backend chargé à la demande prend 123 à 185 ms avecreact-i18nextcontre 3 à 4 ms avec Intlayer. L'adaptateur@intlayer/next-i18nextconserve l'API d'i18next et atteint 150.7 KB par page contre 218.5 KB pour l'original.
En résumé
- i18next / react-i18next / next-i18next - Mature, riche en plugins, agnostique du framework. Namespaces, détecteurs de langue, backends, ICU via plugin,
<Trans>pour le contenu enrichi. Le contenu est centralisé danslocales/{lng}/{ns}.json. Puissant, mais chaque optimisation (découpage des namespaces, chargement par page, sécurité des types) représente une configuration que vous devez maintenir. - Intlayer - Modèle centré sur les composants. Les dictionnaires
.content.tsse trouvent à côté du composant qu'ils desservent, un compilateur au build effectue le tree-shaking et les charge à la demande par composant et par locale, des types TypeScript stricts sont générés à partir de votre contenu, et les traductions manquantes provoquent des erreurs au build. Fournit middleware, helpers SEO, un Éditeur Visuel / CMS et la traduction assistée par IA.
Ouvrir le tableau dans une fenêtre modale pour voir tout le contenu clairement
Les badges se mettent à jour automatiquement. Les données évoluent au fil du temps.
Comparaison des fonctionnalités
Ouvrir le tableau dans une fenêtre modale pour voir tout le contenu clairement
| Fonctionnalité | Intlayer (react-intlayer / next-intlayer) | i18next (react-i18next / next-i18next) |
|---|---|---|
| Traductions proches des composants | ✅ Oui, .content.ts colocalisé avec chaque composant | ❌ Non, centralisé dans locales/{lng}/{ns}.json |
| Intégration TypeScript | ✅ Types stricts générés automatiquement à partir du contenu | ⚠️ Basique; clés strictes via extension CustomTypeOptions et typage ressources |
| Détection des traductions manquantes | ✅ Erreur TypeScript + erreur/avertissement au build | ⚠️ Fallback au runtime (saveMissing, écho de clé) |
| Contenu riche (JSX / Markdown / composants) | ✅ Support direct | ⚠️ <Trans> avec placeholders indexés |
| Support ICU | ⚠️ En cours | ⚠️ Via plugin (i18next-icu) |
| Pluralisation | ✅ Motifs basés sur les énumérations | ✅ Suffixes _one / _other (Intl.PluralRules) |
| Formatage (dates, nombres, devises) | ✅ useNumber, useDate, ... (Intl sous le capot) | ⚠️ Formateurs d'interpolation ou Intl.* manuel |
| Routage localisé et middleware | ✅ Proxy/middleware intégré, getMultilingualUrls | ⚠️ Non natif; middleware personnalisé ou tiers |
| Helpers SEO (hreflang, sitemap, robots) | ✅ Helpers intégrés | ❌ Manuel |
| Composants serveur synchrones | ✅ useIntlayer de next-intlayer/server utilisable dans tout composant serveur | ⚠️ getFixedT sur la page, puis t transmis en props |
| Tree-shaking (n'embarque que le contenu utile) | ✅ Par composant, par locale, automatisé par le compilateur | ⚠️ Manuel: namespaces + liste ns par page + backend |
| Lazy loading | ✅ importMode: 'dynamic' (une ligne de config) | ✅ Via plugins backend (i18next-resources-to-backend, i18next-http-backend) |
| Purger le contenu inutilisé | ✅ Dictionnaires orphelins supprimés au build | ❌ Non intégré |
| Test des traductions manquantes (CLI / CI) | ✅ npx intlayer content test | ⚠️ i18next-parser / outil tiers |
| Traduction assistée par IA | ✅ Intégrée, utilise vos propres clés d'API | ❌ Non (Locize est un service tiers payant) |
| Éditeur Visuel / CMS | ✅ Éditeur Visuel gratuit + CMS optionnel | ❌ Non (Locize / plateformes externes) |
| Serveur MCP et compétences d'agent (Skills) | ✅ Oui | ❌ Non |
| Écosystème / communauté | ⚠️ Plus récent mais en forte croissance | ✅ Le plus étendu et le plus mature |
Le benchmark
Ce qui a été mesuré
La suite Benchmark Bloom construit la même application avec chaque bibliothèque: 10 pages (accueil, à propos, blog, carrières, contact, FAQ, tarifs, produits, paramètres, équipe), 10 locales (en, fr, es, de, it, pt, zh, ja, ko, ru), des composants et un contenu identiques. Les pages sont mesurées en en et en fr. Chaque bibliothèque est testée sous un maximum de quatre stratégies de chargement, de la configuration naïve à l'optimale:
Ouvrir le tableau dans une fenêtre modale pour voir tout le contenu clairement
| Stratégie | Description | Qui fait cela |
|---|---|---|
| static | Toutes les locales et pages regroupées (resources inlinées dans init()) | Prototypes rapides, code généré par IA |
| dynamic | Seule la locale active est chargée via un backend, mais tous les namespaces à la fois | La majorité des projets |
| scoped-static | Un namespace par route, tous chargés en amont | Rare |
| scoped-dynamic | Un namespace par route + chargement dynamique via backend. Seulement la page et locale active | Applications avec un budget de perf strict |
Intlayer n'a pas de variante "scoped": le compilateur isole le contenu par composant automatiquement, ses lignes static et dynamic sont donc déjà découpées.
Pour chaque build, la suite enregistre:
- Lib size: taille gzip d'un composant vide qui n'importe que la bibliothèque i18n. Le coût fixe du runtime.
- Page JS: JavaScript gzip téléchargé par page, en moyenne sur l'ensemble des pages et locales.
- Locale leak %: part des chaînes traduites dans le JS téléchargé appartenant à une locale que l'utilisateur ne consulte pas (évalué sur
enetfr, donc 50% signifie "l'autre locale mesurée est entièrement présente"; avec 10 locales compilées, le gaspillage réel est bien supérieur). - Page leak %: part des chaînes traduites dans le JS téléchargé appartenant à une page sur laquelle l'utilisateur n'est pas.
- Component avg: taille gzip moyenne de chaque composant compilé isolément. Indique le poids du runtime i18n injecté dans chaque composant.
- E2E reactivity: temps réel entre la sélection d'une nouvelle locale et la mise à jour de
html[lang]dans le DOM (Playwright, 5 itérations). - Hydration: durée de la phase d'hydratation de React.
Les données ci-dessous proviennent de l'exécution du 2026-09-12 avecnext-i18next16.3.0,react-i18next17.0.13 etintlayer9.5.1. L'application de test est volontairement modeste (quelques dizaines de chaînes par locale), les pourcentages de fuite décrivent donc un comportement type: ils augmentent à mesure que votre contenu grandit tandis que le coût du runtime reste fixe.
Résultats sur Next.js (next-i18next)
Sélectionnez les métriques et les bibliothèques qui vous intéressent :
Métrique
Chargement JSON dynamique
Charge les traductions à la volée
JSON scopé (espaces de noms)
Espaces de noms de traduction par page
Quelle est cette métrique ?
La taille totale compressée en gzip du bundle de la bibliothèque d’internationalisation. Elle n’inclut que le fournisseur et la logique de récupération de contenu après tree-shaking et minification.
Pourquoi est-ce important ?
Une taille de bibliothèque plus petite réduit la charge utile JavaScript initiale, ce qui accélère le téléchargement et le temps d’exécution sur le client.
Voir comme
Ouvrir le tableau dans une fenêtre modale pour voir tout le contenu clairement
| Bibliothèque | Stratégie | Lib size (gz) | Page JS avg (gz) | Locale leak | Page leak | Component avg (gz) | Réactivité E2E | Hydratation |
|---|---|---|---|---|---|---|---|---|
| base (sans i18n) | - | 0.0 KB | 141.0 KB | 0.0% | 0.0% | 0.9 KB | 13.4 ms | 11.8 ms |
next-i18next | static | 19.7 KB | 218.5 KB | 0.0% | 89.8% | 78.5 KB | 16.4 ms | 15.6 ms |
next-i18next | dynamic | 19.7 KB | 169.5 KB | 50.0% | 89.8% | 26.1 KB | 15.4 ms | 27.7 ms |
next-i18next | scoped-static | 19.7 KB | 220.1 KB | 0.0% | 89.8% | 78.9 KB | 16.4 ms | 14.7 ms |
next-i18next | scoped-dynamic | 19.7 KB | 163.4 KB | 0.0% | 0.0% | 27.1 KB | 15.9 ms | 15.1 ms |
next-intlayer | static | 5.5 KB | 141.3 KB | 0.0% | 0.0% | 8.5 KB | 15.5 ms | 16.9 ms |
next-intlayer | dynamic | 5.5 KB | 141.3 KB | 0.0% | 0.0% | 6.9 KB | 15.3 ms | 15.9 ms |
@intlayer/next-i18next (compat) | static | 9.4 KB | 150.7 KB | 0.0% | 0.0% | 9.7 KB | 10.7 ms | 11.3 ms |
@intlayer/next-i18next (compat) | dynamic | 9.4 KB | 150.7 KB | 0.0% | 0.0% | 9.7 KB | 11.9 ms | 10.6 ms |
Comment interpréter ces données
- Coût du runtime. Le cœur d'i18next plus
react-i18nextreprésente le runtime le plus lourd: 19.7 KB gzip pour un composant vide, contre 5.5 KB pournext-intlayer. - La configuration naïve coûte cher. Inliner
resourcesdansinit()génère 218.5 KB par page, soit +77.5 KB par rapport à l'application de base. Chaque page embarque chaque namespace. - Optimiser demande beaucoup d'efforts. Passer à un backend (
dynamic) fait gagner 49 KB mais laisse fuiter 90% des chaînes des pages distantes et, dans cette configuration, la moitié des chaînes appartiennent à la mauvaise langue. Ajouter un découpage par namespace sur chaque route (scoped-dynamic) permet enfin d'atteindre 0% de fuite à 163.4 KB, ce qui reste +22.4 KB par page de plus qu'Intlayer à 141.3 KB, qui n'a nécessité aucune configuration spécifique. - Taille des composants. Un composant utilisant
useTranslation()pèse entre 26 et 79 KB selon la configuration; le même composant avecuseIntlayer()ne pèse que 6.9 KB. - L'hydratation monte à 27.7 ms dans la configuration
dynamic: l'instance i18next s'initialise et résout son backend côté client avant que React ne puisse hydrater la page.
Tableau complet, chaque bibliothèque et chaque stratégie, dans le rapport de benchmark Next.js.
Résultats sur TanStack Start (react-i18next)
La même application de test sur TanStack Start avec react-i18next pur, ce qui isole les dépendances propres à Next.js.
Ouvrir le tableau dans une fenêtre modale pour voir tout le contenu clairement
| Bibliothèque | Stratégie | Lib size (gz) | Page JS avg (gz) | Locale leak | Page leak | Component avg (gz) | Réactivité E2E | Hydratation |
|---|---|---|---|---|---|---|---|---|
| base (pas i18n) | - | 0.0 KB | 111.0 KB | 0.0% | 0.0% | 0.7 KB | 8.1 ms | 21.6 ms |
react-i18next | static | 18.4 KB | 180.3 KB | 50.0% | 89.8% | 24.3 KB | 12.9 ms | 85.1 ms |
react-i18next | dynamic | 18.4 KB | 136.4 KB | 23.1% | 89.8% | 24.8 KB | 123.1 ms | 32.9 ms |
react-i18next | scoped-static | 18.4 KB | 184.2 KB | 50.7% | 89.8% | 25.3 KB | 185.1 ms | 25.2 ms |
react-i18next | scoped-dynamic | 18.4 KB | 127.2 KB | 0.0% | 0.0% | 26.7 KB | 17.6 ms | 11.3 ms |
intlayer | static | 5.0 KB | 125.8 KB | 50.0% | 0.0% | 8.1 KB | 3.2 ms | 11.5 ms |
intlayer | dynamic | 5.0 KB | 118.6 KB | 0.0% | 0.0% | 6.3 KB | 3.6 ms | 14.1 ms |
Comment interpréter ces données
- L'application
react-i18nextnaïve envoie +69 KB par page de plus que l'application de base, et l'hydratation prend 85 ms (4 fois la base) parce que l'arbre complet des ressources est parsé et enregistré côté client avant le premier rendu. - Le changement de langue met en lumière la latence du lazy loading. Lorsque les ressources sont chargées à la demande via un backend, changer de langue nécessite un aller-retour réseau avant que
html[lang]ne se mette à jour: 123 ms endynamic, 185 ms enscoped-static. Intlayer met à jour le DOM en 3 à 4 ms dans les deux cas: le changement de langue est immédiat et ne dépend pas d'une requête réseau. - La configuration pleinement optimisée
scoped-dynamicatteint 0% de fuite à 127.2 KB, restant +8.6 KB au-dessus de la lignedynamicd'Intlayer, et a nécessité une correspondance routes-namespaces, un backend de ressources et une frontière Suspense par route pour y parvenir. - La ligne
staticd'Intlayer présente déjà 0% de fuite de page car seuls les dictionnaires importés par les composants de la page sont inclus dans le bundle. ActiverimportMode: 'dynamic'supprime également la fuite de locale. - Taille des composants: 24 à 27 KB par composant avec
react-i18nextcontre 6 à 8 KB avec Intlayer.useTranslation()lie chaque composant à l'instance globale d'i18next.
Tableau complet dans le rapport de benchmark TanStack Start.
Pourquoi un tel écart? Instance globale vs dictionnaires compilés

i18next a été pensé en 2012 comme un runtime: une instance globale conserve un dépôt de ressources, des plugins l'enrichissent, et t() résout les clés au rendu. C'est ce qui le rend si flexible (n'importe quel framework, backend ou format) et également ce qui le rend lourd:
Copier le code dans le presse-papiers
L'instance ne peut pas anticiper les clés qu'un composant demandera, elle conserve donc tous les namespaces que vous lui demandez de charger. Optimiser signifie que vous devez découper les catalogues en namespaces, vous devez lister les namespaces nécessaires à chaque page, et vous devez maintenir cette liste à jour quand les composants se déplacent.
La facture augmente sur deux axes à la fois, les pages et les locales :

Comme le soulignent les notes du benchmark: "maintenir la sécurité des types et savoir exactement quel namespace inclure sur quelle page est un cauchemar".
Intlayer élimine l'instance. Le contenu est déclaré à côté du composant, et le compilateur résout le graphe de dépendances au build:
Copier le code dans le presse-papiers
@intlayer/swc / @intlayer/babel identifie quel composant importe quel dictionnaire, n'embarque que ceux-ci, uniquement pour la locale active, et exclut ceux qui ne sont pas référencés. Le modèle "scoped-dynamic" devient le résultat direct du build plutôt qu'une discipline manuelle imposée à l'équipe.
Pour obtenir les chiffres de la lignedynamic, définissezdictionary.importMode: 'dynamic'dansintlayer.config.ts. Consultez la documentation sur l'optimisation de bundle.
Expérience développeur
Configuration
Copier le code dans le presse-papiers
Il faut y ajouter un I18nProvider côté client qui recrée l'instance avec les mêmes options, un generateStaticParams, et une liste de namespaces sur chaque page.
Copier le code dans le presse-papiers
Copier le code dans le presse-papiers
Composant client
Copier le code dans le presse-papiers
Copier le code dans le presse-papiers
La page affichant ce composant doit charger le namespaceabout, ett("counter.label")reste une simple chaîne de caractères non typée à moins d'étendreCustomTypeOptions.
Copier le code dans le presse-papiers
Copier le code dans le presse-papiers
label et increment sont strictement typés; une faute de frappe déclenche une erreur TypeScript, et une valeur française manquante génère une erreur au build.
Composant serveur synchrone
Copier le code dans le presse-papiers
La page appelle i18n.getFixedT(locale, "about") et fait descendre t et locale en tant que props.
Copier le code dans le presse-papiers
Gardez l'API d'i18next, profitez des performances d'Intlayer
Il n'est pas nécessaire de réécrire vos composants pour bénéficier des résultats du benchmark ci-dessus. @intlayer/i18next, @intlayer/react-i18next et @intlayer/next-i18next sont des adaptateurs prêts à l'emploi: useTranslation, t(), <Trans>, {{interpolation}}, pluriels _one / _other, suffixes de contexte et returnObjects continuent de fonctionner, alimentés par les dictionnaires Intlayer compilés.
Copier le code dans le presse-papiers
Copier le code dans le presse-papiers
Dans le benchmark, la version adaptée de la même application Next.js est passée de 218.5 KB à 150.7 KB par page, de 78.5 KB à 9.7 KB par composant, de ~90% de fuite de page à 0%, et d'une hydratation de 15.6 ms à 11.3 ms, sans modifier le code de l'application. Vos fichiers existants locales/{lng}/{ns}.json peuvent rester la source de vérité grâce au plugin de synchronisation JSON.
Consultez les guides de migration: i18next, react-i18next, next-i18next.
Quand choisir quelle solution?
Si vous avez besoin de son écosystème de plugins (détecteurs, backends, ICU, Locize), si vous traduisez aussi en dehors de React (services Node, vanilla JS, autres frameworks), si votre équipe le maîtrise déjà, ou si une plateforme de traduction externe exige locales/{lng}/{ns}.json. Prévoyez le temps de découper vos catalogues en namespaces, de configurer un backend et de maintenir la table routes-namespaces si la performance compte.
Vous voulez du contenu découpé par composant, un typage TypeScript strict, des erreurs au build en cas de clé manquante, du tree-shaking et lazy loading sans effort, un changement de langue instantané, des composants serveur synchrones et des outils éditoriaux intégrés (Éditeur Visuel, CMS, traduction IA, serveur MCP). Particulièrement pertinent pour les codebases modulaires et les design systems.
Vous utilisez déjà i18next et souhaitez obtenir les gains de bundle et de réactivité sans refactoriser vos composants. Vos fichiers locales/{lng}/{ns}.json restent la source de vérité. Mesuré côte à côte dans i18next vs @intlayer/i18next.
FAQ
Il a été conçu comme un runtime indépendant du framework : une instance globale, un pipeline de plugins, un magasin de ressources, un résolveur de clés. Cette flexibilité est compilée dans chaque bundle. Un composant vide qui n'importe que la bibliothèque coûte 19.7 KB gzip avec next-i18next contre 5.5 KB avec next-intlayer, et ce coût est payé sur chaque page quel que soit le poids de votre contenu.
Il réduit les octets, pas la latence. Passer à i18next-resources-to-backend économise ~49 KB par page mais ajoute un aller-retour réseau lors du changement de langue : 123 ms dans la configuration dynamic et 185 ms dans scoped-static, contre 3-4 ms avec Intlayer. L'hydratation grimpe aussi à 27.7 ms car l'instance résout son backend avant que React ne puisse hydrater.
Oui, avec scoped-dynamic : un namespace par route, un backend de ressources et une table de correspondance pages-namespaces maintenue à la main. On arrive à 163.4 KB par page sur Next.js, soit toujours +22 KB par rapport aux 141.3 KB d'Intlayer qui n'a nécessité aucune configuration. Voir l'optimisation du bundle.
Non. @intlayer/i18next, @intlayer/react-i18next et @intlayer/next-i18next conservent useTranslation, t(), <Trans>, {{interpolation}}, les pluriels _one / _other, les suffixes de contexte et returnObjects. Une seule ligne de plugin dans next.config.ts ou vite.config.ts. Guide pas à pas dans le guide de migration next-i18next.
Les backends et détecteurs de langue sont acceptés mais inertes : il n'y a plus rien à charger ou détecter au runtime. La détection de locale devient la configuration de routage d'Intlayer (préfixe d'URL, cookie, en-tête). Si votre application récupère des traductions depuis un CMS au moment de la requête, utilisez le CMS d'Intlayer ou intlayer pull / push à la place.
Comparaisons associées
Même benchmark, autres bibliothèques :
Pour aller plus loin sur i18next :
Documentation de référence :
Adaptateurs de compatibilité :
Guides de migration :
Pour comprendre d'où viennent ces bibliothèques, lisez l'histoire de l'i18n en JavaScript.
Étoiles GitHub
Les étoiles GitHub reflètent la popularité d'un projet, la confiance de la communauté et sa pérennité. Bien qu'elles ne mesurent pas directement la qualité technique, elles montrent combien de développeurs trouvent le projet utile, suivent ses avancées et sont susceptibles de l'adopter.
Activité des commits
Les étoiles mesurent la popularité. Les commits mesurent le travail investi dans un projet. Au moment de l'écriture, Intlayer compte environ 7 500 commits, plus que la plupart des bibliothèques comparées ici, et environ 5 fois plus que next-intl ou next-i18next.
- i18next/i18next
- i18next/react-i18next
- i18next/next-i18next
- aymericzip/intlayer
Commits sur la branche par défaut, source : API GitHub.
Intlayer est un monorepo : ce total inclut chaque package de framework, la CLI et la documentation. Lisez les commits comme un signal d'activité, pas de qualité.
Téléchargements npm
- i18next
- react-i18next
- next-i18next
- intlayer
Source : API de téléchargements du registre npm.
Le nombre de téléchargements récompense les solutions les plus anciennes, pas les meilleures. Une bibliothèque publiée il y a des années est toujours installée par chaque projet qui l'a choisie à l'époque, par chaque exécution de CI et par chaque package qui en dépend. Ce chiffre mesure l'inertie plus qu'un choix réfléchi.
Les assistants IA amplifient cet effet. next-intl, i18next et vue-i18n sont omniprésents dans le code sur lequel ils ont été entraînés : ils les proposent donc par défaut, sans faire l'effort de comparer les alternatives. Chaque suggestion ajoute des téléchargements, qui alimentent la suggestion suivante. Comparez sur le benchmark plutôt que sur le nombre de téléchargements.
Conclusion
i18next a gagné sa place: il s'exécute partout, propose un plugin pour chaque besoin et bénéficie de plus d'une décennie de maintenance. Le benchmark met toutefois en lumière le coût d'une architecture centrée sur le runtime. La configuration déployée par la majorité des équipes ajoute +70 à 77 KB gzip par page, laisse fuiter ~90% du contenu des autres pages, et un changement de langue avec chargement dynamique prend plus de 100 ms. Atteindre 0% de fuite reste envisageable, mais impose un backend, un namespace par route et une table de correspondance maintenue manuellement, tout en restant +9 à 22 KB plus lourd qu'Intlayer.
Intlayer délègue ce travail au compilateur. Dictionnaires par composant, lazy loading par locale et purge du contenu inutile deviennent des artéfacts de build plutôt que des conventions complexes. Sur la même application: +0.3 KB par page, 0% de fuite, des composants 3 à 10 fois plus légers et un basculement de langue en 3 à 4 ms.
Toutes les données brutes, applications de test et scripts sont disponibles dans le dépôt Benchmark Bloom. Testez-le par vous-même.
Consultez la documentation 'Pourquoi Intlayer?' pour en savoir plus.
Commentaires
Aucun commentaire pour le moment. Soyez le premier à partager vos pensées.
