InícioAmbiente de testeVitrineAppDocBlog
    • Englishinglês
      EN
    • русскийrusso
      RU
    • 日本語japonês
      JA
    • françaisfrancês
      FR
    • 한국어coreano
      KO
    • 中文chinês
      ZH
    • españolespanhol
      ES
    • Deutschalemão
      DE
    • العربيةárabe
      AR
    • italianoitaliano
      IT
    • British Englishinglês (Reino Unido)
      EN-GB
    • portuguêsportuguês
      PT
    • हिन्दीhindi
      HI
    • Türkçeturco
      TR
    • polskipolonês
      PL
    • Indonesiaindonésio
      ID
    • Tiếng Việtvietnamita
      VI
    • українськаucraniano
      UK
    /
    Filtrar documentação por framework
    Alt+←
    Por que Intlayer?
    Começar
    Conceito
    • Como o Intlayer funciona
    • Configuração
    • TestFillBuildWatchExtractLoginPushPullConfigurationListVersionEditorLiveDebugDoc ReviewDoc TranslateSDK
    • Editor visual
    • CMS
    • Integração CI/CD
    • TraduçãoPluralEnumeraçãoCondiçãoGêneroInserçãoArquivoAninhamentoMarkdownHTMLBusca de função
    • Arquivo por locale
    • Compilador
    • Preenchimento automático
    • Testes
    • Otimização de bundle
    Ambiente
    • Next.js 14 e App Router
      Next.js 15
      Next.js sem locale URL
      Next.js e Page Router
      Compiler
    • Tanstack Start Solid
    • Astro e React
      Astro e Svelte
      Astro e Vue
      Astro e Solid
      Astro e Preact
      Astro e Lit
      Astro e Vanilla JS
    • React Router v7
      React Router v7 (fs-routes)
      Compiler
    • Nuxt e Vue
    • Vite e Solid
    • SvelteKit
    • Vite e Preact
    • Vite e Vanilla JS
    • Vite e Lit
    • Angular 19 (Webpack)
      Analog
    • React CRA
    • React Native e Expo
    • Express.js
      NestJS
      Fastify
      Hono
      Adonis
    • Lynx e React
    Plugins
    • JSON
    • gettext (.po)
    Extensão VS Code
    Agente
    • Servidor MCP
    • Habilidades do agente
    Versões
    • v8
    • v7
    • v6
    Benchmark
    • Next.js
    • TanStack
    • Vue
    • Solid
    • Svelte
    Blog
    Faça uma pergunta
    1. Documentation
    2. Ambiente
    3. Astro
    4. Lit
    \n```\n\n> Se você quiser usar seu conteúdo em un atributo de `string`, como `alt`, `title`, `href`, `aria-label`, etc., você pode usar o valor da função, como:\n\n> ```html\n> \"{content.image.value}\"\n> \"{content.image.toString()}\"\n> \"{String(content.image)}\"\n> ```\n\n> **Nota sobre a configuração de roteamento:**\n> A estrutura de diretórios que você usa depende da configuração `middleware.routing` no `intlayer.config.ts`:\n>\n> - **`prefix-no-default` (padrão):** mantém o idioma padrão na raiz (sem prefixo) e adiciona prefixos aos outros. Use `[...locale]` para capturar todos os casos.\n> - **`prefix-all`:** todos os URLs recebem um prefixo de idioma. Você pode usar o padrão `[locale]` se não precisar lidar com a raiz separadamente.\n> - **`search-param` ou `no-prefix`:** não são necessários diretórios de idioma. O idioma é tratado via parâmetros de consulta ou cookies.\n\n### Passo 6: Criar um componente Custom Element de Lit\n\nCrie um custom element Lit. Chame `installIntlayer` no `connectedCallback` usando o atributo `locale` do servidor para inicializar o singleton de tradução no lado do cliente.\n\n```typescript fileName=\"src/components/lit/LitDemo.ts\"\nimport { LitElement, html } from \"lit\";\nimport { installIntlayer, useIntlayer, useLocale } from \"lit-intlayer\";\nimport { getLocalizedUrl, getLocaleName, type LocalesValues } from \"intlayer\";\n\nclass LitDemo extends LitElement {\n static properties = {\n locale: { type: String },\n };\n\n locale: LocalesValues = \"en\" as LocalesValues;\n\n private _content = useIntlayer(this, \"lit-demo\");\n private _localeCtrl = useLocale(this, {\n onLocaleChange: (newLocale: LocalesValues) => {\n window.location.href = getLocalizedUrl(\n window.location.pathname,\n newLocale\n );\n },\n });\n\n override connectedCallback() {\n super.connectedCallback();\n // Inicializa com a localidade detectada pelo servidor\n installIntlayer({ locale: this.locale as any });\n }\n\n override render() {\n const { greeting, description } = this._content;\n const {\n locale: currentLocale,\n availableLocales,\n setLocale,\n } = this._localeCtrl;\n\n return html`\n
    \n

    ${greeting}

    \n

    ${description}

    \n \n
    \n Mudar idioma:\n
    \n ${availableLocales.map(\n (localeItem) => html`\n setLocale(localeItem)}\n >\n ${getLocaleName(localeItem)}\n ${getLocaleName(localeItem, currentLocale)}\n ${localeItem.toUpperCase()}\n \n `\n )}\n
    \n
    \n
    \n `;\n }\n}\n\ncustomElements.define(\"lit-demo\", LitDemo);\n```\n\n> O atributo `locale` é passado da página Astro (detecção no servidor) e usado para inicializar o `installIntlayer` no `connectedCallback`, definindo o idioma inicial para todos os hooks `ReactiveController` dentro do elemento.\n\n> `useIntlayer` é registrado como um `ReactiveController`. Ele solicita automaticamente uma nova renderização do elemento quando o idioma muda, portanto, nenhuma lógica de inscrição adicional é necessária.\n\n### Passo 7: Adicionar um Seletor de Idioma\n\nA funcionalidade de troca de idioma está integrada diretamente no método `render()` do custom element Lit (veja o passo 6 acima). Ela usa o `useLocale` do `lit-intlayer` e navega para a URL localizada quando um usuário seleciona um novo idioma:\n\n```typescript fileName=\"src/components/lit/LitDemo.ts\"\n// Dentro da classe LitElement, após a configuração do useLocale no passo 6:\n\nprivate _localeCtrl = useLocale(this, {\n onLocaleChange: (newLocale: LocalesValues) => {\n // Navega para a URL localizada ao mudar de idioma\n window.location.href = getLocalizedUrl(window.location.pathname, newLocale);\n },\n});\n\noverride render() {\n const { locale: currentLocale, availableLocales, setLocale } = this._localeCtrl;\n\n return html`\n
    \n Mudar idioma:\n
    \n ${availableLocales.map(\n (localeItem) => html`\n setLocale(localeItem)}\n >\n ${getLocaleName(localeItem)}\n ${getLocaleName(localeItem, currentLocale)}\n ${localeItem.toUpperCase()}\n \n `\n )}\n
    \n
    \n `;\n}\n```\n\n> **Nota sobre a reatividade do Lit:**\n> `useLocale` retorna um `ReactiveController`. Quando o `setLocale` é chamado, o controlador solicita automaticamente uma nova renderização, atualizando o estado do botão ativo sem a necessidade de manipulação manual do DOM.\n\n> **Nota sobre persistência:**\n> O uso de `onLocaleChange` para redirecionar via `window.location.href` garante que a nova URL linguística seja visitada, permitindo que o middleware do Intlayer defina o cookie de idioma e lembre da preferência do usuário em visitas futuras.\n\n### Passo 8: Sitemap e Robots.txt\n\nO Intlayer oferece utilitários para criar dinamicamente o seu sitemap localizado e os arquivos robots.txt.\n\n#### Sitemap\n\nO 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.\n\n> O sitemap gerado pelo Intlayer suporta o namespace `xhtml: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=fr` e `/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.\n\nCrie `src/pages/sitemap.xml.ts` para gerar um sitemap que inclua todas as suas rotas localizadas.\n\n```typescript fileName=\"src/pages/sitemap.xml.ts\"\nimport type { APIRoute } from \"astro\";\nimport { generateSitemap, type SitemapUrlEntry } from \"intlayer\";\n\nconst pathList: SitemapUrlEntry[] = [\n { path: \"/\", changefreq: \"daily\", priority: 1.0 },\n { path: \"/about\", changefreq: \"monthly\", priority: 0.7 },\n];\n\nconst SITE_URL = import.meta.env.SITE ?? \"http://localhost:4321\";\n\nexport const GET: APIRoute = async ({ site }) => {\n const xmlOutput = generateSitemap(pathList, { siteUrl: SITE_URL });\n\n return new Response(xmlOutput, {\n headers: { \"Content-Type\": \"application/xml\" },\n });\n};\n```\n\n#### Robots.txt\n\nCrie `src/pages/robots.txt.ts` para controlar o rastreamento dos motores de busca.\n\n```typescript fileName=\"src/pages/robots.txt.ts\"\nimport type { APIRoute } from \"astro\";\nimport { getMultilingualUrls } from \"intlayer\";\n\nconst getAllMultilingualUrls = (urls: string[]) =>\n urls.flatMap((url) => Object.values(getMultilingualUrls(url)) as string[]);\n\nconst disallowedPaths = getAllMultilingualUrls([\"/admin\", \"/private\"]);\n\nexport const GET: APIRoute = ({ site }) => {\n const robotsTxt = [\n \"User-agent: *\",\n \"Allow: /\",\n ...disallowedPaths.map((path) => `Disallow: ${path}`),\n \"\",\n `Sitemap: ${new URL(\"/sitemap.xml\", site).href}`,\n ].join(\"\\n\");\n\n return new Response(robotsTxt, {\n headers: { \"Content-Type\": \"text/plain\" },\n });\n};\n```\n\n### Configuração do TypeScript\n\nO Intlayer usa o aumento de módulos (module augmentation) para aproveitar o TypeScript, tornando sua base de código mais robusta. Se você usar a sintaxe de decoradores, certifique-se de habilitar `experimentalDecorators` nas suas opções de compilador.\n\n![Preenchimento automático](https://github.com/aymericzip/intlayer/blob/main/docs/assets/autocompletion.png?raw=true)\n\n![Erro de tradução](https://github.com/aymericzip/intlayer/blob/main/docs/assets/translation_error.png?raw=true)\n\nCertifique-se de que sua configuração do TypeScript inclua os tipos gerados automaticamente.\n\n```json5 fileName=\"tsconfig.json\"\n{\n compilerOptions: {\n // ...\n experimentalDecorators: true,\n useDefineForClassFields: false, // Necessário para suporte a decoradores no Lit\n },\n \"include\": [\n // ... sua configuração existente do TypeScript\n \".intlayer/**/*.ts\", // Incluir tipos gerados automaticamente\n ],\n}\n```\n\n### Configuração do Git\n\nRecomenda-se ignorar os arquivos gerados pelo Intlayer. Isso evita committá-los no seu repositório Git.\n\nPara fazer isso, adicione as seguintes instruções ao seu arquivo `.gitignore`:\n\n```bash\n# Ignorar os arquivos gerados pelo Intlayer\n.intlayer\n```\n\n### Extensão do VS Code\n\nPara melhorar sua experiência de desenvolvimento com o Intlayer, você pode instalar a **extensão oficial do Intlayer para VS Code**.\n\n[Instalação pelo VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=intlayer.intlayer-vs-code-extension)\n\nEsta extensão fornece:\n\n- **Preenchimento automático** para chaves de tradução.\n- **Detecção de erros em tempo real** para traduções ausentes.\n- **Visualização inline** do conteúdo traduzido.\n- **Ações rápidas** para criar e atualizar traduções facilmente.\n\nPara mais informações sobre o uso da extensão, consulte a [documentação da Extensão do VS Code](https://intlayer.org/doc/vs-code-extension).\n\n---\n\n### (Opcional) Passo 15: Extrair o conteúdo dos seus componentes\n\nSe você tiver uma base de código existente, transformar milhares de arquivos pode ser demorado.\n\nPara facilitar esse processo, o Intlayer propõe um [compilador](/pt/doc/compiler) / [extrator](/pt/doc/concept/cli/extract) para transformar seus componentes e extrair o conteúdo.\n\nPara configurá-lo, você pode adicionar uma seção `compiler` no seu arquivo `intlayer.config.ts`:\n\n```typescript fileName=\"intlayer.config.ts\" codeFormat={[\"typescript\", \"esm\", \"commonjs\"]}\nimport { type IntlayerConfig } from \"intlayer\";\n\nconst config: IntlayerConfig = {\n // ... Resto da sua configuração\n compiler: {\n /**\n * Indica se o compilador deve ser ativado.\n */\n enabled: true,\n\n /**\n * Define o caminho dos arquivos de saída\n */\n output: ({ fileName, extension }) => `./${fileName}${extension}`,\n\n /**\n * 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.\n */\n saveComponents: false,\n\n /**\n * Prefixo da chave do dicionário\n */\n dictionaryKeyPrefix: \"\",\n },\n};\n\nexport default config;\n```\n\n\n \n\nExecute o extrator para transformar seus componentes e extrair o conteúdo\n\n```bash packageManager=\"npm\"\nnpx intlayer extract\n```\n\n```bash packageManager=\"pnpm\"\npnpm intlayer extract\n```\n\n```bash packageManager=\"yarn\"\nyarn intlayer extract\n```\n\n```bash packageManager=\"bun\"\nbun x intlayer extract\n```\n\n \n \n\nAtualize seu `vite.config.ts` para incluir o plugin `intlayerCompiler`:\n\n```ts fileName=\"vite.config.ts\"\nimport { defineConfig } from \"vite\";\nimport { intlayer, intlayerCompiler } from \"vite-intlayer\";\n\nexport default defineConfig({\n plugins: [\n intlayer(),\n intlayerCompiler(), // Adiciona o plugin do compilador\n ],\n});\n```\n\n```bash packageManager=\"npm\"\nnpm run build # Ou npm run dev\n```\n\n```bash packageManager=\"pnpm\"\npnpm run build # Or pnpm run dev\n```\n\n```bash packageManager=\"yarn\"\nyarn build # Or yarn dev\n```\n\n```bash packageManager=\"bun\"\nbun run build # Or bun run dev\n```\n\n \n\n\n---\n\n### Aprofunde seu conhecimento\n\nSe quiser saber mais, você também pode implementar o [Editor Visual](/pt/doc/concept/editor) ou usar o [CMS](/pt/doc/concept/cms) para externalizar seu conteúdo.\n","about":"Aprenda como adicionar internacionalização (i18n) ao seu site Astro + Lit com o Intlayer. Siga este guia para tornar seu site multilíngue.","url":"https://intlayer.org/pt/doc/environment/astro/lit","datePublished":"24-04-2026","dateModified":"06-05-2026","keywords":"internacionalização, documentação, Intlayer, Astro, Lit, Web Components, i18n, JavaScript","license":"https://raw.githubusercontent.com/aymericzip/intlayer/refs/heads/main/LICENSE","audience":{"@type":"Audience","audienceType":"Desenvolvedores, Gerentes de Conteúdo"}}
    Criação:2026-04-24Última atualização:2026-05-06
    Ver o modelo de aplicação no GitHub

    Esta página tem um modelo de aplicação disponível.

    Referência esta documentação ao seu assistente AI favorito
    ChatGPT
    Claude
    DeepSeek
    Google AI mode
    Gemini
    Perplexity
    Mistral
    Grok

    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

    1. "Atualizar o uso da API useIntlayer do Solid para acesso direto a propriedades"
      v8.9.004/05/2026
    2. "Documentação inicial para Astro + Lit"
      v8.7.724/04/2026

    O conteúdo desta página foi traduzido com uma IA.

    Veja a última versão do conteúdo original em inglês
    Editar esta documentação

    Se 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ção
    Copiar

    Copiar o Markdown do documento para a área de transferência

    Traduza o seu site Astro + Lit com o Intlayer | Internacionalização (i18n)

    Índice

    O que é o Intlayer?

    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 metadversas, rotas e conteúdo dinamicamente.
    • Garantir suporte TypeScript: Com tipos gerados automaticamente para melhor preenchimento automático e detecção de erros.
    • Beneficiar de recursos avançados: Como detecção dinâmica de idioma e troca de idioma.

    Guia passo a passo para configurar o Intlayer no Astro + Lit

    ide.intlayer.org

    Confira o modelo da aplicação no GitHub.

    Passo 1: Instalar Dependências

    Instale os pacotes necessários usando seu gerenciador de pacotes preferido:

    bash
    Copiar código

    Copiar o código para a área de transferência

    npm install intlayer astro-intlayer lit lit-intlayer @astrojs/litnpx intlayer init
    • intlayer O pacote principal que fornece ferramentas de i18n para gerenciamento de configuração, traduções, declaração de conteúdo, transpilação e comandos CLI.

    • astro-intlayer Inclui o plugin de integração do Astro para vincular o Intlayer ao bundler Vite, bem como o middleware para detectar o idioma preferido do usuário, gerenciar cookies e lidar com redirecionamentos de URL.

    • lit Pacote principal do Lit para criar Web Components rápidos e leves.

    • lit-intlayer Pacote para integrar o Intlayer em aplicações Lit. Ele fornece hooks baseados em ReactiveController (useIntlayer, useLocale, etc.) que instruem automaticamente o LitElement a renderizar novamente quando o idioma muda.

    • @astrojs/lit Integração oficial do Astro que permite o uso de custom elements Lit dentro de páginas Astro.

    Passo 2: Configurar seu Projeto

    Crie um arquivo de configuração para definir os idiomas da sua aplicação:

    intlayer.config.ts
    Copiar código

    Copiar 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,      // Seus outros idiomas    ],    defaultLocale: Locales.ENGLISH,  },};export default config;
    Através deste arquivo de configuração, você pode configurar URLs localizadas, redirecionamentos de middleware, nomes de cookies, localização e extensões de 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 3: Integrar o Intlayer na sua configuração do Astro

    Adicione o plugin intlayer e a integração do Lit à sua configuração do Astro.

    astro.config.ts
    Copiar código

    Copiar o código para a área de transferência

    // @ts-checkimport { intlayer } from "astro-intlayer";import lit from "@astrojs/lit";import { defineConfig } from "astro/config";// https://astro.build/configexport default defineConfig({  integrations: [intlayer(), lit()],});
    O plugin de integração intlayer() é usado para integrar o Intlayer ao Astro. Ele garante a geração dos arquivos de declaração de conteúdo e os monitora em modo de desenvolvimento. Ele define variáveis de ambiente do Intlayer dentro da aplicação Astro e fornece aliases para otimizar o desempenho.
    A integração lit() permite o uso de custom elements Lit dentro de páginas Astro.

    Passo 4: Declarar seu conteúdo

    Crie e gerencie suas declarações de conteúdo para armazenar traduções:

    src/components/lit/app.content.ts
    Copiar código

    Copiar o código para a área de transferência

    import { t, type Dictionary } from "intlayer";const litDemoContent = {  key: "lit-demo",  content: {    greeting: t({      en: "Hello World",      fr: "Bonjour le monde",      es: "Hola mundo",      pt: "Olá Mundo",    }),    description: t({      en: "Welcome to my multilingual Astro + Lit site.",      fr: "Bienvenue sur mon site Astro + Lit multilingue.",      es: "Bienvenido a mi sitio Astro + Lit multilingüe.",      pt: "Bem-vindo ao meu site Astro + Lit multilíngue.",    }),  },} satisfies Dictionary;export default litDemoContent;
    As declarações de conteúdo podem ser definidas em qualquer lugar da sua aplicação, desde que estejam incluídas no contentDir (por padrão ./src) 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 informações, consulte a documentação de declaração de conteúdo.

    Passo 5: Usar o conteúdo no Astro

    Você pode consumir os dicionários diretamente nos seus arquivos .astro usando os ajudantes principais exportados do intlayer. Você também deve adicionar metadados de SEO (como hreflang e links canônicos) a cada página. Os custom elements Lit são importados via um <script> no cliente e colocados no corpo da página.

    src/pages/[...locale]/index.astro
    Copiar código

    Copiar o código para a área de transferência

    ---import {  getIntlayer,  getLocaleFromPath,  getLocalizedUrl,  getHTMLTextDir,  getPrefix,  localeMap,  defaultLocale,  type LocalesValues,} from "intlayer";export const getStaticPaths = () => {  return localeMap(({ locale }) => ({    params: { locale: getPrefix(locale).localePrefix },  }));};const locale = getLocaleFromPath(Astro.url.pathname) as LocalesValues;const { greeting } = getIntlayer("lit-demo", locale);---<!doctype html><html lang={locale} dir={getHTMLTextDir(locale)}>  <head>    <meta charset="utf-8" />    <meta name="viewport" content="width=device-width" />    <link rel="icon" type="image/svg+xml" href="/favicon.svg" />    <title>{greeting}</title>    <!-- Link Canônico -->    <link      rel="canonical"      href={new URL(getLocalizedUrl(Astro.url.pathname, locale), Astro.site)}    />    <!-- Links Hreflang -->    {      localeMap(({ locale: mapLocale }) => (        <link          rel="alternate"          hreflang={mapLocale}          href={new URL(            getLocalizedUrl(Astro.url.pathname, mapLocale),            Astro.site          )}        />      ))    }    <link      rel="alternate"      hreflang="x-default"      href={new URL(        getLocalizedUrl(Astro.url.pathname, defaultLocale),        Astro.site      )}    />  </head>  <body>    <!-- Custom element Lit - recebe a localidade detectada pelo servidor como uma propriedade -->    <lit-demo locale={locale}></lit-demo>  </body></html><script>  import "../../components/lit/LitDemo";</script>
    Se você quiser usar seu conteúdo em un atributo de string, como alt, title, href, aria-label, etc., você pode usar o valor da função, como:
    html
    Copiar código

    Copiar 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)}" />

    Nota sobre a configuração de roteamento: A estrutura de diretórios que você usa depende da configuração middleware.routing no intlayer.config.ts:

    • prefix-no-default (padrão): mantém o idioma padrão na raiz (sem prefixo) e adiciona prefixos aos outros. Use [...locale] para capturar todos os casos.
    • prefix-all: todos os URLs recebem um prefixo de idioma. Você pode usar o padrão [locale] se não precisar lidar com a raiz separadamente.
    • search-param ou no-prefix: não são necessários diretórios de idioma. O idioma é tratado via parâmetros de consulta ou cookies.

    Passo 6: Criar um componente Custom Element de Lit

    Crie um custom element Lit. Chame installIntlayer no connectedCallback usando o atributo locale do servidor para inicializar o singleton de tradução no lado do cliente.

    src/components/lit/LitDemo.ts
    Copiar código

    Copiar o código para a área de transferência

    import { LitElement, html } from "lit";import { installIntlayer, useIntlayer, useLocale } from "lit-intlayer";import { getLocalizedUrl, getLocaleName, type LocalesValues } from "intlayer";class LitDemo extends LitElement {  static properties = {    locale: { type: String },  };  locale: LocalesValues = "en" as LocalesValues;  private _content = useIntlayer(this, "lit-demo");  private _localeCtrl = useLocale(this, {    onLocaleChange: (newLocale: LocalesValues) => {      window.location.href = getLocalizedUrl(        window.location.pathname,        newLocale      );    },  });  override connectedCallback() {    super.connectedCallback();    // Inicializa com a localidade detectada pelo servidor    installIntlayer({ locale: this.locale as any });  }  override render() {    const { greeting, description } = this._content;    const {      locale: currentLocale,      availableLocales,      setLocale,    } = this._localeCtrl;    return html`      <div>        <h1>${greeting}</h1>        <p>${description}</p>        <!-- Seletor de idioma renderizado dentro do LitElement -->        <div class="locale-switcher">          <span class="switcher-label">Mudar idioma:</span>          <div class="locale-buttons">            ${availableLocales.map(              (localeItem) => html`                <button                  class="locale-btn ${localeItem === currentLocale                    ? "active"                    : ""}"                  ?disabled=${localeItem === currentLocale}                  @click=${() => setLocale(localeItem)}                >                  <span class="ls-own-name">${getLocaleName(localeItem)}</span>                  <span class="ls-current-name"                    >${getLocaleName(localeItem, currentLocale)}</span                  >                  <span class="ls-code">${localeItem.toUpperCase()}</span>                </button>              `            )}          </div>        </div>      </div>    `;  }}customElements.define("lit-demo", LitDemo);
    O atributo locale é passado da página Astro (detecção no servidor) e usado para inicializar o installIntlayer no connectedCallback, definindo o idioma inicial para todos os hooks ReactiveController dentro do elemento.
    useIntlayer é registrado como um ReactiveController. Ele solicita automaticamente uma nova renderização do elemento quando o idioma muda, portanto, nenhuma lógica de inscrição adicional é necessária.

    Passo 7: Adicionar um Seletor de Idioma

    A funcionalidade de troca de idioma está integrada diretamente no método render() do custom element Lit (veja o passo 6 acima). Ela usa o useLocale do lit-intlayer e navega para a URL localizada quando um usuário seleciona um novo idioma:

    src/components/lit/LitDemo.ts
    Copiar código

    Copiar o código para a área de transferência

    // Dentro da classe LitElement, após a configuração do useLocale no passo 6:private _localeCtrl = useLocale(this, {  onLocaleChange: (newLocale: LocalesValues) => {    // Navega para a URL localizada ao mudar de idioma    window.location.href = getLocalizedUrl(window.location.pathname, newLocale);  },});override render() {  const { locale: currentLocale, availableLocales, setLocale } = this._localeCtrl;  return html`    <div class="locale-switcher">      <span class="switcher-label">Mudar idioma:</span>      <div class="locale-buttons">        ${availableLocales.map(          (localeItem) => html`            <button              class="locale-btn ${localeItem === currentLocale ? "active" : ""}"              ?disabled=${localeItem === currentLocale}              @click=${() => setLocale(localeItem)}            >              <span class="ls-own-name">${getLocaleName(localeItem)}</span>              <span class="ls-current-name">${getLocaleName(localeItem, currentLocale)}</span>              <span class="ls-code">${localeItem.toUpperCase()}</span>            </button>          `        )}      </div>    </div>  `;}

    Nota sobre a reatividade do Lit: useLocale retorna um ReactiveController. Quando o setLocale é chamado, o controlador solicita automaticamente uma nova renderização, atualizando o estado do botão ativo sem a necessidade de manipulação manual do DOM.

    Nota sobre persistência: O uso de onLocaleChange para redirecionar via window.location.href garante que a nova URL linguística seja visitada, permitindo que o middleware do Intlayer defina o cookie de idioma e lembre da preferência do usuário em visitas futuras.

    Passo 8: Sitemap e Robots.txt

    O Intlayer oferece utilitários para criar dinamicamente o seu sitemap localizado e os arquivos robots.txt.

    Sitemap

    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 namespace xhtml: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=fr e /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.

    Crie src/pages/sitemap.xml.ts para gerar um sitemap que inclua todas as suas rotas localizadas.

    src/pages/sitemap.xml.ts
    Copiar código

    Copiar o código para a área de transferência

    import type { APIRoute } from "astro";import { generateSitemap, type SitemapUrlEntry } from "intlayer";const pathList: SitemapUrlEntry[] = [  { path: "/", changefreq: "daily", priority: 1.0 },  { path: "/about", changefreq: "monthly", priority: 0.7 },];const SITE_URL = import.meta.env.SITE ?? "http://localhost:4321";export const GET: APIRoute = async ({ site }) => {  const xmlOutput = generateSitemap(pathList, { siteUrl: SITE_URL });  return new Response(xmlOutput, {    headers: { "Content-Type": "application/xml" },  });};

    Robots.txt

    Crie src/pages/robots.txt.ts para controlar o rastreamento dos motores de busca.

    src/pages/robots.txt.ts
    Copiar código

    Copiar o código para a área de transferência

    import type { APIRoute } from "astro";import { getMultilingualUrls } from "intlayer";const getAllMultilingualUrls = (urls: string[]) =>  urls.flatMap((url) => Object.values(getMultilingualUrls(url)) as string[]);const disallowedPaths = getAllMultilingualUrls(["/admin", "/private"]);export const GET: APIRoute = ({ site }) => {  const robotsTxt = [    "User-agent: *",    "Allow: /",    ...disallowedPaths.map((path) => `Disallow: ${path}`),    "",    `Sitemap: ${new URL("/sitemap.xml", site).href}`,  ].join("\n");  return new Response(robotsTxt, {    headers: { "Content-Type": "text/plain" },  });};

    Configuração do TypeScript

    O Intlayer usa o aumento de módulos (module augmentation) para aproveitar o TypeScript, tornando sua base de código mais robusta. Se você usar a sintaxe de decoradores, certifique-se de habilitar experimentalDecorators nas suas opções de compilador.

    Preenchimento automático

    Erro de tradução

    Certifique-se de que sua configuração do TypeScript inclua os tipos gerados automaticamente.

    tsconfig.json
    Copiar código

    Copiar o código para a área de transferência

    {  compilerOptions: {    // ...    experimentalDecorators: true,    useDefineForClassFields: false, // Necessário para suporte a decoradores no Lit  },  "include": [    // ... sua configuração existente do TypeScript    ".intlayer/**/*.ts", // Incluir tipos gerados automaticamente  ],}

    Configuração do Git

    Recomenda-se ignorar os arquivos gerados pelo Intlayer. Isso evita committá-los no seu repositório Git.

    Para fazer isso, adicione as seguintes instruções ao seu arquivo .gitignore:

    bash
    Copiar código

    Copiar o código para a área de transferência

    # Ignorar os arquivos gerados pelo Intlayer.intlayer

    Extensão do VS Code

    Para melhorar sua experiência de desenvolvimento com o Intlayer, você pode instalar a extensão oficial do Intlayer para VS Code.

    Instalação pelo VS Code Marketplace

    Esta extensão fornece:

    • Preenchimento automático para chaves de tradução.
    • Detecção de erros em tempo real para traduções ausentes.
    • Visualização inline do conteúdo traduzido.
    • Ações rápidas para criar e atualizar traduções facilmente.

    Para mais informações sobre o uso da extensão, consulte a documentação da Extensão do VS Code.


    (Opcional) Passo 15: Extrair o conteúdo dos seus componentes

    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
    Copiar código

    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 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
    Copiar código

    Copiar o código para a área de transferência

    npx intlayer extract

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

    vite.config.ts
    Copiar código

    Copiar o código para a área de transferência

    import { defineConfig } from "vite";import { intlayer, intlayerCompiler } from "vite-intlayer";export default defineConfig({ plugins: [   intlayer(),   intlayerCompiler(), // Adiciona o plugin do compilador ],});
    bash
    Copiar código

    Copiar o código para a área de transferência

    npm run build # Ou npm run dev

    Aprofunde seu conhecimento

    Se quiser saber mais, você também pode implementar o Editor Visual ou usar o CMS para externalizar seu conteúdo.

    Astro e Preact
    Astro e Vanilla JS
    Alt+→

    Nesta página

      As discussões são anônimas e regularmente revisadas para resolver problemas comuns. Sinta-se à vontade para compartilhar ideias de funcionalidades, feedback sobre a documentação ou qualquer coisa relacionada ao Intlayer, usamos essas informações para moldar nosso roadmap e melhorar o produto.

      npm install intlayer astro-intlayer lit lit-intlayer @astrojs/litnpx intlayer init
      import { Locales, type IntlayerConfig } from "intlayer";const config: IntlayerConfig = {  internationalization: {    locales: [      Locales.ENGLISH,      Locales.FRENCH,      Locales.SPANISH,      Locales.PORTUGUESE,      // Seus outros idiomas    ],    defaultLocale: Locales.ENGLISH,  },};export default config;
      // @ts-checkimport { intlayer } from "astro-intlayer";import lit from "@astrojs/lit";import { defineConfig } from "astro/config";// https://astro.build/configexport default defineConfig({  integrations: [intlayer(), lit()],});
      import { t, type Dictionary } from "intlayer";const litDemoContent = {  key: "lit-demo",  content: {    greeting: t({      en: "Hello World",      fr: "Bonjour le monde",      es: "Hola mundo",      pt: "Olá Mundo",    }),    description: t({      en: "Welcome to my multilingual Astro + Lit site.",      fr: "Bienvenue sur mon site Astro + Lit multilingue.",      es: "Bienvenido a mi sitio Astro + Lit multilingüe.",      pt: "Bem-vindo ao meu site Astro + Lit multilíngue.",    }),  },} satisfies Dictionary;export default litDemoContent;
      ---import {  getIntlayer,  getLocaleFromPath,  getLocalizedUrl,  getHTMLTextDir,  getPrefix,  localeMap,  defaultLocale,  type LocalesValues,} from "intlayer";export const getStaticPaths = () => {  return localeMap(({ locale }) => ({    params: { locale: getPrefix(locale).localePrefix },  }));};const locale = getLocaleFromPath(Astro.url.pathname) as LocalesValues;const { greeting } = getIntlayer("lit-demo", locale);---<!doctype html><html lang={locale} dir={getHTMLTextDir(locale)}>  <head>    <meta charset="utf-8" />    <meta name="viewport" content="width=device-width" />    <link rel="icon" type="image/svg+xml" href="/favicon.svg" />    <title>{greeting}</title>    <!-- Link Canônico -->    <link      rel="canonical"      href={new URL(getLocalizedUrl(Astro.url.pathname, locale), Astro.site)}    />    <!-- Links Hreflang -->    {      localeMap(({ locale: mapLocale }) => (        <link          rel="alternate"          hreflang={mapLocale}          href={new URL(            getLocalizedUrl(Astro.url.pathname, mapLocale),            Astro.site          )}        />      ))    }    <link      rel="alternate"      hreflang="x-default"      href={new URL(        getLocalizedUrl(Astro.url.pathname, defaultLocale),        Astro.site      )}    />  </head>  <body>    <!-- Custom element Lit - recebe a localidade detectada pelo servidor como uma propriedade -->    <lit-demo locale={locale}></lit-demo>  </body></html><script>  import "../../components/lit/LitDemo";</script>
      <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)}" />
      import { LitElement, html } from "lit";import { installIntlayer, useIntlayer, useLocale } from "lit-intlayer";import { getLocalizedUrl, getLocaleName, type LocalesValues } from "intlayer";class LitDemo extends LitElement {  static properties = {    locale: { type: String },  };  locale: LocalesValues = "en" as LocalesValues;  private _content = useIntlayer(this, "lit-demo");  private _localeCtrl = useLocale(this, {    onLocaleChange: (newLocale: LocalesValues) => {      window.location.href = getLocalizedUrl(        window.location.pathname,        newLocale      );    },  });  override connectedCallback() {    super.connectedCallback();    // Inicializa com a localidade detectada pelo servidor    installIntlayer({ locale: this.locale as any });  }  override render() {    const { greeting, description } = this._content;    const {      locale: currentLocale,      availableLocales,      setLocale,    } = this._localeCtrl;    return html`      <div>        <h1>${greeting}</h1>        <p>${description}</p>        <!-- Seletor de idioma renderizado dentro do LitElement -->        <div class="locale-switcher">          <span class="switcher-label">Mudar idioma:</span>          <div class="locale-buttons">            ${availableLocales.map(              (localeItem) => html`                <button                  class="locale-btn ${localeItem === currentLocale                    ? "active"                    : ""}"                  ?disabled=${localeItem === currentLocale}                  @click=${() => setLocale(localeItem)}                >                  <span class="ls-own-name">${getLocaleName(localeItem)}</span>                  <span class="ls-current-name"                    >${getLocaleName(localeItem, currentLocale)}</span                  >                  <span class="ls-code">${localeItem.toUpperCase()}</span>                </button>              `            )}          </div>        </div>      </div>    `;  }}customElements.define("lit-demo", LitDemo);
      // Dentro da classe LitElement, após a configuração do useLocale no passo 6:private _localeCtrl = useLocale(this, {  onLocaleChange: (newLocale: LocalesValues) => {    // Navega para a URL localizada ao mudar de idioma    window.location.href = getLocalizedUrl(window.location.pathname, newLocale);  },});override render() {  const { locale: currentLocale, availableLocales, setLocale } = this._localeCtrl;  return html`    <div class="locale-switcher">      <span class="switcher-label">Mudar idioma:</span>      <div class="locale-buttons">        ${availableLocales.map(          (localeItem) => html`            <button              class="locale-btn ${localeItem === currentLocale ? "active" : ""}"              ?disabled=${localeItem === currentLocale}              @click=${() => setLocale(localeItem)}            >              <span class="ls-own-name">${getLocaleName(localeItem)}</span>              <span class="ls-current-name">${getLocaleName(localeItem, currentLocale)}</span>              <span class="ls-code">${localeItem.toUpperCase()}</span>            </button>          `        )}      </div>    </div>  `;}
      import type { APIRoute } from "astro";import { generateSitemap, type SitemapUrlEntry } from "intlayer";const pathList: SitemapUrlEntry[] = [  { path: "/", changefreq: "daily", priority: 1.0 },  { path: "/about", changefreq: "monthly", priority: 0.7 },];const SITE_URL = import.meta.env.SITE ?? "http://localhost:4321";export const GET: APIRoute = async ({ site }) => {  const xmlOutput = generateSitemap(pathList, { siteUrl: SITE_URL });  return new Response(xmlOutput, {    headers: { "Content-Type": "application/xml" },  });};
      import type { APIRoute } from "astro";import { getMultilingualUrls } from "intlayer";const getAllMultilingualUrls = (urls: string[]) =>  urls.flatMap((url) => Object.values(getMultilingualUrls(url)) as string[]);const disallowedPaths = getAllMultilingualUrls(["/admin", "/private"]);export const GET: APIRoute = ({ site }) => {  const robotsTxt = [    "User-agent: *",    "Allow: /",    ...disallowedPaths.map((path) => `Disallow: ${path}`),    "",    `Sitemap: ${new URL("/sitemap.xml", site).href}`,  ].join("\n");  return new Response(robotsTxt, {    headers: { "Content-Type": "text/plain" },  });};
      {  compilerOptions: {    // ...    experimentalDecorators: true,    useDefineForClassFields: false, // Necessário para suporte a decoradores no Lit  },  "include": [    // ... sua configuração existente do TypeScript    ".intlayer/**/*.ts", // Incluir tipos gerados automaticamente  ],}
      # Ignorar os arquivos gerados pelo Intlayer.intlayer
      npx intlayer extract
      import { defineConfig } from "vite";import { intlayer, intlayerCompiler } from "vite-intlayer";export default defineConfig({ plugins: [   intlayer(),   intlayerCompiler(), // Adiciona o plugin do compilador ],});
      npm run build # Ou npm run dev