Autor:
    Criação:2025-11-20Última atualização:2026-08-30

    Traduza seu site SvelteKit usando Intlayer | Internacionalização (i18n)

    ide.intlayer.org
    intlayer-sveltekit-template.vercel.app

    Índice

    Por que Intlayer em vez de alternativas?

    Comparado com soluções principais como svelte-i18n ou i18next, Intlayer é uma solução que vem com otimizações integradas como:

    O Intlayer é otimizado para funcionar perfeitamente com o SvelteKit, oferecendo roteamento multilíngue, suporte SSR e todos os recursos necessários para dimensionar a internacionalização (i18n).

    Em vez de carregar arquivos JSON enormes em suas páginas, carregue apenas o conteúdo necessário. O Intlayer ajuda a reduzir o tamanho do bundle e das páginas em até 50%.

    Definir o escopo do conteúdo do seu aplicativo facilita a manutenção de aplicativos de grande escala. Você pode duplicar ou excluir uma única pasta de recursos sem o fardo mental de revisar toda a base de código de seu conteúdo. Além disso, o Intlayer é totalmente tipado (fully typed) para garantir a precisão do seu conteúdo.

    A co-localização de conteúdo reduz o contexto necessário pelos Large Language Models (LLMs). O Intlayer também vem com um conjunto de ferramentas, como uma CLI para testar traduções ausentes,LSP, MCP, e agent skills, para tornar a experiência do desenvolvedor (DX) ainda mais tranquila para os agentes de IA.

    Use a automação para traduzir seu pipeline de CI/CD usando o LLM de sua escolha às custas de seu provedor de IA. O Intlayer também oferece um compilador para automatizar a extração de conteúdo, bem como uma plataforma web para ajudar a traduzir em segundo plano.

    Conectar arquivos JSON enormes a componentes pode levar a problemas de desempenho e reatividade. O Intlayer otimiza o carregamento do seu conteúdo no momento da construção.

    Mais do que apenas uma solução i18n, o Intlayer fornece um [editor visual] auto-hospedado(/pt/doc/concept/editor)* e um *CMS completo para ajudá-lo a gerenciar seu conteúdo multilíngue em tempo real, facilitando a colaboração com tradutores, redatores e outros membros da equipe. O conteúdo pode ser armazenado local e/ou remotamente.

    Guia Passo a Passo para Configurar o Intlayer em uma Aplicação SvelteKit

    Veja Application Template no GitHub.

    Para começar, crie um novo projeto SvelteKit. Aqui está a estrutura final que iremos criar:

    bash
    .
    ├── intlayer.config.ts
    ├── package.json
    ├── src
       ├── app.d.ts
    │   ├── app.html
    │   ├── hooks.server.ts
    │   ├── lib
    │   │   ├── getLocale.ts
    │   │   ├── LocaleSwitcher.svelte
    │   │   └── LocalizedLink.svelte
    │   ├── params
    │   │   └── locale.ts
    │   └── routes
    │       ├── [[locale=locale]]
    │       │   ├── +layout.svelte
    │       │   ├── +layout.ts
    │       │   ├── +page.svelte
    │       │   ├── +page.ts
    │       │   ├── about
    │       │   │   ├── +page.svelte
    │       │   │   ├── +page.ts
    │       │   │   └── page.content.ts
    │       │   ├── Counter.content.ts
    │       │   ├── Counter.svelte
    │       │   ├── Header.content.ts
    │       │   ├── Header.svelte
    │       │   ├── home.content.ts
    │       │   └── layout.content.ts
    │       ├── +layout.svelte
    │       └── layout.css
    ├── static
    │   ├── favicon.svg
    │   └── robots.txt
    ├── svelte.config.js
    ├── tsconfig.json
    └── vite.config.ts
    
    1. Instalar Dependências

      Instale os pacotes necessários usando npm:

      bash
      npx intlayer init --interactive
      
      a flag --interactive é opcional. Use intlayer-cli init se você for um agente de IA.
      Este comando detectará seu ambiente e instalará os pacotes necessários. Por exemplo:
      bash
      npm install intlayer svelte-intlayer
      npm install vite-intlayer --save-dev
      
      • intlayer: O pacote principal de i18n.
      • svelte-intlayer: Fornece context providers e stores para Svelte/SvelteKit.
      • vite-intlayer: O plugin do Vite para integrar as declarações de conteúdo com o processo de build.
    2. Configuração do seu projeto

      Crie um arquivo de configuração na raiz do seu projeto:

      intlayer.config.ts
      import { Locales, type IntlayerConfig } from "intlayer";
      
      const config: IntlayerConfig = {
        internationalization: {
          locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],
          defaultLocale: Locales.ENGLISH,
        },
      };
      
      export default config;
      
    3. Integre o Intlayer na sua Configuração do Vite

      Atualize seu vite.config.ts para incluir o plugin Intlayer. Este plugin gerencia a transpiração dos seus arquivos de conteúdo.

      vite.config.ts
      import { sveltekit } from "@sveltejs/kit/vite";
      import { defineConfig } from "vite";
      import { intlayer } from "vite-intlayer";
      
      export default defineConfig({
        plugins: [intlayer(), sveltekit()], // a ordem importa, Intlayer deve ser colocado antes do SvelteKit
      });
      
    4. Declare Seu Conteúdo

      Crie seus arquivos de declaração de conteúdo em qualquer lugar dentro da sua pasta src (por exemplo, src/lib/content ou junto aos seus componentes). Esses arquivos definem o conteúdo traduzível para sua aplicação usando a função t() para cada locale.

    5. Utilize o Intlayer em Seus Componentes

      Agora você pode usar a função useIntlayer em qualquer componente Svelte. Ela retorna um store reativo que se atualiza automaticamente quando a localidade muda. A função respeitará automaticamente a localidade atual (tanto durante SSR quanto na navegação no lado do cliente).

      para acessar seu valor reativo (por exemplo, $content.title).

      src/lib/components/Component.svelte
      <script lang="ts">
        import { useIntlayer } from "svelte-intlayer";
      
        // "hero-section" corresponde à chave definida no Passo 4
        const content = useIntlayer("hero-section");
      </script>
      
      <!-- Renderizar conteúdo como conteúdo simples  -->
      <h1>{$content.title}</h1>
      <!-- Para renderizar o conteúdo editável usando o editor -->
      <h1>{@const Title = $content.title}<Title /></h1>
      <!-- Para renderizar o conteúdo como uma string -->
      <div aria-label={$content.title.value}></div>
      <div aria-label={$content.title.toString()}></div>
      <div aria-label={String($content.title)}></div>
      
    6. Configurar o roteamento

      Opcional

      Os passos a seguir mostram como configurar o roteamento baseado em locale no SvelteKit. Isso permite que suas URLs incluam o prefixo do locale (ex.: /en/about, /fr/about) para melhor SEO e experiência do usuário.

      bash
      .
      └─── src
          ├── app.d.ts                  # Definir o tipo de locale
          ├── hooks.server.ts           # Gerenciar o roteamento do locale
          ├── lib
          │   └── getLocale.ts          # Verificar o locale a partir do header, cookies
          ├── params
          │   └── locale.ts             # Definir o parâmetro do locale
          └── routes
              ├── [[locale=locale]]     # Envolver em um grupo de rotas para definir o locale
              │   ├── +layout.svelte    # Layout local para a rota
              │   ├── +layout.ts
              │   ├── +page.svelte
              │   ├── +page.ts
              │   └── about
              │       ├── +page.svelte
              │       └── +page.ts
              └── +layout.svelte         # Layout raiz para fontes e estilos globais
      
    7. Gerenciar a Detecção de Locale no Lado do Servidor

      No SvelteKit, o servidor precisa saber o locale do usuário para renderizar o conteúdo correto durante o SSR. Usamos hooks.server.ts para detectar o locale a partir da URL ou dos cookies.

      Crie ou modifique src/hooks.server.ts:

      src/hooks.server.ts
      import type { Handle } from "@sveltejs/kit";
      import { getLocalizedUrl } from "intlayer";
      import { getLocale } from "$lib/getLocale";
      
      export const handle: Handle = async ({ event, resolve }) => {
        const detectedLocale = getLocale(event);
      
        // Verifica se o caminho atual já começa com uma localidade (ex: /fr, /en)
        const pathname = event.url.pathname;
        const targetPathname = getLocalizedUrl(pathname, detectedLocale);
      
        // Se NÃO houver localidade presente na URL (ex: usuário visita "/"), redireciona
        if (targetPathname !== pathname) {
          return new Response(undefined, {
            headers: { Location: targetPathname },
            status: 307, // Redirecionamento temporário
          });
        }
      
        return resolve(event, {
          transformPageChunk: ({ html }) => html.replace("%lang%", detectedLocale),
        });
      };
      

      Em seguida, crie um helper para obter a localidade do usuário a partir do evento da requisição:

      src/lib/getLocale.ts
      import {
        configuration,
        getLocaleFromStorage,
        localeDetector,
        type Locale,
      } from "intlayer";
      import type { RequestEvent } from "@sveltejs/kit";
      
      /**
       * Obtém a localidade do usuário a partir do evento de requisição.
       * Esta função é usada no hook `handle` em `src/hooks.server.ts`.
       *
       * Primeiro, tenta obter a localidade do armazenamento do Intlayer (cookies ou cabeçalhos personalizados).
       * Se a localidade não for encontrada, recorre à negociação "Accept-Language" do navegador.
       *
       * @param event - O evento de requisição do SvelteKit
       * @returns A localidade do usuário
       */
      export const getLocale = (event: RequestEvent): Locale => {
        const defaultLocale = configuration?.internationalization?.defaultLocale;
      
        // Tenta obter a localidade do armazenamento do Intlayer (Cookies ou cabeçalhos)
        const storedLocale = getLocaleFromStorage({
          // Acesso aos cookies do SvelteKit
          getCookie: (name: string) => event.cookies.get(name) ?? null,
          // Acesso aos headers do SvelteKit
          getHeader: (name: string) => event.request.headers.get(name) ?? null,
        });
      
        if (storedLocale) {
          return storedLocale;
        }
      
        // Recurso de fallback para a negociação "Accept-Language" do navegador
        const negotiatorHeaders: Record<string, string> = {};
      
        // Converte o objeto Headers do SvelteKit para um Record<string, string> simples
        event.request.headers.forEach((value, key) => {
          negotiatorHeaders[key] = value;
        });
      
        // Verifica a localidade a partir do header `Accept-Language`
        const userFallbackLocale = localeDetector(negotiatorHeaders);
      
        if (userFallbackLocale) {
          return userFallbackLocale;
        }
      
        // Retorna a localidade padrão se nenhuma correspondência for encontrada
        return defaultLocale;
      };
      
      getLocaleFromStorage verificará o locale a partir do header ou cookie dependendo da sua configuração. Veja Configuração para mais detalhes.
      A função localeDetector tratará o header Accept-Language e retornará a melhor correspondência.

      Se o locale não estiver configurado, queremos retornar um erro 404. Para facilitar, podemos criar uma função match para verificar se o locale é válido:

      /src/params/locale.ts
      export const match = (param: Locale = defaultLocale): boolean =>
        locales.includes(param);
      

      Nota: Certifique-se de que seu arquivo src/app.d.ts inclua a definição do locale:

      typescript
      declare global {
        namespace App {
          interface Locals {
            locale: import("intlayer").Locale;
          }
        }
      }
      

      Para o arquivo +layout.svelte, podemos remover tudo, para manter apenas conteúdo estático, não relacionado à i18n:

      src/+layout.svelte
      <script lang="ts">
           import './layout.css';
      
          let { children } = $props();
      </script>
      
      <div class="app">
          {@render children()}
      </div>
      
      <style>
          .app {
          /*  */
          }
      </style>
      

      Em seguida, crie uma nova página e layout dentro do grupo [[locale=locale]]:

      src/routes/[[locale=locale]]/+layout.ts
      import type { Load } from "@sveltejs/kit";
      import { defaultLocale, type Locale } from "intlayer";
      
      export const prerender = true;
      
      // Use o tipo genérico Load
      export const load: Load = ({ params }) => {
        const locale: Locale = (params.locale as Locale) ?? defaultLocale;
      
        return {
          locale,
        };
      };
      
      src/routes/[[locale=locale]]/+layout.svelte
      <script lang="ts">
          import type { Snippet } from 'svelte';
          import { useIntlayer, setupIntlayer } from "svelte-intlayer";
          import Header from './Header.svelte';
          import type { LayoutData } from './$types';
      
          let { children, data }: { children: Snippet, data: LayoutData } = $props();
      
          // Inicializar o Intlayer com a locale da rota
        $effect(() => {
            setupIntlayer(data.locale);
        });
          // Usar o dicionário de conteúdo do layout
          const layoutContent = useIntlayer('layout');
      </script>
      
      <Header />
      
      <main>
          {@render children()}
      </main>
      
      <footer>
          <p>
              {$layoutContent.footer.prefix.value}{' '}
              <a href="https://svelte.dev/docs/kit">{$layoutContent.footer.linkLabel.value}</a>{' '}
              {$layoutContent.footer.suffix.value}
          </p>
      </footer>
      
      <style>
        /*  */
      </style>
      
      src/routes/[[locale=locale]]/+page.ts
      export const prerender = true;
      
      src/routes/[[locale=locale]]/+page.svelte
      <script lang="ts">
          import { useIntlayer } from "svelte-intlayer";
      
          // Usar o dicionário de conteúdo da home
          const homeContent = useIntlayer('home');
      </script>
      
      <svelte:head>
          <title>{$homeContent.title.value}</title>
      </svelte:head>
      
      <section>
          <h1>
              {$homeContent.title}
          </h1>
      </section>
      
      <style>
        /*  */
      </style>
      
    8. Opcional

      Para SEO, é recomendado prefixar suas rotas com a localidade (ex: /en/about, /fr/about). Este componente automaticamente prefixa qualquer link com a localidade atual.

      src/lib/components/LocalizedLink.svelte
      <script lang="ts">
        import { getLocalizedUrl } from "intlayer";
        import { useLocale } from "svelte-intlayer";
      
        let { href = "" } = $props();
        const { locale } = useLocale();
      
        // Auxiliar para prefixar URL com a localidade atual
        $: localizedHref = getLocalizedUrl(href, $locale);
      </script>
      
      <a href={localizedHref}>
        <slot />
      </a>
      

      Se você usar goto do SvelteKit, pode usar a mesma lógica com getLocalizedUrl para navegar para a URL localizada:

      typescript
      import { goto } from "$app/navigation";
      import { getLocalizedUrl } from "intlayer";
      import { useLocale } from "svelte-intlayer";
      
      const { locale } = useLocale();
      const localizedPath = getLocalizedUrl("/about", $locale);
      goto(localizedPath); // Navega para /en/about ou /fr/about dependendo da localidade
      
    9. Seletor de Idioma

      Opcional

      Para permitir que os usuários mudem de idioma, atualize a URL.

      src/lib/components/LanguageSwitcher.svelte
      <script lang="ts">
        import { getLocalizedUrl, getLocaleName } from 'intlayer';
        import { useLocale } from "svelte-intlayer";
        import { page } from '$app/stores';
        import { goto } from '$app/navigation';
      
        const { locale, setLocale, availableLocales } = useLocale({
          onLocaleChange: (newLocale) => {
            const localizedPath = getLocalizedUrl($page.url.pathname, newLocale);
            goto(localizedPath);
          },
        });
      </script>
      
      <ul class="locale-list">
        {#each availableLocales as localeEl}
          <li>
            <a
              href={getLocalizedUrl($page.url.pathname, localeEl)}
              onclick={(e) => {
                e.preventDefault();
                setLocale(localeEl); // Vai definir a localidade na store e disparar onLocaleChange
              }}
              class:active={$locale === localeEl}
            >
              {getLocaleName(localeEl)}
            </a>
          </li>
        {/each}
      </ul>
      
      <style>
        /* */
      </style>
      
    10. Adicionar proxy backend

      Opcional

      Para adicionar um proxy backend à sua aplicação SvelteKit, você pode usar a função intlayerProxy fornecida pelo plugin vite-intlayer. Este plugin detectará automaticamente a melhor localidade para o usuário com base na URL, cookies e preferências de idioma do navegador.

      Desde o Intlayer v9, intlayerProxy() está agrupado diretamente no plugin intlayer() e habilitado por padrão através da opção routing.enableProxy (true por padrão). Registrá-lo separadamente, como mostrado abaixo, agora é opcional — é mantido para compatibilidade retroativa e para configurações que precisam controlar a ordem dos plugins. Configure routing.enableProxy: false para desativar. Consulte as notas de lançamento da v9.
      vite.config.ts
      import { defineConfig } from "vite";
      import { intlayer } from "vite-intlayer";
      import { sveltekit } from "@sveltejs/kit/vite";
      
      // https://vitejs.dev/config/
      export default defineConfig({
        plugins: [
          intlayer({
            proxy: {
              ignore: (req) => req.url?.startsWith("/api"),
            },
          }),
          sveltekit(),
        ],],
      });
      
    11. Configurar o editor / CMS do intlayer

      Opcional

      Para configurar o editor do intlayer, você deve seguir a documentação do editor intlayer.

      Para configurar o CMS do intlayer, você deve seguir a documentação do CMS intlayer.

      Para poder visualizar o seletor do editor intlayer, você deverá usar a sintaxe de componente no seu conteúdo intlayer.

      Component.svelte
      <script lang="ts">
        import { useIntlayer } from "svelte-intlayer";
      
        const content = useIntlayer("component");
      </script>
      
      <div>
      
        <!-- Renderizar conteúdo como conteúdo simples -->
        <h1>{$content.title}</h1>
      
        <!-- Renderizar conteúdo como um componente (requerido pelo editor) -->
        {@const Component = $content.component}<Component />
      </div>
      
    12. Extrair o conteúdo dos seus componentes

      Opcional

      Se você tiver uma base de código existente, transformar milhares de arquivos pode ser demorado.

      Para facilitar esse processo, o Intlayer propõe um compilador / extrator para transformar seus componentes e extrair o conteúdo.

      Para configurá-lo, você pode adicionar uma seção compiler no seu arquivo intlayer.config.ts:

      intlayer.config.ts
      import { type IntlayerConfig } from "intlayer";
      
      const config: IntlayerConfig = {
        // ... Resto da sua configuração
        compiler: {
          /**
           * Indica se o compilador deve ser ativado.
           */
          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. Dessa forma, o compilador pode ser executado apenas uma vez para transformar o aplicativo e depois removido.
           */
          saveComponents: false,
      
          /**
           * Prefixo da chave do dicionário
           */
          dictionaryKeyPrefix: "",
        },
      };
      
      export default config;
      

      Execute o extrator para transformar seus componentes e extrair o conteúdo

      bash
      npx intlayer extract
      
      Since v9, the intlayerCompiler is included in the intlayer plugin. So you don't need to add it manually.

      Atualize seu vite.config.ts para incluir o plugin intlayerCompiler:

      vite.config.ts
      import { defineConfig } from "vite";
      import { intlayer, intlayerCompiler } from "vite-intlayer";
      
      export default defineConfig({
        plugins: [
          intlayer(),
          intlayerCompiler(), // Adds the compiler plugin
        ],
      });
      
      bash
      npm run build # Ou npm run dev
      

    Configuração do Git

    É recomendado ignorar os arquivos gerados pelo Intlayer.

    .gitignore
    # Ignorar os arquivos gerados pelo Intlayer
    .intlayer
    

    Ir Além

    • Editor Visual: Integre o Editor Visual Intlayer para editar traduções diretamente pela interface.
    • CMS: Externalize o gerenciamento do seu conteúdo usando o CMS Intlayer.

    Perguntas Frequentes

    • svelte-i18n e typesafe-i18n: catálogos de mensagens baseados em stores, conectados manualmente nas funções load.
    • Paraglide: mensagens compiladas com forte suporte a tipos, porém focado apenas na camada de mensagens.
    • Intlayer: a solução mais avançada. O conteúdo pode ser declarado em qualquer lugar da sua base de código (ao lado de cada componente ou centralizado) e compilado em tempo de build, com roteamento com suporte a locales, detecção de idioma no servidor, tradução por IA, editor visual e CMS.

    No SvelteKit a diferença se destaca nas partes de servidor: detecção de locale nos hooks, links localizados e a integração com o editor já vêm prontos na biblioteca, sem precisar serem configurados do zero a cada projeto. Consulte por que Intlayer e o benchmark Svelte i18n.

    Muito menos do que uma configuração baseada em namespaces, porque uma página nunca baixa um catálogo que não renderiza. O markup renderizado no servidor (SSR) resolve suas mensagens diretamente no servidor, e o compilador em tempo de build substitui as chamadas useIntlayer pelas entradas exatas que o componente utiliza. Assim, chaves e idiomas não utilizados são descartados, e os dicionários dinâmicos dividem o restante por locale. Comparado às soluções tradicionais, o Intlayer reduz o tamanho do bundle e da página em até 50%. Consulte otimização de bundle e o benchmark.

    Em grande parte, sim. Siga o guia de migração do Svelte I18n para migrar seu conteúdo. Você também pode migrar gradualmente: o plugin sync JSON mantém seus catálogos JSON existentes como fonte de verdade e gera dicionários Intlayer a partir deles, mantendo ambas as camadas sincronizadas enquanto você migra componentes um a um.

    Sim. O plugin sync JSON mantém seus arquivos /messages/{locale}/{namespace}.json como fonte de verdade e gera dicionários Intlayer a partir deles, em ambas as direções. O plugin sync PO faz o mesmo para catálogos gettext, e os arquivos por locale permitem dividir o conteúdo por idioma em vez de agrupar todos os locales em um único arquivo.

    Não. Execute npx intlayer extract e o Intlayer lê seus componentes, extrai as strings voltadas para o usuário e escreve um arquivo .content ao lado de cada um, para que você revise um diff em vez de copiar strings para um catálogo uma a uma. O passo 12 deste guia detalha esse processo.

    Para um fluxo de trabalho totalmente automatizado, o Intlayer Compiler faz o mesmo em tempo de build: ele analisa seu código JSX, TSX, Vue e Svelte a cada alteração, gera os dicionários e os mantém sincronizados via hot module replacement, dispensando completamente a manutenção manual de chaves.

    Dois limites são importantes considerar: o compilador opera por análise estática, de modo que strings criadas apenas em tempo de execução (como códigos de erro de API ou campos dinâmicos de CMS) ficam fora de alcance. Além disso, ele precisa distinguir texto visível de lógicas de aplicação como className="active" ou status codes, exigindo algumas anotações em bases de código extensas. O comando extract evita ambos mantendo você no controle.

    Cinco ferramentas, todas opcionais:

    • Extensão VS Code: navegue de uma chave useIntlayer diretamente para o arquivo de conteúdo que a declara, extraia conteúdo de um componente e execute build, fill, test, push e pull pela paleta de comandos ou pela aba dedicada do Intlayer.
    • Servidor LSP: a mesma inteligência em qualquer editor compatível com LSP, com ir para definição, localizar referências, pré-visualizações de valores traduzidos ao passar o mouse, autocompletar e alertas para chaves não declaradas. Também resolve chamadas de i18next, react-i18next, next-intl e use-intl, facilitando a migração.
    • Servidor MCP: expõe a documentação e a CLI do Intlayer para Cursor, VS Code, Claude Desktop, Claude Code e ChatGPT, permitindo que os assistentes respondam com base na documentação atualizada e executem comandos como intlayer fill.
    • Agent Skills: habilidades focadas como intlayer-config, intlayer-cli e intlayer-content, além de uma por framework, ensinando ao agente suas regras de roteamento e tipos de nós.
    • Plugin ESLint: a regra no-raw-text identifica strings hardcoded, com regras adicionais para chaves estáticas e conteúdo não utilizado.