Posez votre question et obtenez un résumé du document en referencant cette page et le Provider AI de votre choix
Historique des versions
- "Historique initial"v9.1.306/08/2025
Le contenu de cette page a été traduit à l'aide d'une IA.
Voir la dernière version du contenu original en anglaisIf you have an idea for improving this documentation, please feel free to contribute by submitting a pull request on GitHub.
GitHub link to the documentationCopy doc Markdown to clipboard
Traduire votre site SolidStart avec Intlayer | Internationalisation (i18n)
Table des matières
Ce guide couvre une application SolidStart rendue côté serveur : la détection de la locale se fait lors de la requête, les pages sont rendues sur le serveur dans la bonne langue, et les signaux <html lang>, hreflang et sitemap dont les moteurs de recherche ont besoin sont émis côté serveur.
Pourquoi Intlayer plutôt que des alternatives ?
Par rapport aux principales solutions comme @solid-primitives/i18n ou i18next, Intlayer est une solution qui intègre des optimisations comme :
Intlayer est optimisé pour fonctionner parfaitement avec Solid en offrant un ciblage du contenu au niveau des composants, des traductions réactives, et toutes les fonctionnalités nécessaires pour faire évoluer l'internationalisation (i18n).
Au lieu de charger de volumineux fichiers JSON dans vos pages, chargez uniquement le contenu nécessaire. Intlayer aide à réduire la taille de votre bundle et de vos pages jusqu'à 50 %.
Cibler le contenu de votre application facilite la maintenance pour les applications à grande échelle. Vous pouvez dupliquer ou supprimer un dossier de fonctionnalité individuel sans la charge mentale de vérifier l'ensemble de votre base de code de contenu. De plus, Intlayer est entièrement typé pour garantir l'exactitude de votre contenu.
Colocaliser le contenu réduit le contexte nécessaire pour les grands modèles de langage (LLM). Intlayer est également livré avec une suite d'outils, tels qu'un CLI pour tester les traductions manquantes, le LSP, le MCP, et des compétences d'agent, pour rendre l'expérience développeur (DX) encore plus fluide pour les agents IA.
Utilisez l'automatisation pour traduire dans votre pipeline CI/CD en utilisant le LLM de votre choix au coût de votre fournisseur d'IA. Intlayer propose également un compilateur pour automatiser l'extraction de contenu, ainsi qu'une plateforme web pour vous aider à traduire en arrière-plan.
Connecter de volumineux fichiers JSON à des composants peut entraîner des problèmes de performance et de réactivité. Intlayer optimise le chargement de votre contenu au moment du build.
Bien plus qu'une simple solution i18n, Intlayer fournit un éditeur visuel auto-hébergé et un CMS complet pour vous aider à gérer votre contenu multilingue en temps réel, rendant la collaboration avec les traducteurs, rédacteurs et autres membres de l'équipe fluide. Le contenu peut être stocké localement et/ou à distance.
Guide étape par étape pour configurer Intlayer dans une application SolidStart
Installer les dépendances
Installez les paquets nécessaires en utilisant npm :
bashCopier le codeCopier le code dans le presse-papiers
npx intlayer init --interactiveLe drapeau
--interactiveest optionnel. Utilisezintlayer-cli initsi vous êtes un agent IA.Cette commande détectera votre environnement et installera les paquets requis. Par exemple :
bashCopier le codeCopier le code dans le presse-papiers
npm install intlayer solid-intlayer vite-intlayerintlayer
Le paquet principal qui fournit des outils d'internationalisation pour la gestion de la configuration, la traduction, la déclaration de contenu, la transpilation et les commandes CLI.
solid-intlayer
Le paquet qui intègre Intlayer avec l'application Solid. Il fournit des fournisseurs de contexte et des hooks pour l'internationalisation Solid.
vite-intlayer
Inclut le plugin Vite pour intégrer Intlayer avec le bundler Vite, ainsi que le gestionnaire de routage de locale qui détecte la locale préférée de l'utilisateur, gère les cookies et s'occupe de la redirection d'URL.
vite-intlayerest ici une préoccupation côté serveur, et pas seulement au moment du build : il fournit le gestionnaire de requête exécuté par le serveur Nitro de SolidStart. Le conserver dansdependenciesest l'option sécurisée par défaut — vous ne pouvez le déplacer dansdevDependenciesque si vous déployez le répertoire.outputconstruit, dans lequel Nitro intègre le gestionnaire.Configuration de votre projet
Créez un fichier de configuration pour configurer les langues de votre application :
intlayer.config.tsCopier le codeCopier le code dans le presse-papiers
import { type IntlayerConfig, Locales } from "intlayer"; const config: IntlayerConfig = { internationalization: { locales: [ Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH, // Vos autres locales ], defaultLocale: Locales.ENGLISH, }, routing: { mode: "prefix-no-default", }, }; export default config;Avec
prefix-no-default, la locale par défaut est servie depuis des URL sans préfixe :plaintextCopier le codeCopier le code dans le presse-papiers
/ /about → Anglais (locale par défaut)/fr /fr/about → Français/es /es/about → EspagnolGrâce à ce fichier de configuration, vous pouvez configurer les URL localisées, la redirection middleware, les noms de cookies, l'emplacement et l'extension de vos déclarations de contenu, désactiver les logs Intlayer dans la console, et plus encore. Pour une liste complète des paramètres disponibles, reportez-vous à la documentation de configuration.
Intégrer Intlayer dans votre configuration Vite
Ajoutez le plugin Intlayer à votre configuration :
vite.config.tsCopier le codeCopier le code dans le presse-papiers
import { solidStart } from "@solidjs/start/config"; import { nitro } from "nitro/vite"; import { defineConfig } from "vite"; import { intlayer } from "vite-intlayer"; export default defineConfig({ plugins: [solidStart(), nitro(), intlayer()], });Le plugin Vite
intlayer()construit vos fichiers de déclaration de contenu, les surveille en mode développement et définit les variables d'environnement Intlayer dans l'application. Il fournit également des alias qui optimisent les performances.Le routage de locale est inclus avec le plugin
SolidStart fonctionne sur Nitro, et
intlayer()enregistre son gestionnaire de routage de locale directement dans le pipeline serveur de Nitro (via l'optionrouting.enableProxy, àtruepar défaut). Rien d'autre à câbler : sur un serveur construit, chaque requête est inspectée avant d'atteindre le routeur, et- la locale est lue depuis le préfixe de l'URL, puis le cookie
INTLAYER_LOCALE, puis l'en-têteAccept-Language; - une URL non préfixée est redirigée vers sa contrepartie localisée lorsque la locale résolue n'est pas celle par défaut (
/→/fr) ; - une URL préfixée de manière redundante est redirigée vers sa forme canonique (
/en/about→/about) ; - le cookie de locale est réécrit sur la réponse.
- la locale est lue depuis le préfixe de l'URL, puis le cookie
Déclarer votre contenu
Créez et gérez vos déclarations de contenu pour stocker les traductions :
src/contents/home.content.tsCopier le codeCopier le code dans le presse-papiers
import { type Dictionary, t } from "intlayer"; const homeContent = { key: "home-page", content: { title: t({ en: "Hello world!", fr: "Bonjour le monde !", es: "¡Hola mundo!", }), metaTitle: "SolidStart + Intlayer", metaDescription: t({ en: "A SolidStart application internationalized with Intlayer.", fr: "Une application SolidStart internationalisée avec Intlayer.", es: "Una aplicación SolidStart internacionalizada con Intlayer.", }), documentation: t({ en: "Visit start.solidjs.com to learn how to build SolidStart apps.", fr: "Visitez start.solidjs.com pour apprendre à créer des applications SolidStart.", es: "Visita start.solidjs.com para aprender a crear aplicaciones SolidStart.", }), }, } satisfies Dictionary; export default homeContent;⚠️ Piège spécifique à SolidStart : chaque fichier
.ts/.tsxsoussrc/routesdevient une route, et un fichier.content.tsa un export par défaut, donc il serait considéré comme une page. Conservez les déclarations de contenu de vos pages en dehors du répertoire des routes (src/contents/fonctionne très bien). Le contenu des composants peut rester colocalisé, carsrc/componentsn'est pas scanné par le routeur basé sur le système de fichiers.Vos déclarations de contenu peuvent être définies n'importe où dans votre application dès lors qu'elles sont incluses dans le répertoire
contentDir(par défaut,./src), et correspondent à l'extension de fichier de déclaration de contenu (par défaut,.content.{json,ts,tsx,js,jsx,mjs,cjs,md,mdx,yaml,yml}).Pour plus de détails, reportez-vous à la documentation de déclaration de contenu.
Ajouter le routage localisé
L'objectif de cette étape est de donner à chaque langue sa propre URL, ce que les moteurs de recherche indexent.
Déplacez vos pages sous un segment dynamique optionnel. Dans le routeur basé sur le système de fichiers de SolidStart,
[[locale]]se compile selon le motif de chemin:locale?:plaintextCopier le codeCopier le code dans le presse-papiers
src/routes/ [[locale]].tsx ← layout qui valide le segment [[locale]]/ index.tsx → / et /fr et /es about.tsx → /about et /fr/about et /es/about [...404].tsx → catch-all pour tout le resteLe seul rôle du fichier de layout est de restreindre le segment à une locale configurée :
src/routes/[[locale]].tsxCopier le codeCopier le code dans le presse-papiers
import type { RouteSectionProps } from "@solidjs/router";import { locales } from "intlayer";export const route = { matchFilters: { locale: locales, },};export default function LocaleLayout(props: RouteSectionProps) { return <>{props.children}</>;}@solidjs/routerdéveloppe:locale?en deux motifs — un avec le segment et un sans — et les tente par ordre de spécificité décroissante.matchFiltersest ce qui fait la différence entre une configuration fonctionnelle et une configuration confuse :Afficher tout le contenu du tableauOuvrir le tableau dans une fenêtre modale pour voir tout le contenu clairement
URL Sans matchFiltersAvec matchFilters/fr/aboutPage à propos en français Page à propos en français /aboutPage à propos (le segment statique gagne) Page à propos /unknownPage d'accueil, silencieusement, avec locale=unknownPas de correspondance → passe au 404 global Préférez
[locale](obligatoire) à[[locale]]si vous utilisez le mode de routage'prefix-all', et supprimez complètement le segment pour'no-prefix'ou'search-params'.Fournir la locale à votre application
L'URL est la source unique de vérité pour la locale : le middleware a déjà redirigé la requête vers son chemin localisé, donc lire le chemin dans le layout racine maintient le rendu serveur et l'hydratation client en accord, et permet à chaque navigation côté client de mettre à jour la locale gratuitement.
src/app.tsxCopier le codeCopier le code dans le presse-papiers
import { MetaProvider } from "@solidjs/meta";import { Router, useLocation } from "@solidjs/router";import { FileRoutes } from "@solidjs/start/router";import { defaultLocale, getHTMLTextDir, getLocaleFromPath } from "intlayer";import { IntlayerProvider } from "solid-intlayer";import { createEffect, type ParentProps, Suspense } from "solid-js";import { isServer } from "solid-js/web";import { Nav } from "~/components/Nav";import "./app.css";const RootLayout = (props: ParentProps) => { const location = useLocation(); const locale = () => getLocaleFromPath(location.pathname) ?? defaultLocale; // Le serveur rend <html> dans entry-server.tsx ; les navigations côté client // entre les locales doivent mettre à jour les attributs elles-mêmes. createEffect(() => { if (isServer) return; document.documentElement.lang = locale(); document.documentElement.dir = getHTMLTextDir(locale()); }); return ( <MetaProvider> <IntlayerProvider locale={locale()}> <Nav /> <Suspense>{props.children}</Suspense> </IntlayerProvider> </MetaProvider> );};export default function App() { return ( <Router root={RootLayout}> <FileRoutes /> </Router> );}IntlayerProviderréagit à sa proplocale, donc passer l'appel d'accesseurlocale()dans le JSX est suffisant — Solid le compile en un getter, et l'ensemble de l'arbre se ré-affiche dans la nouvelle langue lorsque l'URL change.Définir les attributs HTML lang et dir sur le serveur
L'élément
<html>est rendu parentry-server.tsx, en dehors duRouter. Lisez plutôt la locale depuis l'URL de la requête :src/entry-server.tsxCopier le codeCopier le code dans le presse-papiers
// @refresh reloadimport { createHandler, StartServer } from "@solidjs/start/server";import { defaultLocale, getHTMLTextDir, getLocaleFromPath } from "intlayer";import { getRequestEvent } from "solid-js/web";export default createHandler(() => ( <StartServer document={({ assets, children, scripts }) => { const url = getRequestEvent()?.request.url ?? "/"; const locale = getLocaleFromPath(url) ?? defaultLocale; return ( <html dir={getHTMLTextDir(locale)} lang={locale}> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="icon" href="/favicon.ico" /> {assets} </head> <body> <div id="app">{children}</div> {scripts} </body> </html> ); }} />));Les robots d'indexation reçoivent désormais la bonne langue dès le premier octet :
htmlCopier le codeCopier le code dans le presse-papiers
<html dir="ltr" lang="fr"></html>Utiliser Intlayer dans vos pages
Accédez à vos dictionnaires de contenu dans l'ensemble de votre application :
src/routes/[[locale]]/index.tsxCopier le codeCopier le code dans le presse-papiers
import { Meta, Title } from "@solidjs/meta";import { useIntlayer } from "solid-intlayer";import Counter from "~/components/Counter";export default function Home() { const content = useIntlayer("home-page"); return ( <main> <Title>{content.metaTitle.value}</Title> <Meta content={content.metaDescription.value} name="description" /> <h1>{content.title}</h1> <Counter /> <p>{content.documentation}</p> </main> );}Dans Solid,
useIntlayerrenvoie du contenu réactif (ex.content). Vous pouvez accéder directement à ses propriétés.Si vous souhaitez utiliser votre contenu dans un attribut
string, tel quealt,title,href,aria-label, etc., vous pouvez utiliser la valeur de la fonction, comme :htmlCopier le codeCopier le code dans le presse-papiers
<img src="{content.image.src.value}" alt="{content.image.value}" /><img src="{content.image.src.toString()}" alt="{content.image.toString()}" /><img src="{String(content.image.src)}" alt="{String(content.image)}" />Pour en savoir plus sur le hook
useIntlayer, reportez-vous à la documentation.Les nœuds de contenu ne se limitent pas à de simples traductions. Un compteur pluralisé, par exemple :
src/components/Counter.content.tsCopier le codeCopier le code dans le presse-papiers
import { type Dictionary, plural, t } from "intlayer";const counterContent = { key: "counter", content: { clicks: plural({ one: t({ en: "{{count}} click", fr: "{{count}} clic", es: "{{count}} clic", }), other: t({ en: "{{count}} clicks", fr: "{{count}} clics", es: "{{count}} clics", }), }), },} satisfies Dictionary;export default counterContent;src/components/Counter.tsxCopier le codeCopier le code dans le presse-papiers
import { useIntlayer } from "solid-intlayer";import { createSignal } from "solid-js";export default function Counter() { const [count, setCount] = createSignal(0); const content = useIntlayer("counter"); return ( <button onClick={() => setCount(count() + 1)} type="button"> {content.clicks(count())} </button> );}plural()sélectionne la catégorie viaIntl.PluralRulespour la locale active, ainsi les langues ayant plus de deux formes pluriel fonctionnent sans aucun code supplémentaire.Créer un composant Link localisé
Créez un composant
Linkpersonnalisé qui préfixe automatiquement les URL internes avec la langue actuelle :src/components/LocalizedLink.tsxCopier le codeCopier le code dans le presse-papiers
import { A, type AnchorProps } from "@solidjs/router";import { getLocalizedUrl } from "intlayer";import { useLocale } from "solid-intlayer";import type { ParentComponent } from "solid-js";export const LocalizedLink: ParentComponent<AnchorProps> = (props) => { const { locale } = useLocale(); const isExternal = () => /^[a-z][a-z0-9+.-]*:/i.test(props.href); const localizedHref = () => isExternal() ? props.href : getLocalizedUrl(props.href, locale()); return <A {...props} href={localizedHref()} />;};src/components/Nav.tsxCopier le codeCopier le code dans le presse-papiers
import { useIntlayer } from "solid-intlayer";import type { Component } from "solid-js";import { LocaleSwitcher } from "./LocaleSwitcher";import { LocalizedLink } from "./LocalizedLink";export const Nav: Component = () => { const content = useIntlayer("nav"); return ( <nav> <LocalizedLink href="/">{content.home}</LocalizedLink> <LocalizedLink href="/about">{content.about}</LocalizedLink> <LocaleSwitcher /> </nav> );};Écrire
href="/about"une seule fois produit désormais/about,/fr/aboutou/es/aboutselon la locale active — aucun préfixage manuel n'est nécessaire dans vos pages.Créer un composant de changement de locale
Rendez le sélecteur sous forme de vrais ancres plutôt qu'un
<select>: chaque langue de la page actuelle devient un lien explorable pouvant être ouvert dans un nouvel onglet, ce qu'un contrôle uniquement basé sur JavaScript ne peut pas offrir.getPathWithoutLocalesupprime le segment de locale du chemin actuel, etgetLocalizedUrlle reconstruit pour la locale cible, afin que les liens suivent votre mode de routage sans rien coder en dur. La navigation est ce qui modifie la locale rendue — la route[[locale]]la déduit de l'URL — tandis quesetLocalepersiste le choix dans le cookieINTLAYER_LOCALEafin qu'une visite ultérieure sur une URL sans locale soit résolue dans la même langue.src/components/LocaleSwitcher.tsxCopier le codeCopier le code dans le presse-papiers
import { A, useLocation } from "@solidjs/router"; import { getHTMLTextDir, getLocaleName, getLocalizedUrl, getPathWithoutLocale, } from "intlayer"; import { useIntlayer, useLocale } from "solid-intlayer"; import { type Component, For } from "solid-js"; export const LocaleSwitcher: Component = () => { const content = useIntlayer("locale-switcher"); const location = useLocation(); const { locale, setLocale, availableLocales } = useLocale(); // Chemin canonique (sans locale) de la page actuellement affichée const pathWithoutLocale = () => getPathWithoutLocale(location.pathname); return ( <div> <button aria-label={content.label.value} popoverTarget="localePopover" type="button" > {getLocaleName(locale())} </button> <div id="localePopover" popover="auto"> <For each={availableLocales}> {(localeItem) => ( <A dir={getHTMLTextDir(localeItem)} // Correspondance exacte uniquement, afin que le lien de la locale par défaut ne soit pas marqué // actif sur chaque page end href={getLocalizedUrl(pathWithoutLocale(), localeItem)} hreflang={localeItem} lang={localeItem} onClick={() => setLocale(localeItem)} // S'assure que le bouton "retour" du navigateur revienne à la page précédente replace > {/* Langue dans sa propre locale - ex. Français */} {getLocaleName(localeItem)} </A> )} </For> </div> </div> ); };Dans Solid,
localeprovenant deuseLocaleest un accesseur de signal. Utilisezlocale()(avec parenthèses) pour lire sa valeur actuelle de manière réactive.getLocaleName(localeItem)rend chaque langue dans sa propre langue —English / Français / Español. Passez un second argument pour traduire les noms dans la langue actuellement affichée à la place :getLocaleName(localeItem, locale())donneEnglish / French / Spanishen anglais,anglais / français / espagnolen français.<A>définit déjàaria-current="page"sur le lien correspondant à l'URL actuelle, il n'y a donc rien à ajouter pour cela.replaceest lu depuis l'attribut rendu par le routeur : il remplace l'entrée d'historique au lieu d'en ajouter une, ainsi le bouton "retour" du navigateur revient à la page visitée avant le changement plutôt qu'à la même page dans la langue précédente.direthreflangsur chaque lien permettent de conserver les noms de langues de droite à gauche correctement orientés et d'indiquer aux technologies d'assistance et aux robots d'indexation la langue vers laquelle pointe chaque lien.Pour en savoir plus sur le hook
useLocale, reportez-vous à la documentation.Émettre les liens canoniques et hreflang
FacultatifLes annotations
hreflangindiquent aux moteurs de recherche que/about,/fr/aboutet/es/aboutreprésentent la même page dans des langues différentes.getMultilingualUrlsles déduit du chemin canonique (sans locale), en suivant votre mode de routage, afin que rien ne soit codé en dur :src/components/AlternateLinks.tsxCopier le codeCopier le code dans le presse-papiers
import { defaultLocale, getMultilingualUrls, getPathWithoutLocale,} from "intlayer";import { type Component, For } from "solid-js";export type AlternateLinksProps = { /** URL absolue de la page en cours de rendu. */ url: string;};export const AlternateLinks: Component<AlternateLinksProps> = (props) => { const multilingualUrls = () => { const { origin, pathname } = new URL(props.url); return Object.entries( getMultilingualUrls(`${origin}${getPathWithoutLocale(pathname)}`) ); }; const canonicalUrl = () => new URL(props.url).origin + new URL(props.url).pathname; return ( <> <link href={canonicalUrl()} rel="canonical" /> <For each={multilingualUrls()}> {([locale, localizedUrl]) => ( <link href={localizedUrl} hreflang={locale} rel="alternate" /> )} </For> <link href={ multilingualUrls().find(([locale]) => locale === defaultLocale)?.[1] } hreflang="x-default" rel="alternate" /> </> );};Rendez-le dans l'en-tête du document, où l'URL de la requête est disponible :
src/entry-server.tsxCopier le codeCopier le code dans le presse-papiers
import { AlternateLinks } from "~/components/AlternateLinks";// … à l'intérieur de <head>, à côté des autres balises meta :<AlternateLinks url={url} />;GET /fr/aboutsert alors :htmlCopier le codeCopier le code dans le presse-papiers
<link href="https://example.com/fr/about" rel="canonical" /><link href="https://example.com/about" hreflang="en" rel="alternate" /><link href="https://example.com/fr/about" hreflang="fr" rel="alternate" /><link href="https://example.com/es/about" hreflang="es" rel="alternate" /><link href="https://example.com/about" hreflang="x-default" rel="alternate" />Note sur
@solidjs/meta: au moment d'écrire ces lignes,<Title>et<Meta>de@solidjs/metasont appliqués sur le client après l'hydratation mais ne sont pas émis dans le<head>rendu côté serveur dans SolidStart v2. En attendant que cela soit corrigé en amont, rendez les balises que les robots doivent voir sans JavaScript —canonical,hreflang, et si nécessairetitle/description— directement dansentry-server.tsx, comme montré ci-dessus.Gérer les pages non trouvées
FacultatifUne route splat à la racine de
src/routesintercepte tous les chemins que le segment de locale n'a pas fait correspondre — y compris les préfixes de locale invalides rejetés parmatchFilters. Parce que la locale provient toujours de l'URL à travers le layout racine, la page 404 est affichée dans la langue du visiteur :src/routes/[...404].tsxCopier le codeCopier le code dans le presse-papiers
import { Title } from "@solidjs/meta";import { HttpStatusCode } from "@solidjs/start";import { useIntlayer } from "solid-intlayer";import { LocalizedLink } from "~/components/LocalizedLink";export default function NotFound() { const content = useIntlayer("not-found-page"); return ( <main> <Title>{content.metaTitle.value}</Title> <HttpStatusCode code={404} /> <h1>{content.title}</h1> <LocalizedLink href="/">{content.backHome}</LocalizedLink> </main> );}Afficher tout le contenu du tableauOuvrir le tableau dans une fenêtre modale pour voir tout le contenu clairement
Requête Résultat /xx404—xxn'est pas une locale configurée/nonexistent404dans la locale par défaut/fr/nonexistent404en français (Page introuvable)Générer un sitemap multilingue
FacultatifLe générateurs de sitemap d'Intlayer étend chaque chemin en une entrée par locale et câble les alternatives
xhtml:linkentre elles, de sorte que la route n'a qu'à lister les chemins canoniques sans locale.Contrairement aux générateurs de base qui n'émettent que des URL plates, Intlayer câble des liens bidirectionnels entre chaque variante localisée de chaque page, ce qui aide les moteurs de recherche à relier les URL localisées et à servir la bonne au bon public.
SolidStart transforme un fichier exportant une méthode HTTP en route d'API, et supprime l'extension
.tsdu chemin — ainsisrc/routes/sitemap.xml.tsest servi sur/sitemap.xml:src/routes/sitemap.xml.tsCopier le codeCopier le code dans le presse-papiers
import type { APIEvent } from "@solidjs/start/server"; import { generateSitemap } from "intlayer"; const SITE_URL = process.env.SITE_URL ?? "http://localhost:3000"; export const GET = (_event: APIEvent) => { const sitemap = generateSitemap( [ { path: "/", changefreq: "daily", priority: 1.0 }, { path: "/about", changefreq: "monthly", priority: 0.8 }, ], { siteUrl: SITE_URL } ); return new Response(sitemap, { headers: { "Content-Type": "application/xml" }, }); };sortie de GET /sitemap.xmlCopier le codeCopier le code dans le presse-papiers
<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:xhtml="http://www.w3.org/1999/xhtml"> <url> <loc>https://example.com/about</loc> <changefreq>monthly</changefreq> <priority>0.8</priority> <xhtml:link rel="alternate" hreflang="en" href="https://example.com/about"/> <xhtml:link rel="alternate" hreflang="fr" href="https://example.com/fr/about"/> <xhtml:link rel="alternate" hreflang="es" href="https://example.com/es/about"/> <xhtml:link rel="alternate" hreflang="x-default" href="https://example.com/about"/> </url></urlset>Les routes d'API ne prennent pas en charge les paramètres optionnels, conservez donc ce fichier à la racine de
src/routes, en dehors du segment[[locale]]. Le sitemap contient déjà chaque locale.Vous pouvez construire un
robots.txtde la même manière avecgetMultilingualUrls, de sorte que les entréesDisallowcouvraient chaque orthographe localisée d'un chemin sensible :src/routes/robots.txt.tsCopier le codeCopier le code dans le presse-papiers
import { getMultilingualUrls } from "intlayer"; const SITE_URL = process.env.SITE_URL ?? "http://localhost:3000"; const disallowedPaths = ["/admin", "/private"].flatMap((path) => Object.values(getMultilingualUrls(path)) ); export const GET = () => new Response( [ "User-agent: *", "Allow: /", ...disallowedPaths.map((path) => `Disallow: ${path}`), "", `Sitemap: ${SITE_URL}/sitemap.xml`, ].join("\n"), { headers: { "Content-Type": "text/plain" } } );Récupérer la locale dans vos fonctions serveur
FacultatifVous souhaiterez peut-être accéder à la locale actuelle depuis une fonction serveur ou une route d'API.
Dans une configuration basée sur des préfixes comme celle-ci, l'URL fait foi :
getLocaleFromPathlit le préfixe depuis l'URL de la requête.getLocaleest la solution de repli pour les requêtes qui ne portent pas de préfixe de locale — elle inspecte le cookieINTLAYER_LOCALE, puis l'en-têtex-intlayer-locale, puis négocieAccept-Language.src/routes/[[locale]]/index.tsxCopier le codeCopier le code dans le presse-papiers
import { createAsync } from "@solidjs/router";import { getCookie, getIntlayer, getLocale, getLocaleFromPath } from "intlayer";import { getRequestEvent } from "solid-js/web";const loadLocalizedData = async () => { "use server"; const request = getRequestEvent()?.request; const locale = getLocaleFromPath(request?.url) ?? (await getLocale({ // Récupérer le cookie depuis la requête (par défaut : 'INTLAYER_LOCALE') getCookie: (name) => getCookie(name, request?.headers.get("cookie") ?? ""), // Récupérer l'en-tête depuis la requête (par défaut : 'x-intlayer-locale'), // avec repli sur la négociation Accept-Language getHeader: (name) => request?.headers.get(name) ?? undefined, })); // Récupérer du contenu en dehors d'un composant en utilisant getIntlayer() const content = getIntlayer("home-page", locale); return { locale, title: String(content.title) };};export default function Page() { const data = createAsync(() => loadLocalizedData()); return <p>{data()?.title}</p>;}Ne vous fiez pas uniquement à
getLocaleici : le cookie de locale n'est écrit qu'une fois qu'un visiteur change activement de langue, donc une première visite sur/fr/...serait résolue avec la locale par défaut.Extraire le contenu de vos composants
FacultatifSi vous avez une base de code existante, transformer des milliers de fichiers peut prendre du temps.
Pour faciliter ce processus, Intlayer propose un compilateur / extracteur pour transformer vos composants et en extraire le contenu.
Pour le configurer, vous pouvez ajouter une section
compilerdans votre fichierintlayer.config.ts:intlayer.config.tsCopier le codeCopier le code dans le presse-papiers
import { type IntlayerConfig } from "intlayer"; const config: IntlayerConfig = { // ... Reste de votre configuration compiler: { /** * Indique si le compilateur doit être activé. */ enabled: true, /** * Définit le chemin des fichiers de sortie */ output: ({ fileName, extension }) => `./${fileName}${extension}`, /** * Indique si les composants doivent être enregistrés après avoir été transformés. * * - Si `true`, le compilateur réécrira le fichier du composant sur le disque. La transformation sera donc permanente et le compilateur ignorera la transformation lors du processus suivant. De cette façon, le compilateur peut transformer l'application, puis être retiré. * * - Si `false`, le compilateur injectera l'appel de fonction `useIntlayer()` dans le code dans le résultat du build uniquement, et gardera la base de code intacte. La transformation sera effectuée uniquement en mémoire. */ saveComponents: false, /** * Préfixe de clé de dictionnaire */ dictionaryKeyPrefix: "", }, }; export default config;Exécutez l'extracteur pour transformer vos composants et extraire le contenu
bashCopier le codeCopier le code dans le presse-papiers
npx intlayer extractDéplacez ensuite les fichiers de contenu générés de vos pages hors de
src/routes, pour la raison expliquée à l'étape 5.Configurer TypeScript
Intlayer utilise l'augmentation de module pour bénéficier des avantages de TypeScript et rendre votre base de code plus solide.
Assurez-vous que votre configuration TypeScript inclut les types générés automatiquement :
tsconfig.jsonCopier le codeCopier le code dans le presse-papiers
{ compilerOptions: { // ... vos configurations existantes }, include: [ "src", "*.ts", ".intlayer/**/*.ts", // Inclure les types générés automatiquement ],}Les clés de dictionnaire et les chemins de contenu sont désormais vérifiés au moment de la compilation :
tsxCopier le codeCopier le code dans le presse-papiers
useIntlayer("home-page"); // ✅useIntlayer("hom-page"); // ❌ Argument of type '"hom-page"' is not assignable to parameter of type 'keyof __DictionaryRegistry'
Vérification de votre configuration
Construisez et démarrez le serveur, puis vérifiez que ces requêtes se comportent comme prévu :
Copier le code dans le presse-papiers
npm run buildnode .output/server/index.mjsOuvrir le tableau dans une fenêtre modale pour voir tout le contenu clairement
| Requête | Réponse attendue |
|---|---|
GET / | 200 — Anglais |
GET / avec Accept-Language: fr | 302 → /fr |
GET / avec cookie INTLAYER_LOCALE=es | 302 → /es |
GET /fr | 200 — Français, <html lang="fr"> |
GET /fr/about | 200 — Page à propos en français |
GET /en/about | 302 → /about (redirection canonique) |
GET /xx | 404 |
GET /fr/nonexistent | 404 en français |
GET /sitemap.xml | 200 — Sitemap XML multilingue |
Les lignes qui rendent une page se comportent à l'identique sous vite dev. Les trois lignes de redirection s'appliquent uniquement à un serveur construit, sauf si vous enregistrez vous-même le gestionnaire comme middleware — voir l'étape 3.
Exécutez le serveur dev sur Node (vite dev) plutôt que sur Bun (bun --bun vite dev) : le SSR de SolidStart échoue actuellement sous le runtime Bun avecExpected a Response object, but received 'NodeResponse'. Ceci n'a aucun lien avec Intlayer — cela se reproduit sur le modèle de base — et n'affecte que le serveur dev, pasvite build.
Configuration Git
Il est recommandé d'ignorer les fichiers générés par Intlayer. Cela vous permet d'éviter de les commiter dans votre dépôt Git.
Pour ce faire, vous pouvez ajouter les instructions suivantes à votre fichier .gitignore :
Copier le code dans le presse-papiers
# Ignorer les fichiers générés par Intlayer.intlayerExtension VS Code
Pour améliorer votre expérience de développement avec Intlayer, vous pouvez installer l'extension VS Code officielle Intlayer.
Installer depuis le VS Code Marketplace
Cette extension fournit :
- L'autocomplétion pour les clés de traduction.
- La détection d'erreurs en temps réel pour les traductions manquantes.
- Aperçus en ligne du contenu traduit.
- Actions rapides pour créer et mettre à jour facilement les traductions.
Pour aller plus loin
Pour aller plus loin, vous pouvez implémenter l'éditeur visuel ou externaliser votre contenu à l'aide du CMS.