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
- "Uso do middleware e hooks do remix-intlayer"v9.5.519/09/2026
- "Documentação inicial para Remix 3"v9.5.009/09/2026
O conteúdo desta página foi traduzido com uma IA.
Veja a última versão do conteúdo original em inglêsSe você tiver uma ideia para melhorar esta documentação, sinta-se à vontade para contribuir enviando uma pull request no GitHub.
Link do GitHub para a documentaçãoCopiar o Markdown do documento para a área de transferência
Traduza o seu site Remix 3 utilizando o Intlayer
Este guia demonstra como integrar o Intlayer para uma internacionalização perfeita em aplicações Remix 3, com roteamento com suporte a idiomas, declarações de conteúdo com segurança de tipos, componentes JSX renderizados no servidor e compatibilidade multi-runtime no Node.js, Bun, Deno e Cloudflare Workers.
O que é o Remix 3?
O Remix 3 representa uma mudança arquitetural fundamental em direção a um framework web combinável e independente de runtime, construído inteiramente sobre padrões web. Em vez de estar vinculado a empacotadores específicos ou a APIs proprietárias de servidor, o Remix 3 é distribuído em pacotes combináveis de propósito único:
remix/fetch-router(ouremix/router): Roteamento leve e em conformidade com os padrões, baseado na Fetch API (RequesteResponse).remix/ui: Um modelo de componentes JSX (jsxImportSource: "remix/ui"). Um componente é uma função de setup que retorna uma função de renderização, parecendo React, mas mantendo o estado em closures simples de JavaScript.remix/middleware/render: Instalacontext.render(<Page />)em cada requisição, transmitindo a árvore JSX em umaResponseHTML.remix/node-fetch-server: Adaptadores de servidor para Node.js, com suporte nativo para Bun, Deno e runtimes edge.remix/cookie: Análise e serialização de cookies criptograficamente seguros.
Combinado com o Intlayer e o pacote remix-intlayer, um middleware de locale mais os mesmos hooks useIntlayer / useDictionary / useLocale do react-intlayer, vinculados ao contexto de requisição do Remix, você obtém um sistema completo de internacionalização que oferece segurança em tempo de compilação, traduções automatizadas por IA, renderização no servidor sem sobrecarga e roteamento fluido de locales.
Índice
Por que escolher o Intlayer em vez de alternativas?
Em comparação com soluções tradicionais como o i18next ou carregadores de tradução sob medida, o Intlayer oferece uma experiência de desenvolvimento integrada e otimizada para a arquitetura web moderna:
O Intlayer foi projetado para funcionar de forma nativa com os padrões web (Request, Response, Headers e URL). O remix-intlayer conecta-se ao router Fetch do Remix 3 como um middleware leve, extraindo o locale dos caminhos de URL, cookies ou cabeçalhos Accept-Language e expondo-o ao restante da requisição, handlers, visualizações e componentes remix/ui, sem a necessidade de repassá-lo manualmente nem prender você a um ambiente de execução específico.
Diga adeus às chaves JSON soltas e a falhas em tempo de execução causadas por chaves ausentes. O Intlayer aplica verificações do TypeScript em todos os idiomas declarados, avisando-o no momento da compilação caso falte uma tradução ou haja alguma inconsistência.
O Remix 3 renderiza componentes JSX no servidor e transmite o HTML para o cliente. Apenas o texto resolvido para o idioma solicitado é enviado no fluxo de resposta. Nenhum bundle de hidratação no cliente ou catálogo pesado de tradução é necessário, a menos que um componente seja explicitamente marcado como clientEntry.
O Intlayer coloca as declarações de conteúdo (.content.ts) diretamente junto da lógica de rotas, reduzindo o contexto de tokens exigido por Grandes Modelos de Linguagem (LLMs). Comandos CLI integrados como intlayer fill e intlayer test permitem automatizar traduções em pipelines de CI/CD pelo custo direto do seu provedor de IA.
Além dos fluxos de trabalho baseados em código, o Intlayer disponibiliza um Editor Visual auto-hospedado e um CMS Remoto, permitindo que editores e tradutores atualizem o conteúdo sem necessidade de novo deploy.
Guia Passo a Passo
Veja o Modelo de Aplicação no GitHub.
Instalar Dependências
Instale
intlayer,remix-intlayereremix(versão 3) usando seu gerenciador de pacotes preferido:bashCopiar códigoCopiar o código para a área de transferência
intlayer: Motor principal de internacionalização que fornece gestão de configurações, declaração de dicionários (t(),Dictionary), ferramentas CLI e interpretador em tempo de execução.remix-intlayer: A integração com Remix 3: o middleware de routerintlayer()que resolve o locale de cada requisição, e os hooksuseIntlayer,useDictionaryeuseLocaleque o leem em qualquer ponto subsequente.remix: O pacote unificado do framework Remix 3 que exportaremix/router,remix/routes,remix/ui,remix/middleware/rendereremix/node-fetch-server.
Configurar o Intlayer
Arquitetura
Nesta arquitetura, o middleware
intlayer()doremix-intlayeré registrado nocreateRouter()antes do middlewarerender(). Ele remove o prefixo de localidade antes do matching do roteador, de modo que as rotas sejam declaradas apenas uma vez emsrc/routes.tssem o segmento:locale, e executa o restante da requisição dentro de um escopoAsyncLocalStorage, permitindo queuseIntlayer/useLocaleleiam a localidade sem argumentos nos manipuladores de rotas e visualizações doremix/ui. As declarações de conteúdo são colocadas ao lado de suas visualizações emsrc/:bashCopiar códigoCopiar o código para a área de transferência
Configuração
Crie um arquivo
intlayer.config.tsna raiz do seu projeto para declarar os idiomas suportados e as configurações de internacionalização:intlayer.config.tsCopiar códigoCopiar o código para a área de transferência
import { Locales, type IntlayerConfig } from "intlayer"; const config: IntlayerConfig = { internationalization: { locales: [ Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH, Locales.PORTUGUESE, ], defaultLocale: Locales.ENGLISH, }, }; export default config;Para configurações adicionais, consulte a documentação de configuração.
Declarar o Conteúdo Multilíngue
Declare o seu conteúdo localizado em um arquivo
.content.ts:src/home.content.tsCopiar códigoCopiar o código para a área de transferência
import { t, type Dictionary } from "intlayer"; const homeContent = { key: "home", content: { title: t({ pt: "Bem-vindo ao Remix 3", en: "Welcome to Remix 3", fr: "Bienvenue sur Remix 3", es: "Bienvenido a Remix 3", }), description: t({ pt: "Uma aplicação combinável baseada em padrões web com i18n nativa.", en: "A composable, web-standard application with native i18n.", fr: "Une application composable basée sur les standards web avec i18n native.", es: "Una aplicación componible basada en estándares web con i18n nativa.", }), switchLanguage: t({ pt: "Alterar idioma:", en: "Switch language:", fr: "Changer de langue :", es: "Cambiar idioma:", }), }, } satisfies Dictionary; export default homeContent;O Intlayer também suporta formatos JSON, YAML e CommonJS. Veja a Documentação sobre Declaração de Conteúdo.
Compilar os Dicionários Intlayer
Compile as definições do dicionário para gerar os tipos TypeScript e registros de execução:
bashCopiar códigoCopiar o código para a área de transferência
Isso compila o seu conteúdo no diretório de artefatos
.intlayer, permitindo autocompletar completo no TypeScript e consulta rápida aos dicionários.Adicionar o Middleware do Intlayer
O Remix 3 oferece um pipeline de middleware componível por meio de
createRouter({ middleware: [...] }).O
remix-intlayerfornece o middlewareintlayer(). Para cada requisição recebida, ele resolve o locale usando:- A URL, em todos os modos de roteamento exceto
no-prefix: o prefixo do caminho (ex./ptou/es) ou o parâmetro de busca?locale=. - O locale persistido pelo cliente: o cookie de armazenamento (
INTLAYER_LOCALE) ou cabeçalho personalizado (x-intlayer-locale). - A negociação padrão de
Accept-Language, recorrendo ao seudefaultLocaleconfigurado.
O resultado é armazenado no contexto de requisição do Remix como
context.intlayer(oucontext.get(Intlayer)), comlocale,defaultLocaleeavailableLocales. O middleware então executa o restante da requisição dentro de um escopoAsyncLocalStoragevinculado a esse contexto, o que permite que os hooks do pacote leiam o locale sem argumentos, seja em manipuladores de rotas, visualizações ou componentesremix/ui:typescriptCopiar códigoCopiar o código para a área de transferência
useIntlayer("home", "fr")ouuseIntlayer("faq", { item: 2 })sobrescrevem o locale da requisição para uma chamada, euseDictionary(homeContent)lê um dicionário importado em vez de uma chave. Fora de uma requisição, os hooks recorrem ao locale padrão.O middleware também prepara os dicionários do Intlayer quando o servidor inicia, de modo que a ausência de um
intlayer buildnão deixa o registro vazio.Defina
routing.enableProxy: falseemintlayer.config.tspara manter apenas a resolução da locale e tratar o roteamento você mesmo.intlayer({ ignore })deixa as requisições correspondentes intactas (um prefixo de API, por exemplo), eintlayer({ isDevServer })controla se a locale armazenada conduz os redirecionamentos no modo automático padrão deenableProxy.- A URL, em todos os modos de roteamento exceto
Definir Rotas com Segurança de Tipos
Defina as rotas da sua aplicação utilizando
route()deremix/routes:src/routes.tsCopiar códigoCopiar o código para a área de transferência
import { route } from "remix/routes"; export const routes = route({ // Rota padrão do idioma home: "/", // Rota localizada com segmento dinâmico :locale localizedHome: "/:locale", });O uso de
route()garante geração de URLs tipadas em toda a sua aplicação:typescriptCopiar códigoCopiar o código para a área de transferência
Renderizar Páginas Localizadas com JSX
O Remix 3 renderiza a interface do usuário com componentes JSX de
remix/ui. Um componente é uma função de setup que recebe umHandlee retorna uma função de renderização. O setup é executado uma vez por instância, o render a cada atualização, e as props são lidas através dehandle.props.Comece com um shell compartilhado
Documentque define os atributos<html lang="..." dir="...">a partir do locale resolvido pelo middleware:src/views/document.tsxCopiar códigoCopiar o código para a área de transferência
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> ); };Em seguida, crie a página inicial. Ela lê o dicionário localizado com
useIntlayere renderiza um seletor de idiomas:src/views/home.tsxCopiar códigoCopiar o código para a área de transferência
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> ); };O JSX do Remix não é React:
classé escrito como está (classNametambém é aceito) e novas renderizações são disparadas explicitamente comhandle.update(). Valores interpolados são escapados automaticamente. Os hooks do Intlayer são funções simples que leem o escopo da requisição, portanto podem ser chamados tanto na função de setup quanto na de renderização.Ligar o Roteador e o Servidor
Adicione o middleware
render()deremix/middleware/renderjunto com o middleware do Intlayer. Ele instalacontext.render(node, init)em cada requisição, transmitindo a árvore JSX em umaResponseHTML (adicionando<!DOCTYPE html>no início e configurando o cabeçalhoContent-Type):src/router.tsxCopiar códigoCopiar o código para a área de transferência
import { isDeclaredLocale } from "intlayer"; 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. Initialize router with Intlayer + render middleware export const router = createRouter({ middleware: [intlayer(), render()], }); // 2. Map route handlers router.map(routes, { actions: { // Default locale route home(context) { return context.render(<HomePage />); }, // Localized route localizedHome(context) { if (!isDeclaredLocale(context.params.locale)) { return new Response("Not Found", { status: 404 }); } return context.render(<HomePage />); }, }, });context.renderaceita umResponseInitopcional como segundo argumento, por ex.context.render(<NotFoundPage />, { status: 404 }). O locale resolvido permanece acessível a partir do handler comocontext.intlayer.locale, por exemplo para construir uma respostaResponse.json.Por fim, exponha o roteador através de um manipulador
fetchpadrão. O mesmo roteador funciona no Node.js, Bun, Deno e Cloudflare Workers:src/server.tsCopiar códigoCopiar o código para a área de transferência
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(`Servidor em execução em http://localhost:${PORT}`); }); // Bun / Deno / Cloudflare Workers export default { port: PORT, fetch(request: Request) { return router.fetch(request); }, };Auditar e Preencher Traduções Automaticamente
O Intlayer disponibiliza uma CLI para verificar traduções em falta e preenchê-las automaticamente usando IA:
bashCopiar códigoCopiar o código para a área de transferência
Configuração do TypeScript
Aponte o JSX para o runtime remix/ui e certifique-se de que o seu tsconfig.json inclui os tipos gerados do .intlayer:
Copiar o código para a área de transferência
jsxImportSource: "remix/ui"é o que faz com que<HomePage />resolva para ocreateElementdo Remix em vez do React.
Conclusão
Com o Remix 3 e o Intlayer, você obtém uma stack enxuta, totalmente tipada e portável, alinhada com os padrões da web aberta. A sua aplicação escala facilmente de páginas de marketing simples para serviços globais renderizados na borda (edge).
