Posez votre question et obtenez un résumé du document en referencant cette page et le Provider AI de votre choix
Historique des versions
- "Version initiale"v9.5.1026/09/2026
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
Comment internationaliser votre application TanStack Start avec Paraglide JS en 2026
Table des matières
Qu'est-ce que Paraglide JS ?
Paraglide JS (développé par inlang) est une bibliothèque d'internationalisation (i18n) basée sur un compilateur. Au lieu d'embarquer un runtime qui recherche des clés dans un objet JSON, elle compile chaque message en une fonction JavaScript typée (m.about_title()). Les messages inutilisés peuvent être éliminés par le bundler, et une faute de frappe dans une clé devient une erreur de compilation.
Paraglide est l'approche i18n utilisée dans les exemples officiels de TanStack Router, et elle s'intègre à TanStack Start via trois éléments principaux :
- un plugin Vite qui compile les messages et le runtime dans
src/paraglide; - un middleware serveur qui résout la locale de chaque requête ;
- une réécriture de routeur qui mappe les URL localisées (
/fr/about) vers votre arbre de routes (/about), vous évitant ainsi d'avoir recours à un segment$locale.
Ce guide configure ces trois éléments, puis aborde tout ce que Paraglide vous laisse gérer : lang et dir, sélecteur de langue, métadonnées traduites, canonical, hreflang avec x-default, Open Graph, JSON-LD, sitemap, robots.txt, pré-rendu et pages 404 localisées.
Vous recherchez une autre stack ? Consultez le guide TanStack Start + use-intl, le guide TanStack Start + Lingui ou le guide TanStack Start + Intlayer.
Vous souhaitez comparer les deux approches basées sur un compilateur ? Lisez Intlayer est-il plus léger que Paraglide ?.
Ce que révèlent les benchmarks sur Paraglide avec TanStack Start
Le benchmark i18n exécute la même application TanStack Start de 10 pages et 10 locales avec chaque bibliothèque majeure, et mesure ce que le navigateur télécharge réellement.
Chargement JSON dynamique
Charge les traductions à la volée
JSON scopé (espaces de noms)
Espaces de noms de traduction par page
Benchmark de Performance I18n
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
Chiffres clés pour @inlang/paraglide-js@2.15.1, mesurés le 26-09-2026 (gzip) :
Ouvrir le tableau dans une fenêtre modale pour voir tout le contenu clairement
| Configuration | Taille de la bibliothèque | JS par page | Fuite autres locales | Fuite autres pages | Chargement de la page |
|---|---|---|---|---|---|
| Sans i18n (app de base) | - | 111.0 KB | 0% | 0% | 15.7 ms |
| Paraglide JS | 1.8 KB | 125.1 KB | 49.7% | 0% | 22.1 ms |
react-intlayer | 4.5 KB | 126.8 KB | 0% | 0% | 14.8 ms |
use-intl | 75.9 KB | 128.7 KB | 0% | 0% | 17.4 ms |
| Lingui | 56.7 KB | 120.2 KB | 8.6% | 0% | 21.9 ms |
Ce qu'il faut retenir :
- Le runtime est minuscule et les pages ne fuient pas. Le runtime est généré sur mesure pour votre configuration, et les messages sont importés là où ils sont utilisés.
- Les locales fuient. Chaque fonction de message contient toutes les locales, de sorte qu'environ la moitié des chaînes traduites envoyées à une page correspondent à des langues que le visiteur n'utilise pas. Plus vous ajoutez de locales, plus cette part augmente.
- Le chargement de la page est le plus lent du groupe, en partie parce que la locale est résolue via des stratégies à chaque appel plutôt que lue depuis un contexte React.
Consultez les données complètes : Rapport de benchmark TanStack Start, et le dépôt de benchmark.
Comparatif des fonctionnalités sur TanStack Start
Comment Paraglide JS se compare aux autres bibliothèques couramment utilisées sur TanStack Start :
Ouvrir le tableau dans une fenêtre modale pour voir tout le contenu clairement
| Fonctionnalité | react-intlayer (Intlayer) | use-intl | Paraglide JS | Lingui |
|---|---|---|---|---|
| Traductions proches des composants | ✅ Colocalisées | ❌ JSON centralisé | ❌ Un fichier JSON par locale | ⚠️ Texte source dans les composants |
| Intégration TypeScript | ✅ Types auto-générés | ✅ Via AppConfig | ✅ Fonctions de message typées | ⚠️ Macros uniquement |
| Détection des traductions manquantes | ✅ Erreurs de types et alertes de build | ⚠️ Fallback au runtime | ⚠️ Repli sur la locale de base | ⚠️ Repli sur le texte source |
| Contenu riche (JSX, Markdown) | ✅ Support direct | ⚠️ Balises via t.rich | ⚠️ Chaînes simples | ✅ JSX dans <Trans> |
| Routage localisé | ✅ Intégré | ❌ {-$locale} manuel | ✅ urlPatterns + réécriture de routeur | ❌ {-$locale} manuel |
| Changement de locale sans rechargement | ✅ Oui | ✅ Oui | ❌ Rechargement complet de la page | ✅ Oui |
| Pluralisation | ✅ Basée sur l'énumération | ✅ ICU | ✅ Variantes | ✅ ICU |
| MessageFormat ICU | ✅ Via format: "icu" | ✅ Natif | ⚠️ Via un plugin inlang | ✅ Natif |
| Formats de contenu | ✅ .ts, .json, .md, .yaml... | ⚠️ .json | ⚠️ JSON inlang | ✅ PO, JSON, CSV |
| Traduction par IA | ✅ Votre propre fournisseur et clé | ❌ Non | ❌ Non | ❌ Non |
| Éditeur visuel / CMS | ✅ Éditeur local + CMS optionnel | ❌ Plateformes externes | ⚠️ Applications de l'écosystème inlang | ❌ Plateformes externes |
| Outils SEO (hreflang, sitemap) | ✅ Intégrés | ❌ Manuel | ⚠️ URL localisées, le reste manuel | ❌ Manuel |
| Taille runtime (gzip, benchmark) | 4.5 KB | 75.9 KB | 1.8 KB | 56.7 KB |
| Fuite, meilleure config (locale / page) | 0% / 0% | 0% / 0% | 49.7% / 0% | 8.6% / 0% |
| Traductions manquantes en CI | ✅ npx intlayer test | ⚠️ Non intégré | ⚠️ Non intégré | ✅ lingui compile --strict |
La taille du runtime et les chiffres de fuite proviennent du benchmark TanStack Start. La fuite est mesurée sur la configuration optimale de chaque bibliothèque.
Autres guides TanStack Start : Lingui, use-intl et Intlayer.
Bonnes pratiques à respecter
- Définissez
langetdirsur<html>à partir de la locale résolue, côté serveur. - Conservez une URL par langue avec une stratégie de préfixe (
/fr/about), afin que chaque version linguistique soit indexable. - Placez
urlen premier dans votre stratégie de locale, afin que l'URL soit la source de vérité et que les robots d'indexation reçoivent la page demandée. - Utilisez des clés de message plates et descriptives (
about_title) qui correspondent proprement à des noms de fonctions. - Versionnez vos fichiers
messages/*.json, et non le dossier générésrc/paraglide, pour éviter les conflits de fusion sur les fichiers générés. - Traduisez vos métadonnées, et déclarez
canonical,hreflangetx-defaultsur chaque page. - Générez un sitemap multilingue et un robots.txt, et pré-rendez chaque locale.
- Utilisez de véritables liens pour le sélecteur de langue, afin que les robots d'indexation découvrent toutes les langues.
Consultez notre guide sur l'internationalisation et le SEO ainsi que le guide hreflang.
Guide étape par étape pour configurer Paraglide JS dans une application TanStack Start
Voici la structure de projet que nous allons créer :
Copier le code dans le presse-papiers
Remarquez l'absence de dossier $locale : la réécriture du routeur retire le préfixe avant la correspondance des routes.
Installer les dépendances
Commencez à partir d'un projet TanStack Start, puis initialisez Paraglide. La commande d'initialisation crée
project.inlang/settings.json, un premier fichiermessages/en.jsonet installe le paquet.bashCopier le codeCopier le code dans le presse-papiers
- @inlang/paraglide-js : le compilateur et son plugin Vite. Il n'y a aucun paquet runtime à installer : le runtime est généré directement dans votre projet.
Configurer vos locales
project.inlang/settings.jsonconstitue l'unique source de vérité pour les langues gérées. Le plugin de format de message lit un fichier JSON par locale.project.inlang/settings.jsonCopier le codeCopier le code dans le presse-papiers
Configurer le plugin Vite et la stratégie d'URL
Le plugin compile les messages à chaque modification. Trois options sont particulièrement importantes pour TanStack Start :
strategy: la liste ordonnée des sources permettant de déterminer la locale. Placerurlen premier fait de l'URL la source de vérité.cookieetpreferredLanguagesont utilisés par le middleware lorsque l'URL ne permet pas de trancher.urlPatterns: la façon dont une locale est associée à une URL. Les locales non par défaut sont listées en premier, car le premier motif correspondant est appliqué. Ici, la locale par défaut ne comporte pas de préfixe (/about), tandis que les autres sont préfixées (/fr/about).outputStructure: "message-modules": un module par message, ce qui permet au bundler d'éliminer les messages qu'une page n'importe pas.
vite.config.tsCopier le codeCopier le code dans le presse-papiers
Ajoutez le dossier généré à
.gitignore. Il est reconstruit lors dedevetbuild:.gitignoreCopier le codeCopier le code dans le presse-papiers
Créer vos fichiers de traduction
Chaque clé devient une fonction exportée depuis
src/paraglide/messages. Des clés plates en snake_case offrent les noms de fonctions les plus lisibles. Les variables utilisent des espaces réservés{name}.messages/en.jsonCopier le codeCopier le code dans le presse-papiers
messages/fr.jsonCopier le codeCopier le code dans le presse-papiers
Les pluriels utilisent la syntaxe de variantes du format de message inlang :
messages/en.jsonCopier le codeCopier le code dans le presse-papiers
Ajouter le middleware serveur
Le middleware résout la locale de chaque requête selon votre stratégie, et la rend accessible via
getLocale()pendant toute la durée du rendu côté serveur, à travers un scopeAsyncLocalStorage. C'est ce qui garantit la sécurité des requêtes concurrentes dans différentes langues.Dans TanStack Start, enveloppez le point d'entrée serveur par défaut :
src/server.tsCopier le codeCopier le code dans le presse-papiers
Réécrire les URL localisées dans le routeur
L'option
rewritede TanStack Router traduit les URL aux limites du routeur :- entrée (input) :
/fr/aboutest dé-localisé en/aboutavant la mise en correspondance, de sorte qu'une unique routeabout.tsxgère toutes les langues ; - sortie (output) : chaque
hrefgénéré (liens, redirections, navigation) est localisé pour la locale active, si bien que<Link to="/about">génère/fr/aboutsur une page en français.
src/router.tsxCopier le codeCopier le code dans le presse-papiers
Parce que les liens sont automatiquement localisés par la réécriture, vous n'avez pas besoin d'un composant personnalisé
LocalizedLink: utilisez le composantLinkhabituel de TanStack Router.- entrée (input) :
Créer le document racine
getLocale()renvoie la locale résolue par le middleware sur le serveur, et la locale extraite de l'URL dans le navigateur, garantissant ainsi quelangetdirrestent identiques dans le HTML serveur et après hydratation.src/i18n/config.tsCopier le codeCopier le code dans le presse-papiers
src/routes/__root.tsxCopier le codeCopier le code dans le presse-papiers
Utiliser les traductions dans vos pages
Les messages sont de simples fonctions : importez
m, appelez la fonction et transmettez les variables sous forme d'objet. Tout est typé, y compris les variables.src/routes/index.tsxCopier le codeCopier le code dans le presse-papiers
src/routes/about.tsxCopier le codeCopier le code dans le presse-papiers
Une fonction de message accepte également une locale explicite :
m.about_title({}, { locale: "fr" }). C'est utile dans le code serveur qui génère une langue différente de celle de la requête en cours, comme pour l'envoi d'e-mails.Changer la langue de votre contenu
FacultatifAffichez le sélecteur sous forme de liens avec
localizeHref, afin que les robots d'indexation découvrent chaque langue.setLocaleenregistre le choix dans un cookie et recharge la page dans la nouvelle langue : un rechargement complet est le comportement prévu par Paraglide, car les fonctions de message lisent la locale à chaque appel au lieu de s'abonner à un état React.src/components/LocaleSwitcher.tsxCopier le codeCopier le code dans le presse-papiers
Internationaliser vos métadonnées
FacultatifChaque version linguistique peut se positionner de façon autonome dans les moteurs de recherche, à condition que chaque page fournisse :
- un
<title>et unedescriptiontraduits ; - une URL canonique pointant vers elle-même ;
- une balise alternative
hreflangpar locale, plusx-default; - les balises Open Graph
og:locale,og:locale:alternateetog:url; - des données structurées JSON-LD avec
inLanguage.
La fonction
localizeUrlde Paraglide construit les URL alternatives à partir de vosurlPatterns, ce qui évite toute divergence avec le routage réel :src/i18n/seo.tsCopier le codeCopier le code dans le presse-papiers
- un
Internationaliser votre sitemap
FacultatifUn sitemap multilingue énumère chaque URL pour chaque locale, et chaque entrée déclare toutes ses alternatives à l'aide de
xhtml:link:src/routes/sitemap[.]xml.tsCopier le codeCopier le code dans le presse-papiers
Internationaliser votre robots.txt
FacultatifLes routes privées existent dans toutes les langues, les règles
Disallowdoivent donc couvrir chaque chemin localisé. Supprimezpublic/robots.txtsi le starter en a créé un, puis servez-le depuis une route :src/routes/robots[.]txt.tsCopier le codeCopier le code dans le presse-papiers
Pré-rendre chaque locale
FacultatifListez le chemin localisé de chaque page afin que TanStack Start pré-rende l'ensemble des versions linguistiques.
localizeHrefest du code généré sans dépendance au navigateur, il peut donc s'exécuter dansvite.config.ts, mais le fichier n'existe qu'après une première compilation. Énumérer les chemins manuellement, comme ci-dessous, permet d'éviter ce problème d'ordre :vite.config.tsCopier le codeCopier le code dans le presse-papiers
Comme le sélecteur affiche de véritables liens,
crawlLinks: truedécouvre également les pages que vous auriez oublié de lister.Gérer les pages 404 localisées
FacultatifGrâce à la réécriture,
/fr/does-not-existcorrespond à/does-not-exist, etgetLocale()renvoie toujoursfr, de sorte que lenotFoundComponentracine de l'étape 7 s'affiche en français. Une route catch-all garantit que les chemins profonds y parviennent également. Marquez la page avecnoindex: React 19 hisse la balise<meta>dans le<head>.src/components/NotFound.tsxCopier le codeCopier le code dans le presse-papiers
src/routes/$.tsxCopier le codeCopier le code dans le presse-papiers
Accéder à la locale dans les Server Functions
FacultatifLes fonctions serveur s'exécutent dans le contexte du middleware Paraglide, donc
getLocale()y fonctionne également :src/server/sendWelcomeEmail.tsCopier le codeCopier le code dans le presse-papiers
Comparer avec Intlayer
FacultatifIl n'existe pas d'adaptateur direct pour passer de Paraglide à Intlayer, car les deux reposent sur la même idée : compiler le contenu au moment du build et embarquer le runtime le plus léger possible. Les différences se situent au niveau de ce qui parvient au navigateur et de l'organisation des contenus :
- Locales : Intlayer charge des dictionnaires dynamiques par langue (0 % de fuite de locale dans le benchmark), tandis que chaque fonction de message Paraglide embarque toutes les langues (49.7 %).
- Organisation du contenu : le contenu peut être placé dans des fichiers
.content.tsà côté de chaque composant ou dans des fichiers centralisés. Voir i18n par composant vs centralisée. - Changement de locale : le contenu est lu depuis un contexte React, de sorte que le changement de langue re-rend les composants sans rechargement de page.
- Code généré : rien n'est généré dans le dossier
src, il n'y a donc rien à régénérer avant un commit.
Si vous venez d'une autre bibliothèque plutôt que de Paraglide, les adaptateurs de compatibilité conservent l'API de
use-intl,next-intl,react-i18next,react-intlou Lingui tout en remplaçant le runtime.Consultez Intlayer est-il plus léger que Paraglide ? et le guide TanStack Start pour Intlayer.
Automatiser vos traductions avec Intlayer
FacultatifParaglide affiche les traductions, mais il ne vous aide pas à les produire. Intlayer est gratuit et open source, et son outillage vous aide même sur un projet Paraglide :
- Traduisez avec l'IA en utilisant votre propre clé d'API et fournisseur. Consultez le remplissage automatique et la CLI.
- Conservez vos fichiers JSON comme source de vérité grâce au plugin sync JSON.
- Testez les traductions manquantes en CI. Consultez tester vos traductions.
- Analysez votre site déployé à la recherche de balises
hreflangmanquantes, de mauvaises URL canoniques et de fuites de locales grâce à la commande scan.
Foire aux questions
C'est un choix solide : il est utilisé dans les exemples officiels de TanStack Router, possède le plus petit runtime du benchmark (~1.8 KB gzip), et les messages sont entièrement typés. Les compromis sont que chaque fonction de message contient toutes les langues, ce qui fait fuiter environ la moitié des chaînes traduites vers des visiteurs d'autres langues, et que changer de langue recharge la page.
Non. La fonction rewrite du routeur supprime le préfixe de locale avant la correspondance des routes et l'ajoute de nouveau aux liens générés, de sorte qu'un simple about.tsx dessert /about, /fr/about et /es/about.
Les fonctions de message lisent la langue au moment où elles sont appelées ; elles ne sont pas abonnées à un état React. setLocale recharge donc la page par défaut afin que chaque message soit re-rendu dans la nouvelle langue. Vous pouvez passer { reload: false }, mais vous devrez alors re-rendre l'arbre de composants vous-même.
Il est préférable de ne pas le faire. Le dossier est régénéré à chaque exécution de dev et build, et le versionner entraîne des conflits de fusion sur des fichiers générés. Versionnez plutôt messages/*.json et project.inlang/settings.json.
Utilisez localizeUrl pour construire une URL absolue par langue dans le head() de la route, et ajoutez une balise x-default pointant vers la langue de base. L'étape 10 fournit un helper réutilisable, et l'étape 11 ajoute ces mêmes alternatives au sitemap.
Les messages inutilisés sont éliminés lorsque vous utilisez outputStructure: "message-modules", évitant ainsi la fuite du contenu d'autres pages. Les locales inutilisées ne le sont pas : chaque fonction de message contient toutes les traductions, c'est pourquoi le benchmark mesure une fuite de locale de 49.7 %.
Commentaires
Aucun commentaire pour le moment. Soyez le premier à partager vos pensées.
