Pose una domanda e ottieni un riassunto del documento facendo riferimento a questa pagina e al provider AI di tua scelta
Cronologia delle versioni
- "Storia iniziale"v9.1.306/08/2025
Il contenuto di questa pagina è stato tradotto con un'IA.
Vedi l'ultima versione del contenuto originale in ingleseIf 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
Traduci il tuo sito web SolidStart usando Intlayer | Internazionalizzazione (i18n)
Indice
Questa guida copre un'applicazione SolidStart renderizzata lato server: il rilevamento della locale avviene sulla richiesta, le pagine vengono renderizzate sul server nella lingua corretta e i segnali <html lang>, hreflang e sitemap di cui i motori di ricerca hanno bisogno vengono emessi lato server.
Perché Intlayer rispetto alle alternative?
Rispetto alle principali soluzioni come @solid-primitives/i18n o i18next, Intlayer è una soluzione dotata di ottimizzazioni integrate come:
Intlayer è ottimizzato per funzionare perfettamente con Solid offrendo scoping del contenuto a livello di componente, traduzioni reattive e tutte le funzionalità necessarie per scalare l'internazionalizzazione (i18n).
Invece di caricare enormi file JSON nelle tue pagine, carica solo il contenuto necessario. Intlayer aiuta a ridurre le dimensioni del tuo bundle e delle tue pagine fino al 50%.
Definire l'ambito del contenuto della tua applicazione facilita la manutenzione per le applicazioni su larga scala. Puoi duplicare o eliminare una singola cartella di funzionalità senza l'onere mentale di rivedere l'intera codebase del contenuto. Inoltre, Intlayer è completamente tipizzato per garantire la precisione del tuo contenuto.
Collocare il contenuto riduce il contesto necessario per i modelli di linguaggio di grandi dimensioni (LLM). Intlayer è inoltre fornito con una suite di strumenti, come una CLI per verificare le traduzioni mancanti, LSP, MCP e competenze dell'agente, per rendere l'esperienza di sviluppo (DX) ancora più fluida per gli agenti AI.
Utilizza l'automazione per tradurre nella tua pipeline CI/CD utilizzando l'LLM di tua scelta al costo del tuo fornitore AI. Intlayer offre anche un compilatore per automatizzare l'estrazione del contenuto, oltre a una piattaforma web per aiutare a tradurre in background.
Connettere enormi file JSON ai componenti può causare problemi di prestazioni e reattività. Intlayer ottimizza il caricamento del contenuto al momento della build.
Molto più di una semplice soluzione i18n, Intlayer fornisce un editor visuale self-hosted e un CMS completo per aiutarti a gestire il tuo contenuto multilingue in tempo reale, rendendo la collaborazione con traduttori, copywriter e altri membri del team semplice e fluida. Il contenuto può essere archiviato localmente e/o da remoto.
Guida passo dopo passo per configurare Intlayer in un'applicazione SolidStart
Installa le dipendenze
Installa i pacchetti necessari utilizzando npm:
bashCopiare il codiceCopiare il codice nella clipboard
npx intlayer init --interactiveil flag
--interactiveè opzionale. Usaintlayer-cli initse sei un agente AI.Questo comando rileverà il tuo ambiente e installerà i pacchetti richiesti. Ad esempio:
bashCopiare il codiceCopiare il codice nella clipboard
npm install intlayer solid-intlayer vite-intlayerintlayer
Il pacchetto principale che fornisce strumenti di internazionalizzazione per la gestione della configurazione, traduzione, dichiarazione del contenuto, transpilazione e comandi CLI.
solid-intlayer
Il pacchetto che integra Intlayer con l'applicazione Solid. Fornisce provider di contesto e hook per l'internazionalizzazione in Solid.
vite-intlayer
Include il plugin Vite per integrare Intlayer con il bundler Vite, oltre al gestore di routing delle impostazioni locali che rileva la locale preferita dall'utente, gestisce i cookie e gestisce il reindirizzamento degli URL.
vite-intlayerè una questione lato server in questo contesto, non solo di build time: fornisce il gestore di richieste eseguito dal server Nitro di SolidStart. Mantenerlo independenciesè l'opzione predefinita sicura — puoi spostarlo indevDependenciessolo se distribuisci la cartella.outputcreata, nella quale Nitro include direttamente il gestore.Configurazione del tuo progetto
Crea un file di configurazione per configurare le lingue della tua applicazione:
intlayer.config.tsCopiare il codiceCopiare il codice nella clipboard
import { type IntlayerConfig, Locales } from "intlayer"; const config: IntlayerConfig = { internationalization: { locales: [ Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH, // Le tue altre impostazioni locali ], defaultLocale: Locales.ENGLISH, }, routing: { mode: "prefix-no-default", }, }; export default config;Con
prefix-no-default, la locale predefinita viene servita da URL senza prefisso:plaintextCopiare il codiceCopiare il codice nella clipboard
/ /about → Inglese (locale predefinita)/fr /fr/about → Francese/es /es/about → SpagnoloAttraverso questo file di configurazione, puoi impostare URL localizzati, reindirizzamenti middleware, nomi di cookie, la posizione e l'estensione delle tue dichiarazioni di contenuto, disabilitare i log di Intlayer nella console e altro ancora. Per un elenco completo dei parametri disponibili, fai riferimento alla documentazione sulla configurazione.
Integra Intlayer nella tua configurazione Vite
Aggiungi il plugin Intlayer alla tua configurazione:
vite.config.tsCopiare il codiceCopiare il codice nella clipboard
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()], });Il plugin Vite
intlayer()crea i tuoi file di dichiarazione del contenuto, li osserva in modalità di sviluppo e definisce le variabili di ambiente Intlayer all'interno dell'applicazione. Fornisce inoltre alias che ottimizzano le prestazioni.Il routing delle impostazioni locali viene fornito con il plugin
SolidStart viene eseguito su Nitro, e
intlayer()registra il suo gestore di routing delle impostazioni locali direttamente nella pipeline del server Nitro (tramite l'opzionerouting.enableProxy,truedi default). Nient'altro da collegare: su un server compilato, ogni richiesta viene ispezionata prima che raggiunga il router, e- la locale viene letta dal prefisso URL, quindi dal cookie
INTLAYER_LOCALE, quindi dall'intestazioneAccept-Language; - un URL senza prefisso viene reindirizzato alla sua controparte localizzata quando la locale risolta non è quella predefinita (
/→/fr); - un URL con prefisso ridondante viene reindirizzato alla sua forma canonica (
/en/about→/about); - il cookie della locale viene riscritto nella risposta.
- la locale viene letta dal prefisso URL, quindi dal cookie
Dichiara il tuo contenuto
Crea e gestisci le tue dichiarazioni di contenuto per archiviare le traduzioni:
src/contents/home.content.tsCopiare il codiceCopiare il codice nella clipboard
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;⚠️ Particolarità di SolidStart: ogni file
.ts/.tsxsottosrc/routesdiventa una rotta, e un file.content.tsha un'esportazione predefinita, quindi verrebbe interpretato come una pagina. Mantieni le dichiarazioni di contenuto delle tue pagine all'esterno della cartella delle rotte (src/contents/funziona benissimo). Il contenuto dei componenti può rimanere co-localizzato, poichésrc/componentsnon viene scansionato dal router del file system.Le tue dichiarazioni di contenuto possono essere definite ovunque nella tua applicazione a condizione che siano incluse nella cartella
contentDir(di default,./src), e corrispondano all'estensione del file di dichiarazione di contenuto (di default,.content.{json,ts,tsx,js,jsx,mjs,cjs,md,mdx,yaml,yml}).Per maggiori dettagli, fai riferimento alla documentazione sulla dichiarazione del contenuto.
Aggiungi il routing localizzato
L'obiettivo di questo passaggio è fornire a ciascuna lingua il proprio URL, che è quello che i motori di ricerca indicizzano.
Sposta le tue pagine sotto un segmento dinamico opzionale. Nel router basato su file system di SolidStart,
[[locale]]viene compilato nel pattern di percorso:locale?:plaintextCopiare il codiceCopiare il codice nella clipboard
src/routes/ [[locale]].tsx ← layout che convalida il segmento [[locale]]/ index.tsx → / e /fr e /es about.tsx → /about e /fr/about e /es/about [...404].tsx → catch-all per qualsiasi altra cosaL'unico compito del file di layout è limitare il segmento a una locale configurata:
src/routes/[[locale]].tsxCopiare il codiceCopiare il codice nella clipboard
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/routerespande:locale?in due pattern — uno con il segmento e uno senza — e li prova per specificità decrescente.matchFiltersè ciò che fa la differenza tra una configurazione funzionante e una confusa:Mostra tutto il contenuto della tabellaApri la tabella in una finestra modale per visualizzare tutti i dati in modo chiaro
URL Senza matchFiltersCon matchFilters/fr/aboutPagina informazioni in francese Pagina informazioni in francese /aboutPagina informazioni (vince il segmento statico) Pagina informazioni /unknownHome page, silenziosamente, con locale=unknownNessuna corrispondenza → passa al 404 generale Preferisci
[locale](obbligatorio) a[[locale]]se usi la modalità di routing'prefix-all', ed elimina completamente il segmento per'no-prefix'o'search-params'.Fornire le impostazioni locali alla tua applicazione
L'URL è l'unica fonte di verità per la locale: il middleware ha già reindirizzato la richiesta al suo percorso localizzato, quindi leggere il percorso nel layout principale mantiene in accordo il rendering lato server e l'idratazione lato client, e fa in modo che ogni navigazione lato client aggiorni la locale gratuitamente.
src/app.tsxCopiare il codiceCopiare il codice nella clipboard
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; // Il server renderizza <html> in entry-server.tsx; le navigazioni lato client // tra le impostazioni locali devono aggiornare gli attributi da sole. 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> );}IntlayerProviderreagisce alla sua proplocale, quindi passare la chiamata all'accessorlocale()all'interno di JSX è sufficiente — Solid lo compila in un getter e l'intero albero viene nuovamente renderizzato nella nuova lingua quando l'URL cambia.Imposta gli attributi HTML lang e dir sul server
L'elemento
<html>viene renderizzato daentry-server.tsx, all'esterno delRouter. Leggi la locale dall'URL della richiesta:src/entry-server.tsxCopiare il codiceCopiare il codice nella clipboard
// @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> ); }} />));I crawler ora ricevono la lingua corretta fin dal primo byte:
htmlCopiare il codiceCopiare il codice nella clipboard
<html dir="ltr" lang="fr"></html>Utilizza Intlayer nelle tue pagine
Accedi ai tuoi dizionari di contenuto in tutta la tua applicazione:
src/routes/[[locale]]/index.tsxCopiare il codiceCopiare il codice nella clipboard
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> );}In Solid,
useIntlayerrestituisce contenuto reattivo (ad es.content). Puoi accedere direttamente alle sue proprietà.Se desideri utilizzare il tuo contenuto in un attributo
string, comealt,title,href,aria-label, ecc., puoi utilizzare il valore della funzione, come:htmlCopiare il codiceCopiare il codice nella clipboard
<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)}" />Per saperne di più sull'hook
useIntlayer, fai riferimento alla documentazione.I nodi di contenuto non si limitano a semplici traduzioni. Un contatore con pluralizzazione, ad esempio:
src/components/Counter.content.tsCopiare il codiceCopiare il codice nella clipboard
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.tsxCopiare il codiceCopiare il codice nella clipboard
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()seleziona la categoria tramiteIntl.PluralRulesper la locale attiva, in modo che le lingue con più di due forme plurali funzionino senza alcun codice aggiuntivo.Crea un componente Link localizzato
Crea un componente
Linkpersonalizzato che aggiunge automaticamente il prefisso della lingua corrente agli URL interni:src/components/LocalizedLink.tsxCopiare il codiceCopiare il codice nella clipboard
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.tsxCopiare il codiceCopiare il codice nella clipboard
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> );};Scrivere
href="/about"una volta produce ora/about,/fr/abouto/es/abouta seconda della locale attiva — nessun prefisso manuale in nessuna parte delle tue pagine.Crea un componente per il cambio di lingua
Renderizza il selettore come ancore reali piuttosto che come uno
<select>: ogni lingua della pagina corrente diventa un link indicizzabile che può essere aperto in una nuova scheda, cosa che un controllo basato unicamente su JavaScript non può offrire.getPathWithoutLocalerimuove il segmento della locale dal percorso corrente, egetLocalizedUrllo ricostruisce per la locale di destinazione, in modo che i link seguano la tua modalità di routing senza dover codificare nulla in modo rigido. La navigazione è ciò che modifica la locale renderizzata — la rotta[[locale]]la ricava dall'URL — mentresetLocalememorizza la scelta nel cookieINTLAYER_LOCALEin modo che una successiva visita a un URL privo di locale si risolva nella stessa lingua.src/components/LocaleSwitcher.tsxCopiare il codiceCopiare il codice nella clipboard
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(); // Percorso canonico (senza locale) della pagina attualmente visualizzata 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)} // Solo corrispondenza esatta, in modo che il link della locale predefinita non sia contrassegnato // come attivo su ogni pagina end href={getLocalizedUrl(pathWithoutLocale(), localeItem)} hreflang={localeItem} lang={localeItem} onClick={() => setLocale(localeItem)} // Assicura che il pulsante "indietro" del browser torni alla pagina precedente replace > {/* Lingua nella propria locale - es. Français */} {getLocaleName(localeItem)} </A> )} </For> </div> </div> ); };In Solid,
localedauseLocaleè un accessor di segnale. Usalocale()(con parentesi) per leggere il suo valore corrente in modo reattivo.getLocaleName(localeItem)renderizza ciascuna lingua nella propria lingua —English / Français / Español. Passa un secondo argomento per tradurre i nomi nella lingua attualmente visualizzata:getLocaleName(localeItem, locale())restituisceEnglish / French / Spanishin inglese,anglais / français / espagnolin francese.<A>imposta giàaria-current="page"sul link che corrisponde all'URL corrente, quindi non c'è nulla da aggiungere per quello.replaceviene letto dall'attributo renderizzato dal router: sostituisce la voce di cronologia invece di aggiungerne una nuova, in modo che il pulsante "indietro" del browser torni alla pagina visitata prima del cambio anziché alla stessa pagina nella lingua precedente.direhreflangsu ciascun link mantengono i nomi delle lingue da destra a sinistra orientati correttamente e indicano alle tecnologie assistive e ai crawler a quale lingua punta ciascun link.Per saperne di più sull'hook
useLocale, fai riferimento alla documentazione.Emetti link canonici e hreflang
OpzionaleLe annotazioni
hreflangdicono ai motori di ricerca che/about,/fr/aboute/es/aboutsono la stessa pagina in lingue diverse.getMultilingualUrlsle ricava dal percorso canonico (senza locale), seguendo la tua modalità di routing, in modo che nulla sia codificato in modo rigido:src/components/AlternateLinks.tsxCopiare il codiceCopiare il codice nella clipboard
import { defaultLocale, getMultilingualUrls, getPathWithoutLocale,} from "intlayer";import { type Component, For } from "solid-js";export type AlternateLinksProps = { /** URL assoluto della pagina in fase di rendering. */ 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" /> </> );};Renderizzalo nell'intestazione del documento, dove l'URL della richiesta è disponibile:
src/entry-server.tsxCopiare il codiceCopiare il codice nella clipboard
import { AlternateLinks } from "~/components/AlternateLinks";// … all'interno di <head>, accanto agli altri tag meta:<AlternateLinks url={url} />;GET /fr/aboutrestituisce quindi:htmlCopiare il codiceCopiare il codice nella clipboard
<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" />Nota su
@solidjs/meta: al momento della scrittura,<Title>e<Meta>di@solidjs/metavengono applicati sul client dopo l'idratazione ma non vengono emessi nel<head>renderizzato lato server in SolidStart v2. Fino a quando ciò non verrà risolto a monte, renderizza i tag che i crawler devono vedere senza JavaScript —canonical,hreflange, se necessario,title/description— direttamente inentry-server.tsx, come mostrato sopra.Gestisci le pagine non trovate
OpzionaleUna rotta wildcard (splat) alla radice di
src/routescattura qualsiasi percorso che il segmento locale non ha trovato — compresi i prefissi di locale non validi rifiutati damatchFilters. Poiché la locale proviene comunque dall'URL attraverso il layout di radice, la pagina 404 viene visualizzata nella lingua del visitatore:src/routes/[...404].tsxCopiare il codiceCopiare il codice nella clipboard
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> );}Mostra tutto il contenuto della tabellaApri la tabella in una finestra modale per visualizzare tutti i dati in modo chiaro
Richiesta Risultato /xx404—xxnon è una locale configurata/nonexistent404nella locale predefinita/fr/nonexistent404in francese (Page introuvable)Genera una sitemap multilingue
OpzionaleIl generatore di sitemap di Intlayer espande ogni percorso in una voce per locale e collega le alternative
xhtml:linktra loro, in modo che la rotta debba solo elencare i percorsi canonici e privi di locale.A differenza dei generatori di base che emettono solo URL semplici, Intlayer collega link bidirezionali tra ogni variante localizzata di ciascuna pagina, aiutando i motori di ricerca a mettere in relazione gli URL localizzati e a servire quello corretto al pubblico giusto.
SolidStart trasforma un file che esporta un metodo HTTP in una rotta API e rimuove l'estensione
.tsdal percorso — in questo modosrc/routes/sitemap.xml.tsviene servito su/sitemap.xml:src/routes/sitemap.xml.tsCopiare il codiceCopiare il codice nella clipboard
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" }, }); };output di GET /sitemap.xmlCopiare il codiceCopiare il codice nella clipboard
<?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>Le rotte API non supportano parametri opzionali, quindi mantieni questo file alla radice di
src/routes, all'esterno del segmento[[locale]]. La sitemap contiene già ogni locale.Puoi creare un file
robots.txtallo stesso modo congetMultilingualUrls, in modo che le vociDisallowcoprano ogni ortografia localizzata di un percorso sensibile:src/routes/robots.txt.tsCopiare il codiceCopiare il codice nella clipboard
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" } } );Recupera le impostazioni locali nelle tue funzioni server
OpzionalePotresti voler accedere alla locale corrente dall'interno di una funzione server o di una rotta API.
In una configurazione basata su prefisso come questa, l'URL fa fede:
getLocaleFromPathlegge il prefisso dall'URL della richiesta.getLocaleè il ripiego per le richieste che non trasportano alcun prefisso di locale — ispeziona il cookieINTLAYER_LOCALE, quindi l'intestazionex-intlayer-locale, quindi negoziaAccept-Language.src/routes/[[locale]]/index.tsxCopiare il codiceCopiare il codice nella clipboard
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({ // Ottieni il cookie dalla richiesta (predefinito: 'INTLAYER_LOCALE') getCookie: (name) => getCookie(name, request?.headers.get("cookie") ?? ""), // Ottieni l'intestazione dalla richiesta (predefinito: 'x-intlayer-locale'), // ripiegando sulla negoziazione Accept-Language getHeader: (name) => request?.headers.get(name) ?? undefined, })); // Recupera del contenuto all'esterno di un componente utilizzando 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>;}Non affidarti unicamente a
getLocalequi: il cookie della locale viene scritto solo quando un visitatore cambia attivamente lingua, quindi una prima visita a/fr/...si risolverebbe nella locale predefinita.Estrai il contenuto dei tuoi componenti
OpzionaleSe hai una codebase esistente, trasformare migliaia di file può richiedere molto tempo.
Per facilitare questo processo, Intlayer propone un compilatore / estrattore per trasformare i tuoi componenti ed estrarne il contenuto.
Per configurarlo, puoi aggiungere una sezione
compilernel tuo fileintlayer.config.ts:intlayer.config.tsCopiare il codiceCopiare il codice nella clipboard
import { type IntlayerConfig } from "intlayer"; const config: IntlayerConfig = { // ... Resto della tua configurazione compiler: { /** * Indica se il compilatore deve essere abilitato. */ enabled: true, /** * Definisce il percorso dei file di output */ output: ({ fileName, extension }) => `./${fileName}${extension}`, /** * Indica se i componenti devono essere salvati dopo essere stati trasformati. * * - Se `true`, il compilatore riscriverà il file del componente sul disco. Quindi la trasformazione sarà permanente e il compilatore salterà la trasformazione per il processo successivo. In questo modo, il compilatore può trasformare l'app e poi essere rimosso. * * - Se `false`, il compilatore inietterà la chiamata alla funzione `useIntlayer()` nel codice solo nell'output di build e manterrà intatta la codebase di base. La trasformazione verrà eseguita solo in memoria. */ saveComponents: false, /** * Prefisso chiave del dizionario */ dictionaryKeyPrefix: "", }, }; export default config;Esegui l'estrattore per trasformare i tuoi componenti ed estrarre il contenuto
bashCopiare il codiceCopiare il codice nella clipboard
npx intlayer extractSposta successivamente i file di contenuto generati delle tue pagine fuori da
src/routes, per il motivo spiegato al passaggio 5.Configura TypeScript
Intlayer utilizza l'aumento dei moduli per sfruttare i vantaggi di TypeScript e rendere la tua codebase più solida.
Assicurati che la tua configurazione TypeScript includa i tipi generati automaticamente:
tsconfig.jsonCopiare il codiceCopiare il codice nella clipboard
{ compilerOptions: { // ... le tue configurazioni esistenti }, include: [ "src", "*.ts", ".intlayer/**/*.ts", // Includi i tipi generati automaticamente ],}Le chiavi del dizionario e i percorsi del contenuto vengono ora controllati in fase di compilazione:
tsxCopiare il codiceCopiare il codice nella clipboard
useIntlayer("home-page"); // ✅useIntlayer("hom-page"); // ❌ Argument of type '"hom-page"' is not assignable to parameter of type 'keyof __DictionaryRegistry'
Verifica della configurazione
Compila e avvia il server, quindi verifica che queste richieste si comportino come previsto:
Copiare il codice nella clipboard
npm run buildnode .output/server/index.mjsApri la tabella in una finestra modale per visualizzare tutti i dati in modo chiaro
| Richiesta | Risposta prevista |
|---|---|
GET / | 200 — Inglese |
GET / con Accept-Language: fr | 302 → /fr |
GET / con cookie INTLAYER_LOCALE=es | 302 → /es |
GET /fr | 200 — Francese, <html lang="fr"> |
GET /fr/about | 200 — Pagina informazioni in francese |
GET /en/about | 302 → /about (reindirizzamento canonico) |
GET /xx | 404 |
GET /fr/nonexistent | 404 in francese |
GET /sitemap.xml | 200 — Sitemap XML multilingue |
Le righe che renderizzano una pagina si comportano in modo identico sotto vite dev. Le tre righe di reindirizzamento si applicano solo a un server compilato a meno che tu non registri il gestore come middleware personalmente — vedi passaggio 3.
Esegui il server dev su Node (vite dev) invece che su Bun (bun --bun vite dev): l'SSR di SolidStart al momento fallisce nel runtime Bun conExpected a Response object, but received 'NodeResponse'. Questo non ha alcuna relazione con Intlayer — si riproduce sul template di base — e riguarda solo il server dev, nonvite build.
Configurazione Git
Si consiglia di ignorare i file generati da Intlayer. Ciò consente di evitare di committarli nel repository Git.
A tale scopo, puoi aggiungere le seguenti istruzioni al tuo file .gitignore:
Copiare il codice nella clipboard
# Ignora i file generati da Intlayer.intlayerEstensione VS Code
Per migliorare la tua esperienza di sviluppo con Intlayer, puoi installare l'estensione ufficiale Intlayer per VS Code.
Installa dal VS Code Marketplace
Questa estensione offre:
- Autocompletamento per le chiavi di traduzione.
- Rilevamento degli errori in tempo reale per le traduzioni mancanti.
- Anteprime inline del contenuto tradotto.
- Azioni rapide per creare e aggiornare facilmente le traduzioni.
Per andare oltre
Per andare oltre, puoi implementare l'editor visuale o esternalizzare il tuo contenuto utilizzando il CMS.