Posez votre question et obtenez un résumé du document en referencant cette page et le Provider AI de votre choix
Historique des versions
- "Utilisation du middleware et des hooks de remix-intlayer"v9.5.519/09/2026
- "Documentation initiale pour Remix 3"v9.5.009/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
Traduisez votre site web Remix 3 avec Intlayer
Ce guide montre comment intégrer Intlayer pour une internationalisation fluide dans les applications Remix 3 avec un routage sensible à la locale, des déclarations de contenu typées, des composants JSX rendus côté serveur et un support multi-runtime sur Node.js, Bun, Deno et Cloudflare Workers.
Qu'est-ce que Remix 3 ?
Remix 3 représente une évolution architecturale majeure vers un framework web composable et agnostique au runtime, entièrement basé sur les standards web. Plutôt que d'être lié à des bundlers spécifiques ou à des API serveur propriétaires, Remix 3 est distribué sous forme de packages composables à usage unique :
remix/fetch-router(ouremix/router) : Routage léger et conforme aux standards basé sur l'API Fetch (RequestetResponse).remix/ui: Un modèle de composant JSX (jsxImportSource: "remix/ui"). Un composant est une fonction de setup qui renvoie une fonction de rendu, ce qui ressemble à React mais conserve l'état dans des fermetures JavaScript simples.remix/middleware/render: Installecontext.render(<Page />)sur chaque requête, diffusant l'arbre JSX sous forme deResponseHTML.remix/node-fetch-server: Adaptateurs de serveur pour Node.js, avec support natif pour Bun, Deno et les runtimes edge.remix/cookie: Analyse et sérialisation de cookies sécurisées par chiffrement.
Associé à Intlayer et au package remix-intlayer, un middleware de locale ainsi que les mêmes hooks useIntlayer / useDictionary / useLocale que react-intlayer, liés au contexte de requête de Remix, vous bénéficiez d'un système d'internationalisation complet offrant une sécurité au moment de la compilation, des traductions automatisées par IA, un rendu serveur sans surcharge et un routage fluide par locale.
Table des matières
Pourquoi choisir Intlayer plutôt que les alternatives ?
Comparé aux solutions traditionnelles telles que i18next ou aux chargeurs de traduction sur mesure, Intlayer offre une expérience développeur intégrée, optimisée pour l'architecture web moderne :
Intlayer est conçu pour fonctionner nativement avec les standards web (Request, Response, Headers et URL). remix-intlayer s'intègre au Fetch router de Remix 3 sous la forme d'un middleware léger, extrayant la locale des chemins d'URL, des cookies ou des en-têtes Accept-Language et l'exposant au reste de la requête, handlers, vues et composants remix/ui, sans avoir à la transmettre manuellement ni dépendre d'un runtime spécifique.
Fini les clés JSON non vérifiées et les erreurs de clés manquantes au runtime. Intlayer applique les vérifications TypeScript sur toutes les locales déclarées, vous avertissant dès la compilation si une traduction est absente ou invalide.
Remix 3 effectue le rendu des composants JSX sur le serveur et diffuse le flux HTML vers le client. Seul le texte résolu pour la locale demandée se retrouve dans le flux de sortie. Aucun bundle d'hydratation client ni catalogue de traduction encombrant n'est requis, sauf si un composant est explicitement marqué comme clientEntry.
Intlayer colocalise les déclarations de contenu (.content.ts) avec la logique de vos routes, réduisant le contexte de tokens nécessaire pour les grands modèles de langage (LLM). Les commandes CLI intégrées telles que intlayer fill et intlayer test vous permettent d'automatiser les traductions dans vos pipelines CI/CD au coût direct de votre fournisseur d'IA.
Au-delà des flux de travail orientés code, Intlayer propose un Éditeur Visuel auto-hébergé et un CMS Distant, permettant aux éditeurs, traducteurs et rédacteurs de modifier le contenu sans redéployer l'application.
Guide étape par étape
Consultez le Modèle d'Application sur GitHub.
Installer les dépendances
Installez
intlayer,remix-intlayeretremix(version 3) à l'aide de votre gestionnaire de paquets préféré :bashCopier le codeCopier le code dans le presse-papiers
intlayer: Moteur d'internationalisation de base gérant la configuration, la déclaration des dictionnaires (t(),Dictionary), les outils CLI et l'interpréteur de runtime.remix-intlayer: L'intégration Remix 3 : le middleware de routeurintlayer()qui résout la locale de chaque requête, et les hooksuseIntlayer,useDictionaryetuseLocalequi la lisent n'importe où en aval.remix: Package unifié du framework Remix 3 exportantremix/router,remix/routes,remix/ui,remix/middleware/renderetremix/node-fetch-server.
Configurer Intlayer
Architecture
Dans cette architecture, le middleware
intlayer()deremix-intlayerest enregistré danscreateRouter()avant le middlewarerender(). Il retire le préfixe de locale avant la résolution par le routeur, de sorte que les routes ne sont déclarées qu'une seule fois danssrc/routes.tssans segment:locale, et il exécute le reste de la requête dans un scopeAsyncLocalStorage, ce qui permet àuseIntlayer/useLocalede lire la locale sans argument dans les gestionnaires de routes et les vuesremix/ui. Les déclarations de contenu sont placées aux côtés de vos vues danssrc/:bashCopier le codeCopier le code dans le presse-papiers
Configuration
Créez un fichier
intlayer.config.tsà la racine de votre projet pour déclarer les langues prises en charge et les paramètres d'internationalisation :intlayer.config.tsCopier le codeCopier le code dans le presse-papiers
import { Locales, type IntlayerConfig } from "intlayer"; const config: IntlayerConfig = { internationalization: { locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH], defaultLocale: Locales.ENGLISH, }, }; export default config;Pour d'autres paramètres de configuration (comme le mode strict ou les préférences de stockage de routage), consultez la documentation de configuration.
Déclarer votre contenu multilingue
Déclarez votre contenu localisé dans un fichier
.content.ts:src/home.content.tsCopier le codeCopier le code dans le presse-papiers
import { t, type Dictionary } from "intlayer"; const homeContent = { key: "home", content: { title: t({ fr: "Bienvenue sur Remix 3", en: "Welcome to Remix 3", es: "Bienvenido a Remix 3", }), description: t({ fr: "Une application composable basée sur les standards web avec i18n native.", en: "A composable, web-standard application with native i18n.", es: "Una aplicación componible basada en estándares web con i18n nativa.", }), switchLanguage: t({ fr: "Changer de langue :", en: "Switch language:", es: "Cambiar idioma:", }), }, } satisfies Dictionary; export default homeContent;Intlayer prend également en charge les formats JSON, YAML et CommonJS. Voir la Documentation sur la Déclaration de Contenu.
Générer les dictionnaires Intlayer
Compilez les définitions de dictionnaires pour générer les types TypeScript et les registres de runtime :
bashCopier le codeCopier le code dans le presse-papiers
Cette commande compile votre contenu dans le répertoire
.intlayer, offrant une auto-complétion TypeScript complète et un accès rapide aux dictionnaires.Ajouter le middleware Intlayer
Remix 3 propose un pipeline de middlewares composable via
createRouter({ middleware: [...] }).remix-intlayerfournit le middlewareintlayer(), le pendant Remix des proxies denext-intlayeretvite-intlayer. Pour chaque requête entrante, il :- Route la locale, selon
routing.mode(prefix-no-defaultpar défaut). Une URL sans préfixe de locale est redirigée vers l'URL localisée de la locale détectée (le cookie de stockage (INTLAYER_LOCALE) ou l'en-tête personnalisé (x-intlayer-locale), puis la négociation standardAccept-Language, puis votredefaultLocale) à moins que cette locale ne nécessite pas de préfixe. Une URL préfixée telle que/fr/aboutest servie depuis la route/abouten français,/en/aboutest redirigée vers/about, et les règles de réécriturerouting.rewritesont appliquées dans les deux sens (/fr/about→/fr/a-propos). Les ressources statiques et, dans les configurations avecrouting.domains, les domaines de locale sont gérés de la même manière que dans les autres intégrations. - Résout la locale dans le contexte de requête Remix sous
context.intlayer(oucontext.get(Intlayer)), aveclocale,defaultLocaleetavailableLocales. - Persiste la locale via le cookie / en-tête configuré, de sorte que les requêtes suivantes résolvent la même locale.
Parce que le préfixe de locale est supprimé avant la mise en correspondance du routeur, vos routes sont déclarées une seule fois, sans segment
:locale, quel que soit le mode de routage. Le middleware exécute ensuite le reste de la requête dans une portéeAsyncLocalStorageliée au contexte de requête, ce qui permet aux hooks du package de lire la locale sans aucun argument, aussi bien dans les gestionnaires de routes, les vues que les composantsremix/ui:typescriptCopier le codeCopier le code dans le presse-papiers
useIntlayer("home", "fr")ouuseIntlayer("faq", { item: 2 })surchargent la locale de la requête pour un appel, etuseDictionary(homeContent)lit un dictionnaire importé au lieu d'une clé. En dehors d'une requête, les hooks se replient sur la locale par défaut.Le middleware prépare également les dictionnaires Intlayer au démarrage du serveur, évitant ainsi qu'un
intlayer buildmanquant ne laisse le registre vide.Définissez
routing.enableProxy: falsedansintlayer.config.tspour conserver uniquement la résolution de locale et gérer le routage vous-même.intlayer({ ignore })laisse intactes les requêtes correspondantes (un préfixe d'API, par exemple), etintlayer({ isDevServer })contrôle si la locale stockée pilote les redirections dans le mode automatiqueenableProxypar défaut.- Route la locale, selon
Définir des routes typées
Définissez vos routes d'application à l'aide de
route()issu deremix/routes. Déclarez-les une seule fois, sans segment de locale, le middleware sert chaque locale à partir de ces routes :src/routes.tsCopier le codeCopier le code dans le presse-papiers
import { route } from "remix/routes"; export const routes = route({ home: "/", });L'utilisation de
route()garantit la génération d'URL typées dans toute votre application, etgetLocalizedPathapplique le mode de routage correspondant :typescriptCopier le codeCopier le code dans le presse-papiers
Afficher des pages localisées avec JSX
Remix 3 effectue le rendu de l'interface utilisateur avec des composants JSX issus de
remix/ui. Un composant est une fonction de setup qui reçoit unHandleet renvoie une fonction de rendu. Le setup s'exécute une seule fois par instance, le rendu s'exécute à chaque mise à jour, et les props sont lues viahandle.props.Commencez par un shell partagé
Documentqui applique les attributs<html lang="..." dir="...">à partir de la locale résolue par le middleware :src/views/document.tsxCopier le codeCopier le code dans le presse-papiers
import { getHTMLTextDir } from "intlayer"; import { useLocale } from "remix-intlayer"; import type { Handle, RemixNode } from "remix/ui"; type DocumentProps = { title: string; children?: RemixNode; }; export const Document = (handle: Handle<DocumentProps>) => () => { const { title, children } = handle.props; const { locale } = useLocale(); return ( <html lang={locale} dir={getHTMLTextDir(locale)}> <head> <meta charSet="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>{title}</title> </head> <body>{children}</body> </html> ); };Créez ensuite la page d'accueil. Elle lit le dictionnaire localisé avec
useIntlayeret affiche un sélecteur de langue :src/views/home.tsxCopier le codeCopier le code dans le presse-papiers
import { getLocaleName, getLocalizedUrl, getPathWithoutLocale } from "intlayer"; import { useIntlayer, useLocale } from "remix-intlayer"; import { Document } from "./document"; export const HomePage = () => () => { const { locale, availableLocales } = useLocale(); const home = useIntlayer("home"); const pathWithoutLocale = getPathWithoutLocale(); return ( <Document title={home.title}> <header> <nav aria-label="Languages"> <span>{home.switchLanguage}</span> <ul> {availableLocales.map((localeItem) => { const isActive = localeItem === locale; return ( <li key={localeItem} class="p-1"> <a href={getLocalizedUrl(pathWithoutLocale, localeItem)} class={isActive ? "active" : undefined} aria-current={isActive ? "page" : undefined} > {getLocaleName(localeItem, locale)} </a> </li> ); })} </ul> </nav> </header> <main> <h1>{home.title}</h1> <p>{home.description}</p> </main> </Document> ); };Le JSX de Remix n'est pas React :
classs'écrit tel quel (classNameest également accepté) et les nouveaux rendus sont déclenchés explicitement avechandle.update(). Les valeurs interpolées sont automatiquement échappées. Les hooks Intlayer sont de simples fonctions lisant la portée de la requête, ils peuvent donc être appelés aussi bien depuis la fonction de setup que depuis la fonction de rendu.Connecter le routeur et le serveur
Ajoutez le middleware
render()deremix/middleware/renderaux côtés du middleware Intlayer. Il installecontext.render(node, init)sur chaque requête, ce qui diffuse l'arbre JSX dans uneResponseHTML (en ajoutant<!DOCTYPE html>au début et en définissant l'en-têteContent-Type) :src/router.tsxCopier le codeCopier le code dans le presse-papiers
import { intlayer } from "remix-intlayer"; import { render } from "remix/middleware/render"; import { createRouter } from "remix/router"; import { routes } from "./routes"; import { HomePage } from "./views/home"; // 1. Initialiser le routeur avec les middlewares Intlayer + render export const router = createRouter({ middleware: [intlayer(), render()], }); // 2. Associer les gestionnaires de route, `/`, `/fr`, `/es`… atteignent tous `home` router.map(routes, { actions: { home(context) { return context.render(<HomePage />); }, }, });context.renderaccepte unResponseInitoptionnel comme second argument, par ex.context.render(<NotFoundPage />, { status: 404 }). La locale résolue reste accessible depuis le gestionnaire viacontext.intlayer.locale, par exemple pour construire une réponseResponse.json.Enfin, exposez le routeur via un gestionnaire
fetchstandard. Le même routeur fonctionne sur Node.js, Bun, Deno et Cloudflare Workers :src/server.tsCopier le codeCopier le code dans le presse-papiers
import * as http from "node:http"; import { createRequestListener } from "remix/node-fetch-server"; import { router } from "./router"; const PORT = Number(process.env.PORT || 3000); // Node.js const server = http.createServer( createRequestListener((request) => router.fetch(request)) ); server.listen(PORT, () => { console.log(`Serveur démarré sur http://localhost:${PORT}`); }); // Bun / Deno / Cloudflare Workers export default { port: PORT, fetch(request: Request) { return router.fetch(request); }, };Auditer et auto-compléter les traductions
Intlayer fournit un CLI pour auditer les traductions manquantes et les compléter automatiquement grâce à l'IA :
bashCopier le codeCopier le code dans le presse-papiers
Configuration TypeScript
Pointez JSX vers le runtime remix/ui et assurez-vous que votre tsconfig.json inclut les types générés par .intlayer :
Copier le code dans le presse-papiers
jsxImportSource: "remix/ui"est ce qui permet à<HomePage />d'être résolu avec lecreateElementde Remix plutôt qu'avec celui de React.
Conclusion
Avec Remix 3 et Intlayer, vous bénéficiez d'une stack légère, typée et portable, conforme aux standards du web ouvert. Votre application peut évoluer aisément de pages marketing simples à des services distribués mondialement et rendus en périphérie (edge).
