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
vue-i18n VS Intlayer
vue-i18n est la librairie i18n de référence pour Vue. Intlayer est une alternative basée sur un compilateur, à contenu scopé par composant, avec une intégration Vue (vue-intlayer). Cet article regarde ce que chacune coûte une fois l'application construite.
Les données viennent de Benchmark Bloom, une suite open-source qui construit la même application avec chaque librairie et enregistre ce que le navigateur télécharge et exécute réellement.
tl;dr : Sur la même app Vite + Vue 3,vue-i18nlivre 134,9 KB de JavaScript gzippé par page contre 41,3 KB pour l'app sans i18n. Intlayer livre 57,1 KB. Le runtime devue-i18npèse à lui seul 24,3 KB gzip (6x les 3,9 KB d'Intlayer), chaque page embarque 90 % des chaînes des autres pages, et un composant compilé isolément entraîne 196 KB parce qu'il est lié à l'arbre global de messages. L'adaptateur@intlayer/vue-i18nconserve l'API devue-i18net a mesuré 47,0 KB par page.
En bref
- vue-i18n - La librairie i18n de facto pour Vue 2 / Vue 3 et le cœur de
@nuxtjs/i18n. Messages de style ICU, blocs<i18n>dans les SFC, directivev-t, formateursd()/n(), large écosystème. Les messages sont enregistrés sur une instance globale aucreateI18n(); le chargement paresseux par locale est un patternsetLocaleMessage()manuel, et le découpage par route est à construire vous-même. - Intlayer - Modèle de contenu centré sur les composants. Les dictionnaires
.content.tssont placés à côté du composant qu'ils servent, un compilateur au build (vite-intlayer) les tree-shake et les charge paresseusement par composant et par locale, des types TypeScript stricts sont générés depuis votre contenu, et les traductions manquantes échouent au build. Fournit des helpers routeur / SEO, un Visual Editor / CMS et une 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 instantanés varieront avec le temps.
Comparaison des fonctionnalités côte à côte
Ouvrir le tableau dans une fenêtre modale pour voir tout le contenu clairement
| Fonctionnalité | vue-intlayer (Intlayer) | vue-i18n |
|---|---|---|
| Traductions près des composants | ✅ Oui, .content.ts colocalisé avec chaque composant | ✅ Via les blocs SFC <i18n> (optionnel) ; les catalogues globaux sont l'usage courant |
| Intégration TypeScript | ✅ Types stricts auto-générés depuis le contenu | ✅ Bons typages ; la sûreté stricte des clés demande un schéma typé et de la discipline |
| Détection des traductions manquantes | ✅ Erreur TypeScript + erreur/avertissement au build | ⚠️ Fallback au runtime + avertissement console |
| Contenu riche (composants / Markdown) | ✅ Support direct | ⚠️ Interpolation de composants <i18n-t> ; Markdown via plugins externes |
| Support ICU | ⚠️ En cours | ✅ Oui |
| Formatage (dates, nombres, devises) | ✅ Formateurs basés sur Intl | ✅ d() / n() avec datetimeFormats / numberFormats |
| Routage localisé | ✅ Helpers pour Vue Router / Nuxt, getMultilingualUrls | ⚠️ Pas dans le cœur (@nuxtjs/i18n ou configuration routeur personnalisée) |
| Helpers SEO (hreflang, sitemap, robots) | ✅ Helpers intégrés | ❌ Pas dans le cœur |
| Tree-shaking (ne livrer que le contenu utilisé) | ✅ Par composant, par locale, automatisé par le compilateur | ⚠️ Manuel : découper les catalogues, setLocaleMessage() par route |
| Chargement paresseux | ✅ importMode: 'dynamic' (une ligne de config) | ✅ import() manuel + setLocaleMessage() |
| Purge du contenu inutilisé | ✅ Les dictionnaires morts sont retirés au build | ❌ Pas intégré |
| Test des traductions manquantes (CLI / CI) | ✅ npx intlayer content test | ⚠️ Tiers (vue-i18n-extract) |
| Traduction par IA | ✅ Intégrée, utilise vos propres clés de fournisseur | ❌ Non |
| Visual Editor / CMS | ✅ Visual Editor gratuit + CMS optionnel | ❌ Non (plateformes de localisation externes) |
| Serveur MCP & Agent Skills | ✅ Oui | ❌ Non |
| Écosystème / communauté | ⚠️ Plus petit mais en forte croissance | ✅ Large et mature dans l'écosystème Vue |
Le benchmark
Ce qui a été mesuré
La suite Benchmark Bloom construit la même application Vite + Vue 3 avec chaque librairie : 10 pages (home, about, blog, careers, contact, FAQ, pricing, products, settings, team), 10 locales (en, fr, es, de, it, pt, zh, ja, ko, ru), composants identiques et contenu identique. Les pages sont mesurées en en et fr.
Les deux librairies ont été testées dans la configuration static, celle que la plupart des projets Vue livrent : pour vue-i18n, le JSON de chaque locale importé et passé à createI18n({ messages }) ; pour Intlayer, le importMode: 'static' par défaut. Dans ce mode Intlayer embarque aussi toutes les locales, mais le compilateur scope toujours le contenu par composant, donc une page n'embarque que les dictionnaires des composants qu'elle rend.
Pour chaque build, la suite enregistre :
- Lib size : taille gzip d'un composant vide qui importe seulement la librairie i18n. Le coût fixe du runtime.
- Page JS : JavaScript gzip téléchargé par page, moyenné sur toutes les pages et locales.
- Locale leak % : part des chaînes traduites trouvées dans le JS téléchargé qui appartiennent à une locale que l'utilisateur ne consulte pas (empreintes sur
enetfr, donc 50 % signifie « l'autre locale mesurée est entièrement présente » ; avec 10 locales embarquées, le gaspillage réel est plus élevé). - Page leak % : part des chaînes traduites trouvées dans le JS téléchargé qui appartiennent à une page sur laquelle l'utilisateur n'est pas.
- Component avg : taille gzip moyenne de chaque composant compilé isolément. Montre combien de runtime i18n et de catalogue un seul composant entraîne.
- 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). - Page load :
PerformanceNavigationTiming.duration.
Les chiffres ci-dessous viennent du run daté du 2026-09-12 avecvue-i18n11.4.0 etintlayer9.5.0 / 9.5.1. L'application de test est volontairement petite (quelques dizaines de chaînes par locale), donc les pourcentages de fuite décrivent un pattern : ils grandissent avec votre contenu alors que le coût du runtime reste fixe.
Résultats sur Vite + Vue 3
Choisissez les métriques et les librairies 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
| Librairie | Stratégie | Lib size (gz) | Lib size (min) | Page JS moy. (gz) | Locale leak | Page leak | Component moy. (gz) | Réactivité E2E | Page load |
|---|---|---|---|---|---|---|---|---|---|
| base (sans i18n) | - | 0,0 KB | 0,0 KB | 41,3 KB | 0,0 % | - | 1,1 KB | 1,8 ms | 10,8 ms |
vue-i18n | static | 24,3 KB | 83,2 KB | 134,9 KB | 50,0 % | 90,0 % | 196,0 KB | 2,8 ms | 13,6 ms |
vue-intlayer | static | 3,9 KB | 11,1 KB | 57,1 KB | 56,8 % | 0,0 % | 7,7 KB | 4,5 ms | 13,8 ms |
@intlayer/vue-i18n (compat) | static | 7,9 KB | 23,2 KB | 47,0 KB | 15,0 % | 0,0 % | 8,4 KB | 1,5 ms | 9,3 ms |
La colonne page-leak de l'app de base est laissée vide : sans librairie i18n, l'empreinte capte des chaînes codées en dur dans les chunks partagés et le chiffre n'a pas de sens.
Comment le lire
- Coût du runtime.
vue-i18nest l'un des runtimes les plus lourds de tout le benchmark : 24,3 KB gzip / 83,2 KB minifié pour un composant vide qui l'importe seulement.vue-intlayercoûte 3,9 KB gzip. Cet écart est payé sur chaque page, quel que soit le nombre de chaînes. - JavaScript par page. L'app sans i18n pèse 41,3 KB.
vue-i18nfait plus que la tripler à 134,9 KB ; Intlayer atterrit à 57,1 KB, +15,8 KB, dont l'essentiel vient des dix locales embarquées (voir le point suivant). - Fuite. Avec
createI18n({ messages: { en, fr, ... } }), chaque page livre toutes les locales et les chaînes de toutes les pages : 50 % de fuite de locale (sur les deux locales mesurées) et 90 % de fuite de page. Le modestaticd'Intlayer embarque aussi toutes les locales (d'où un chiffre de fuite de locale comparable) mais a 0 % de fuite de page : une page ne tire que les dictionnaires des composants qu'elle rend. Passer àimportMode: 'dynamic'supprime aussi la fuite de locale ; cette configuration ne faisait pas partie de ce run Vue. - La taille des composants est là où l'architecture se voit. Un composant appelant
useI18n()compile à 196 KB en moyenne, parce quet()est lié à l'instance globale qui contient tous les messages de toutes les locales. Le même composant avecuseIntlayer()compile à 7,7 KB : il n'atteint que son propre dictionnaire. - La réactivité n'est un problème pour aucun des deux (2-5 ms). Le système de réactivité de Vue rend le changement de locale peu coûteux une fois les messages en mémoire.
@intlayer/vue-i18n, l'adaptateur drop-in, conserve l'API devue-i18net a mesuré 47,0 KB par page et 8,4 KB par composant, sans toucher au code de l'application.
Pour référence, le même run a mesuré fluent-vue à 171,8 KB par page, 29,7 KB de runtime et 217 KB par composant.
Tableau complet, avec toutes les librairies et toutes les stratégies, dans le rapport de benchmark Vue.
Pourquoi cet écart ? Instance globale vs dictionnaires compilés
vue-i18n est un runtime. createI18n() construit une instance globale contenant un arbre de messages par locale ; useI18n() lie chaque composant à celle-ci ; t("footer.github") cherche la clé au moment du rendu. C'est ce qui rend possibles les blocs SFC <i18n>, v-t et le chargement de messages au runtime, et c'est aussi pourquoi le graphe de dépendances de chaque composant inclut l'arbre entier :
Copier le code dans le presse-papiers
Optimiser signifie que vous découpez en.json en fichiers par route, que vous appelez setLocaleMessage() dans un guard du routeur, et que vous maintenez la correspondance route → fichier à jour quand les composants bougent. Le runtime ne peut pas le faire pour vous parce qu'il n'a aucune idée des clés qu'un composant va demander.
Intlayer déplace cette connaissance vers le build. Le contenu est déclaré à côté du composant, et vite-intlayer résout quel composant importe quel dictionnaire :
Copier le code dans le presse-papiers
Le compilateur émet, par dictionnaire et par locale, exactement le JSON dont ce composant a besoin, et supprime les dictionnaires que rien n'importe. Le scoping par route est une conséquence du scoping par composant, pas une tâche.
Pour retirer aussi les locales inutilisées, mettezdictionary.importMode: 'dynamic'dansintlayer.config.ts. Voir la doc d'optimisation du bundle.
Expérience développeur
Configuration
vue-i18n
Copier le code dans le presse-papiers
Copier le code dans le presse-papiers
Intlayer
Copier le code dans le presse-papiers
Copier le code dans le presse-papiers
Copier le code dans le presse-papiers
Composant
vue-i18n
Copier le code dans le presse-papiers
Copier le code dans le presse-papiers
t('counter.label') est une chaîne tant que vous ne typez pas vous-même le schéma des messages ; une faute de frappe affiche la clé.
Intlayer
Copier le code dans le presse-papiers
Copier le code dans le presse-papiers
label et increment sont typés ; une faute de frappe est une erreur TypeScript, une valeur française manquante est une erreur de build.
Chargement paresseux par locale
vue-i18n
Copier le code dans le presse-papiers
Ensuite appelez loadLocaleMessages() depuis un guard du routeur, et découpez vous-même locales/{locale}.json par route si vous voulez un scoping par page.
Intlayer
Copier le code dans le presse-papiers
Gardez l'API de vue-i18n, obtenez la sortie d'Intlayer
@intlayer/vue-i18n est un adaptateur drop-in : useI18n(), t(), d(), n(), l'interpolation {name} et {0}, les pluriels à pipe ("car | cars"), v-t et i18n.global.locale continuent de fonctionner, servis depuis des dictionnaires Intlayer compilés par vite-intlayer.
Copier le code dans le presse-papiers
Dans le benchmark, le build compat de la même app est passé de 134,9 KB à 47,0 KB par page et de 196 KB à 8,4 KB par composant, sans toucher aux composants. Vos locales/{locale}.json existants peuvent rester la source de vérité grâce au plugin de synchronisation JSON.
Voir le guide de migration vue-i18n et la doc de compatibilité. Les utilisateurs de Nuxt ont le même chemin via la compatibilité @nuxtjs/i18n.
Quand choisir lequel ?
- Choisissez vue-i18n si vous voulez l'approche Vue standard, si vous dépendez des messages ICU ou des blocs SFC
<i18n>, si vous utilisez déjà@nuxtjs/i18n, ou si une plateforme de traduction attend du JSON centralisé. Prévoyez le temps de découper les catalogues et de charger paresseusement par route si la taille du bundle compte. - Choisissez Intlayer si vous voulez du contenu scopé par composant, du TypeScript strict, des erreurs de clés manquantes au build, du tree-shaking et du chargement paresseux sans effort, et un outillage éditorial intégré (Visual Editor, CMS, traduction IA, serveur MCP). Particulièrement pertinent pour les grandes bases de code Vue / Nuxt modulaires et les design systems.
- Choisissez
@intlayer/vue-i18nsi vous êtes déjà survue-i18net voulez les gains de bundle sans réécriture.
FAQ
Les deux, selon la façon dont vous l'adoptez. vue-intlayer est un runtime natif avec son propre composable useIntlayer(). @intlayer/vue-i18n est un adaptateur de compatibilité qui conserve l'API vue-i18n et remplace ce à quoi elle est liée, afin que vous puissiez migrer sans toucher aux composants et progresser fichier par fichier ensuite.
L'adaptateur ne les lit pas. Déplacez ces messages dans votre JSON de locale, ou dans un .content.ts à côté du composant, ce qui est la même idée avec des types générés. C'est la seule fonctionnalité de vue-i18n qui n'est pas reportée.
Oui. Intlayer avec Nuxt prend en charge le routage multilingue, le middleware de détection de locale et la génération de sitemaps. Si vous utilisez @nuxtjs/i18n, l'adaptateur de compatibilité Nuxt i18n constitue la voie de migration.
Oui. Le plugin de synchronisation JSON les lit avec le dialecte vue-i18n ({name}, {0}, les pluriels en pipe "car | cars") et réécrit les traductions lorsque la CLI ou le CMS les met à jour.
Le support natif d'ICU est en cours de développement. L'adaptateur @intlayer/vue-i18n gère la syntaxe propre à vue-i18n, y compris les pluriels et l'interpolation de listes et de variables nommées. Pour le modèle de pluralisation d'Intlayer, consultez le contenu d'énumération.
Comparaisons associées
Documentation de référence :
Rapports de benchmark :
Pour comprendre d'où viennent ces bibliothèques, lisez l'histoire de l'i18n en JavaScript.
Étoiles GitHub
Les étoiles GitHub sont un indicateur fort de la popularité d'un projet, de la confiance de la communauté et de sa pertinence à long terme. Bien qu'elles ne mesurent pas directement la qualité technique, elles reflètent combien de développeurs trouvent le projet utile, suivent ses progrès 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.
- intlify/vue-i18n
- 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
- vue-i18n
- vue-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
vue-i18n est mature, flexible et profondément intégré à Vue. Le benchmark montre ce que son design centré sur le runtime coûte sur un build Vite : un runtime de 24 KB gzip, 134,9 KB par page pour une app qui pèse 41 KB sans i18n, 90 % de contenu d'autres pages sur chaque page, et des composants qui atteignent chacun 196 KB parce qu'ils dépendent de l'arbre global de messages.
Intlayer déplace le travail dans le compilateur. Les dictionnaires par composant et la purge du contenu mort sont des sorties du build, pas des conventions. Sur la même app : 3,9 KB de runtime, 57,1 KB par page, 0 % de fuite de page, des composants 25x plus petits. Et si une réécriture n'est pas envisageable, @intlayer/vue-i18n fait l'essentiel du chemin sans toucher aux composants.
Toutes les données brutes, les apps de test et les scripts sont dans le dépôt Benchmark Bloom. Lancez-le vous-même.
Consultez la doc « Pourquoi Intlayer ? » pour plus de détails.
Commentaires
Aucun commentaire pour le moment. Soyez le premier à partager vos pensées.
