Faça sua pergunta e obtenha um resumo do documento referenciando esta página e o provedor AI de sua escolha
Histórico de versões
- "Atualizar o uso da API useIntlayer do Solid para acesso direto a propriedades"v8.9.004/05/2026
- "Adicionado para Tanstack Start Solid.js"v8.5.125/03/2026
O conteúdo desta página foi traduzido com uma IA.
Veja a última versão do conteúdo original em inglêsIf 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
Traduza seu site Tanstack Start com Solid.js usando Intlayer | Internacionalização (i18n)
Índice
Este guia demonstra como integrar o Intlayer para uma internacionalização perfeita em projetos Tanstack Start com Solid.js, roteamento ciente de localidade, suporte a TypeScript e práticas de desenvolvimento modernas.
O que é o Intlayer?
O Intlayer é uma biblioteca de internacionalização (i18n) inovadora e de código aberto, projetada para simplificar o suporte multilíngue em aplicações web modernas.
Com o Intlayer, você pode:
- Gerenciar traduções facilmente usando dicionários declarativos ao nível do componente.
- Localizar metadados, rotas e conteúdo dinamicamente.
- Garantir o suporte a TypeScript com tipos autogerados, melhorando o autocompletar e a detecção de erros.
- Beneficiar-se de recursos avançados, como detecção e troca dinâmica de localidade.
- Habilitar roteamento ciente de localidade com o sistema de roteamento baseado em arquivos do Tanstack Start.
Guia Passo a Passo para Configurar o Intlayer numa Aplicação Tanstack Start
Veja o Modelo de Aplicação no GitHub.
Passo 1: Criar o Projeto
Comece criando um novo projeto TanStack Start seguindo o guia Iniciar novo projeto no site do TanStack Start.
Passo 2: Instalar os Pacotes Intlayer
Instale os pacotes necessários usando o seu gerenciador de pacotes preferido:
Copiar o código para a área de transferência
npm install intlayer solid-intlayernpm install vite-intlayer --save-devnpx intlayer initintlayer
O pacote principal que fornece ferramentas de internacionalização para gerenciamento de configuração, tradução, declaração de conteúdo, transpilação e comandos CLI.
solid-intlayer O pacote que integra o Intlayer com a aplicação Solid. Ele fornece provedores de contexto e hooks para a internacionalização em Solid.
vite-intlayer Inclui o plugin Vite para integrar o Intlayer com o bundler Vite, bem como o middleware para detectar a localidade preferida do usuário, gerenciar cookies e lidar com redirecionamento de URL.
Passo 3: Configuração do seu projeto
Crie um arquivo de configuração para configurar as línguas da sua aplicação:
Copiar o código para a área de transferência
import type { IntlayerConfig } from "intlayer";import { Locales } from "intlayer";const config: IntlayerConfig = { internationalization: { defaultLocale: Locales.ENGLISH, locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH], },};export default config;Através deste arquivo de configuração, você pode configurar URLs localizadas, redirecionamento de middleware, nomes de cookies, a localização e extensão das suas declarações de conteúdo, desativar logs do Intlayer no console e muito mais. Para uma lista completa de parâmetros disponíveis, consulte a documentação de configuração.
Passo 4: Integrar o Intlayer na sua Configuração Vite
Adicione o plugin intlayer na sua configuração:
Copiar o código para a área de transferência
import { intlayer } from "vite-intlayer";import { defineConfig } from "vite";import { devtools } from "@tanstack/devtools-vite";import { tanstackStart } from "@tanstack/solid-start/plugin/vite";import solidPlugin from "vite-plugin-solid";export default defineConfig({ plugins: [ devtools(), tanstackStart({ router: { routeFileIgnorePattern: ".content.(ts|tsx|js|mjs|cjs|jsx|json|jsonc|json5)$", }, }), solidPlugin({ ssr: true }), intlayer(), ],});O plugin Vite intlayer() é usado para integrar o Intlayer com o Vite. Ele garante a construção dos arquivos de declaração de conteúdo e os monitora no modo de desenvolvimento. Ele define as variáveis de ambiente do Intlayer dentro da aplicação Vite. Adicionalmente, ele fornece aliases para otimizar a performance.
Passo 5: Criar o Layout Raiz (Root Layout)
Configure o seu layout raiz para suportar internacionalização usando useParams para detectar a localidade atual e definindo os atributos lang e dir na tag html.
Copiar o código para a área de transferência
import { HeadContent, Scripts, createRootRouteWithContext,} from "@tanstack/solid-router";import { HydrationScript } from "solid-js/web";import { Suspense, type ParentComponent } from "solid-js";import { IntlayerProvider } from "solid-intlayer";import { defaultLocale, getHTMLTextDir } from "intlayer";import { Route as LocaleRoute } from "./{-$locale}/route";export const Route = createRootRouteWithContext()({ shellComponent: RootComponent,});const RootComponent: ParentComponent = (props) => { const params = LocaleRoute.useParams(); const locale = params()?.locale ?? defaultLocale; return ( <html dir={getHTMLTextDir(locale)} lang={locale}> <head> <HydrationScript /> <HeadContent /> </head> <body> <IntlayerProvider locale={locale}> <Suspense>{props.children}</Suspense> </IntlayerProvider> <Scripts /> </body> </html> );};Passo 6: Criar o Layout de Localidade (Opcional)
Crie um layout que lide com o prefixo de localidade e realize a validação. Este layout garantirá que apenas localidades válidas sejam processadas.
Este passo é opcional se você não precisar validar o prefixo de localidade ao nível da rota.
Copiar o código para a área de transferência
import { createFileRoute, Outlet, redirect } from "@tanstack/solid-router";import { validatePrefix } from "intlayer";export const Route = createFileRoute("/{-$locale}")({ beforeLoad: ({ params }) => { const localeParam = params.locale; // Validar o prefixo de localidade const { isValid, localePrefix } = validatePrefix(localeParam); if (!isValid) { throw redirect({ to: "/{-$locale}/404", params: { locale: localePrefix }, replace: true, }); } }, component: Outlet,});Aqui,{-$locale}é um parâmetro de rota dinâmico que é substituído pela localidade atual. Esta notação torna o slot opcional, permitindo que funcione com modos de roteamento como'prefix-no-default'etc.
Esteja ciente de que este slot pode causar problemas se você usar múltiplos segmentos dinâmicos na mesma rota (ex:
/{-$locale}/outro-caminho/$outroCaminhoDinamico/...). Para o modo'prefix-all', você pode preferir mudar o slot para$locale. Para o modo'no-prefix'ou'search-params', você pode remover o slot inteiramente.
Passo 7: Declarar o Seu Conteúdo
Crie e gerencie as suas declarações de conteúdo para armazenar traduções:
Copiar o código para a área de transferência
import type { Dictionary } from "intlayer";import { t } from "intlayer";const appContent = { content: { links: { about: t({ en: "About", es: "Acerca de", fr: "À propos", }), home: t({ en: "Home", es: "Inicio", fr: "Accueil", }), }, meta: { title: t({ en: "Welcome to Intlayer + TanStack Router", es: "Bienvenido a Intlayer + TanStack Router", fr: "Bienvenue à Intlayer + TanStack Router", }), description: t({ en: "This is an example of using Intlayer with TanStack Router", es: "Este es un ejemplo de uso de Intlayer con TanStack Router", fr: "Ceci est un exemple d'utilisation d'Intlayer avec TanStack Router", }), }, }, key: "app",} satisfies Dictionary;export default appContent;As suas declarações de conteúdo podem ser definidas em qualquer lugar da sua aplicação, desde que sejam incluídas no diretóriocontentDir(por padrão,./app). E correspondam à extensão do arquivo de declaração de conteúdo (por padrão,.content.{json,ts,tsx,js,jsx,mjs,cjs}).
Para mais detalhes, consulte a documentação de declaração de conteúdo.
Passo 8: Utilizar Componentes e Hooks Cientes de Localidade
Crie um componente LocalizedLink para navegação ciente de localidade:
Copiar o código para a área de transferência
import { Link, type LinkProps } from "@tanstack/solid-router";import { getPrefix } from "intlayer";import { useLocale } from "solid-intlayer";import type { JSX } from "solid-js";export const LOCALE_ROUTE = "{-$locale}" as const;export type RemoveLocaleParam<TVal> = TVal extends string ? RemoveLocaleFromString<TVal> : TVal;export type To = RemoveLocaleParam<LinkProps["to"]>;type CollapseDoubleSlashes<TString extends string> = TString extends `${infer THead}//${infer TTail}` ? CollapseDoubleSlashes<`${THead}/${TTail}`> : TString;export type LocalizedLinkProps = Omit<LinkProps, "to"> & { to?: To;} & JSX.AnchorHTMLAttributes<HTMLAnchorElement>;type RemoveAll< TString extends string, TSub extends string,> = TString extends `${infer THead}${TSub}${infer TTail}` ? RemoveAll<`${THead}${TTail}`, TSub> : TString;type RemoveLocaleFromString<TString extends string> = CollapseDoubleSlashes< RemoveAll<TString, typeof LOCALE_ROUTE>>;export const LocalizedLink = (props: LocalizedLinkProps) => { const { locale } = useLocale(); return ( <Link {...props} params={{ locale: getPrefix(locale()).localePrefix, ...(typeof props.params === "object" ? props.params : {}), }} to={`/${LOCALE_ROUTE}${props.to ?? ""}` as LinkProps["to"]} /> );};Este componente tem dois objetivos:
- Remover o prefixo desnecessário
{-$locale}da URL. - Injetar o parâmetro de localidade na URL para garantir que o usuário seja diretamente redirecionado para a rota localizada.
Depois, podemos criar um hook useLocalizedNavigate para navegação programática:
Copiar o código para a área de transferência
import { useNavigate } from "@tanstack/solid-router";import { getLocalizedUrl } from "intlayer";import { useLocale } from "solid-intlayer";export const useLocalizedNavigate = () => { const navigate = useNavigate(); const { locale } = useLocale(); const localizedNavigate = (to: string) => { const localizedTo = getLocalizedUrl(to, locale()); return navigate({ to: localizedTo }); }; return localizedNavigate;};Passo 9: Utilizar o Intlayer em Suas Páginas
Acesse seus dicionários de conteúdo através da sua aplicação:
Página Inicial Localizada
Copiar o código para a área de transferência
import { createFileRoute } from "@tanstack/solid-router";import { useIntlayer } from "solid-intlayer";import { LocalizedLink } from "@/components/LocalizedLink";export const Route = createFileRoute("/{-$locale}/")({ component: RouteComponent,});function RouteComponent() { const content = useIntlayer("index-page"); return ( <main> <h1>{content.heroTitle}</h1> <p>{content.heroDesc}</p> <div> <LocalizedLink to="/">{content.navHome}</LocalizedLink> <LocalizedLink to="/about">{content.navAbout}</LocalizedLink> </div> </main> );}Se você quiser usar seu conteúdo em um atributo do tipostring, comoalt,title,href,aria-label, etc., você deve chamar o valor da função, assim:
htmlCopiar códigoCopiar o código para a área de transferência
<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)}" />
No Solid,
useIntlayerretorna conteúdo reativo (por exemplo,content). Você pode acessar suas propriedades diretamente.Para aprender mais sobre o hook
useIntlayer, consulte a documentação.
Passo 10: Criar um Componente Seletor de Localidade (Locale Switcher)
Crie um componente para permitir que os usuários mudem de língua:
Copiar o código para a área de transferência
import { useLocation } from "@tanstack/solid-router";import { getLocaleName, getPathWithoutLocale, getPrefix } from "intlayer";import { For } from "solid-js";import { useIntlayer, useLocale } from "solid-intlayer";import { LocalizedLink, type To } from "./LocalizedLink";export const LocaleSwitcher = () => { const content = useIntlayer("locale-switcher"); const location = useLocation(); const { availableLocales, locale, setLocale } = useLocale(); const pathWithoutLocale = () => getPathWithoutLocale(location().pathname); return ( <div class="flex flex-row gap-2"> <For each={availableLocales}> {(localeEl) => ( <LocalizedLink aria-current={localeEl === locale() ? "page" : undefined} onClick={() => setLocale(localeEl)} params={{ locale: getPrefix(localeEl).localePrefix }} to={pathWithoutLocale() as To} > {getLocaleName(localeEl)} </LocalizedLink> )} </For> </div> );};export default LocaleSwitcher;No Solid,
localedeuseLocaleé um signal accessor. Uselocale()(com parênteses) para ler o seu valor atual de forma reativa.Para aprender mais sobre o hook
useLocale, consulte la documentação.
Passo 11: Gerenciamento de Atributos HTML
Como visto no Passo 5, você pode gerenciar os atributos lang e dir da tag html usando useParams no seu componente raiz. Isso garante que os atributos corretos sejam definidos no servidor e no cliente.
Copiar o código para a área de transferência
const RootComponent: ParentComponent = (props) => { const params = LocaleRoute.useParams(); const locale = params()?.locale ?? defaultLocale; return ( <html dir={getHTMLTextDir(locale)} lang={locale}> {/* ... */} </html> );};Passo 12: Adicionar Middleware (Opcional)
Você também pode usar o intlayerProxy para adicionar roteamento do lado do servidor à sua aplicação. Este plugin detectará automaticamente a localidade atual baseada na URL e definirá o cookie de localidade apropriado. Se nenhuma localidade for especificada, o plugin determinará a localidade mais apropriada baseada nas preferências de língua do navegador do usuário. Se nenhuma localidade for detectada, ele redirecionará para a localidade padrão.
Note que para usar ointlayerProxyem produção, você precisa trocar o pacotevite-intlayerdedevDependenciesparadependencies.
Copiar o código para a área de transferência
import { tanstackStart } from "@tanstack/solid-start/plugin/vite";import solid from "vite-plugin-solid";import { nitro } from "nitro/vite";import { defineConfig } from "vite";import { intlayer, intlayerProxy } from "vite-intlayer";export default defineConfig({ plugins: [ intlayerProxy(), // O proxy deve ser colocado antes do servidor se você usar o Nitro nitro(), intlayer(), tanstackStart({ router: { routeFileIgnorePattern: ".content.(ts|tsx|js|mjs|cjs|jsx|json|jsonc|json5)$", }, }), solid(), ],});Passo 13: Internacionalizar Seus Metadados (Opcional)
Você também pode usar a função getIntlayer para acessar seus dicionários de conteúdo dentro do loader head para metadados cientes de localidade:
Copiar o código para a área de transferência
import { createFileRoute } from "@tanstack/solid-router";import { getIntlayer } from "intlayer";export const Route = createFileRoute("/{-$locale}/")({ component: RouteComponent, head: ({ params }) => { const { locale } = params; const path = "/"; // The path for this route const metaContent = getIntlayer("app", locale); return { links: [ // Canonical link: Points to the current localized page { rel: "canonical", href: getLocalizedUrl(path, locale) }, // Hreflang: Tell Google about all localized versions ...localeMap(({ locale: mapLocale }) => ({ rel: "alternate", hrefLang: mapLocale, href: getLocalizedUrl(path, mapLocale), })), // x-default: For users in unmatched languages // Define the default fallback locale (usually your primary language) { rel: "alternate", hrefLang: "x-default", href: getLocalizedUrl(path, defaultLocale), }, ], meta: [ { title: metaContent.title }, { name: "description", content: metaContent.meta.description }, ], }; },});Passo 14: Recuperar a localidade nas suas server actions (Opcional)
Você pode querer acessar a localidade atual de dentro das suas server actions ou endpoints de API.
Você pode fazer isso usando o helper getLocale do intlayer.
Aqui está um exemplo usando as server functions do TanStack Start:
Copiar o código para a área de transferência
import { createServerFn } from "@tanstack/solid-start";import { getRequestHeader, getRequestHeaders,} from "@tanstack/solid-start/server";import { getCookie, getIntlayer, getLocale } from "intlayer";export const getLocaleServer = createServerFn().handler(async () => { const locale = await getLocale({ // Obter o cookie da requisição (padrão: 'INTLAYER_LOCALE') getCookie: (name) => { const cookieString = getRequestHeader("cookie"); return getCookie(name, cookieString); }, // Obter o header da requisição (padrão: 'x-intlayer-locale') // Fallback usando negociação Accept-Language getHeader: (name) => getRequestHeader(name), }); // Recuperar algum conteúdo usando getIntlayer() const content = getIntlayer("app", locale); return { locale, content };});Passo 15: Gerenciar páginas não encontradas (Opcional)
Quando um usuário visita uma página inexistente, você pode exibir uma página personalizada de não encontrado e o prefixo de localidade pode impactar a maneira como a página de não encontrado é disparada.
Entendendo o Processamento de 404 do TanStack Router com Prefixos de Localidade
No TanStack Router, processar páginas 404 com rotas localizadas requer uma abordagem multicamada:
- Rota de 404 dedicada: Uma rota específica para exibir a UI do 404
- Validação ao nível da rota: Valida os prefixos de localidade e redireciona os inválidos para o 404
- Rota catch-all: Captura quaisquer caminhos não correspondentes dentro do segmento de localidade
Copiar o código para a área de transferência
import { createFileRoute } from "@tanstack/solid-router";// Isso cria uma rota /[locale]/404 dedicada// Ela é usada tanto como uma rota direta quanto importada como um componente em outros arquivosexport const Route = createFileRoute("/{-$locale}/404")({ component: NotFoundComponent,});// Exportado separadamente para que possa ser reutilizado em notFoundComponent e rotas catch-allexport function NotFoundComponent() { return ( <div> <h1>404</h1> </div> );}Copiar o código para a área de transferência
import { createFileRoute, Outlet, redirect } from "@tanstack/solid-router";import { validatePrefix } from "intlayer";import { NotFoundComponent } from "./404";export const Route = createFileRoute("/{-$locale}")({ // beforeLoad executa antes da rota renderizar (tanto no servidor quanto no cliente) // É o lugar ideal para validar o prefixo de localidade beforeLoad: ({ params }) => { const localeParam = params.locale; // validatePrefix verifica se a localidade é válida de acordo com a sua configuração do intlayer const { isValid, localePrefix } = validatePrefix(localeParam); if (!isValid) { // Prefixo de localidade inválido - redireciona para a página 404 com um prefixo de localidade válido throw redirect({ to: "/{-$locale}/404", params: { locale: localePrefix }, }); } }, component: Outlet, // notFoundComponent é chamado quando uma rota filha não existe // ex: /en/pagina-nao-existente dispara isso dentro do layout /en notFoundComponent: NotFoundComponent,});Copiar o código para a área de transferência
import { createFileRoute } from "@tanstack/solid-router";import { NotFoundComponent } from "./404";// A rota $ (splat/catch-all) corresponde a qualquer caminho que não corresponda a outras rotas// ex: /en/algum/caminho/profundamente/aninhado/invalido// Isso garante que TODOS os caminhos não correspondentes dentro de uma localidade mostrem a página 404// Sem isso, caminhos profundos não correspondentes poderiam mostrar uma página em branco ou erroexport const Route = createFileRoute("/{-$locale}/$")({ component: NotFoundComponent,});(Opcional) Passo 15: Extrair o conteúdo dos seus componentes
Se você tem uma base de código existente, transformar milhares de arquivos pode ser demorado.
Para facilitar este processo, o Intlayer propõe um compilador / extrator para transformar os seus componentes e extrair o conteúdo.
Para configurá-lo, você pode adicionar uma seção compiler no seu arquivo intlayer.config.ts:
Copiar o código para a área de transferência
import { type IntlayerConfig } from "intlayer";
const config: IntlayerConfig = {
// ... Resto da sua configuração
compiler: {
/**
* Indica se o compilador deve ser habilitado.
*/
enabled: true,
/**
* Define o caminho dos arquivos de saída
*/
output: ({ fileName, extension }) => `./${fileName}${extension}`,
/**
* Indica se os componentes devem ser salvos após serem transformados.
*
* - Se `true`, o compilador reescreverá o arquivo do componente no disco. Assim, a transformação será permanente, e o compilador pulará a transformação para o próximo processo. Dessa forma, o compilador pode transformar a aplicação e depois pode ser removido.
*
* - Se `false`, o compilador injetará a chamada de função `useIntlayer()` no código apenas no output da build, mantendo a base de código intacta. A transformação será feita apenas em memória.
*/
saveComponents: false,
/**
* Prefixo da chave do dicionário
*/
dictionaryKeyPrefix: "",
},
};
export default config;Rode o extrator para transformar os seus componentes e extrair o conteúdo
Copiar o código para a área de transferência
npx intlayer extractPasso 16: Gerar um Sitemap (Opcional)
O Intlayer vem com um gerador de sitemap integrado para ajudá-lo a criar facilmente um sitemap para sua aplicação. Ele cuida das rotas localizadas e adiciona os metadados necessários para os mecanismos de busca.
O sitemap gerado pelo Intlayer suporta o namespacexhtml:link(Hreflang XML Extensions). Ao contrário dos geradores de sitemap padrão que apenas listam URLs brutos, o Intlayer cria automaticamente os links bidirecionais necessários entre todas as versões de idioma de uma página (por exemplo,/about,/about?lang=fre/about?lang=es). Isso garante que os mecanismos de busca indexem e sirvam corretamente a versão de idioma certa para o público certo.
Para usá-lo, você primeiro precisa configurar o seu vite.config.ts para habilitar a pré-renderização de suas rotas localizadas e desabilitar a geração de sitemap padrão do TanStack Start.
Copiar o código para a área de transferência
import { localeMap, localeFlatMap } from "intlayer";// ... outras importaçõesexport const pathList = ["", "/about", "/404"];const localizedPages = localeFlatMap(({ urlPrefix }) => pathList.map((path) => ({ path: `${urlPrefix}${path}`, prerender: { enabled: true, }, })));export default defineConfig({ plugins: [ // ... outros plugins tanstackStart({ // ... outras configurações sitemap: { enabled: false, }, prerender: { enabled: true, crawlLinks: false, concurrency: 10, }, pages: localizedPages, }), ],});Em seguida, crie uma rota src/routes/sitemap[.]xml.ts que use a função generateSitemap:
Copiar o código para a área de transferência
import { createFileRoute } from "@tanstack/solid-router";import { generateSitemap } from "intlayer";const SITE_URL = "http://localhost:3000";export const Route = createFileRoute("/sitemap.xml")({ server: { handlers: { GET: async () => { 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" }, }); }, }, },});Passo 17: Configurar TypeScript (Opcional)
O Intlayer usa a ampliação de módulo para obter os benefícios do TypeScript e tornar a sua base de código mais forte.
Certifique-se de que a sua configuração do TypeScript inclua os tipos autogerados:
Copiar o código para a área de transferência
{ // ... as suas configurações existentes include: [ // ... os seus includes existentes ".intlayer/**/*.ts", // Incluir os tipos autogerados ],}Configuração Git
É recomendado ignorar os arquivos gerados pelo Intlayer. Isso permite que você evite committá-los no seu repositório Git.
Para fazer isso, você pode adicionar as seguintes instruções ao seu arquivo .gitignore:
Copiar o código para a área de transferência
# Ignorar os arquivos gerados pelo Intlayer.intlayerExtensão VS Code
Para melhorar a sua experiência de desenvolvimento com o Intlayer, você pode instalar a Extensão oficial do Intlayer VS Code.
Instalar a partir do VS Code Marketplace
Esta extensão oferece:
- Autocompletar para chaves de tradução.
- Detecção de erros em tempo real para traduções ausentes.
- Previsões inline de conteúdo traduzido.
- Ações rápidas para criar e atualizar traduções facilmente.
Para mais detalhes sobre como usar a extensão, consulte a documentação da Extensão Intlayer VS Code.
Ir Além
Para ir mais além, você pode implementar o editor visual ou externalizar o seu conteúdo usando o CMS.