Creation:2026-03-23Last update:2026-05-06

    Traduza o seu website Vite e Lit usando Intlayer | Internacionalização (i18n)

    ide.intlayer.org

    Tabela de Conteúdos

    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, pode:

    • Gerir facilmente as traduções usando dicionários declarativos ao nível do componente.
    • Localizar dinamicamente metadados, rotas e conteúdo.
    • Garantir o suporte a TypeScript com tipos autogerados, melhorando o autocompletar e a deteção de erros.
    • Beneficiar de funcionalidades avançadas, como a deteção e alternância dinâmica de idioma.

    Guia Passo-a-Passo para Configurar o Intlayer numa Aplicação Vite e Lit

    Passo 1: Instalar Dependências

    Instale os pacotes necessários usando npm:

    bash
    npm install intlayer lit-intlayernpm install vite-intlayer --save-devnpx intlayer init
    • intlayer

      O pacote principal que fornece ferramentas de internacionalização para gestão de configuração, tradução, declaração de conteúdo, transpilação e comandos CLI.

    • lit-intlayer O pacote que integra o Intlayer com aplicações Lit. Fornece hooks baseados em ReactiveController (useIntlayer, useLocale, etc.) para que os LitElements sejam renderizados novamente de forma automática quando o idioma muda.

    • vite-intlayer Inclui o plugin Vite para integrar o Intlayer com o bundler Vite, bem como middleware para detetar o idioma preferido do utilizador, gerir cookies e lidar com redirecionamento de URL.

    Passo 2: Configuração do seu projeto

    Crie um ficheiro de configuração para configurar os idiomas da sua aplicação:

    intlayer.config.ts
    import { Locales, type IntlayerConfig } from "intlayer";
    
    const config: IntlayerConfig = {
      internationalization: {
        locales: [
          Locales.ENGLISH,
          Locales.FRENCH,
          Locales.SPANISH,
          // Os seus outros idiomas
        ],
        defaultLocale: Locales.ENGLISH,
      },
    };
    
    export default config;
    Através deste ficheiro de configuração, pode configurar URLs localizados, redirecionamento de middleware, nomes de cookies, a localização e extensão das suas declarações de conteúdo, desativar os logs do Intlayer na consola 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 Vite

    Adicione o plugin intlayer na sua configuração.

    vite.config.ts
    import { defineConfig } from "vite";
    import { intlayer } from "vite-intlayer";
    
    // https://vitejs.dev/config/
    export default defineConfig({
      plugins: [intlayer()],
    });
    O plugin Vite intlayer() é usado para integrar o Intlayer com o Vite. Garante a construção dos ficheiros de declaração de conteúdo e monitoriza-os em modo de desenvolvimento. Define variáveis de ambiente do Intlayer dentro da aplicação Vite. Adicionalmente, fornece pseudónimos para otimizar o desempenho.

    Passo 4: Inicializar o Intlayer no seu ponto de entrada

    Chame installIntlayer() antes de quaisquer elementos personalizados serem registados para que o singleton global de idioma esteja pronto quando o primeiro elemento se ligar.

    src/main.ts
    import { installIntlayer } from "lit-intlayer";// Deve ser chamado antes de qualquer LitElement ser ligado ao DOM.installIntlayer();// Importe e registe os seus elementos personalizados.import "./my-element.js";

    Se também usar declarações de conteúdo md() (Markdown), instale também o renderizador de markdown:

    src/main.ts
    import { installIntlayer, installIntlayerMarkdown } from "lit-intlayer";installIntlayer();installIntlayerMarkdown();import "./my-element.js";

    Passo 5: Declarar o Seu Conteúdo

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

    src/app.content.ts
    import { t, type Dictionary } from "intlayer";
    
    const appContent = {
      key: "app",
      content: {
        title: "Vite + Lit",
    
        viteLogo: t({
          en: "Vite logo",
          fr: "Logo Vite",
          es: "Logo Vite",
        }),
        litLogo: t({
          en: "Lit logo",
          fr: "Logo Lit",
          es: "Logo Lit",
        }),
    
        count: t({
          en: "count is {{count}}",
          fr: "le compte est {{count}}",
          es: "el recuento es {{count}}",
        }),
    
        readTheDocs: t({
          en: "Click on the Vite and Lit logos to learn more",
          fr: "Cliquez sur les logos Vite et Lit pour en savoir plus",
          es: "Haga clic en los logotipos de Vite y Lit para obtener más información",
        }),
      },
    } 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ório contentDir (por padrão, ./src) e correspondam à extensão do ficheiro 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 6: Utilizar o Intlayer no seu LitElement

    Use o useIntlayer dentro de um LitElement. Ele retorna um proxy ReactiveController que ativa automaticamente re-renderizações sempre que o idioma ativo muda - não é necessária configuração extra.

    src/my-element.ts
    import { LitElement, html } from "lit";import { customElement, property } from "lit/decorators.js";import { useIntlayer } from "lit-intlayer";@customElement("my-element")export class MyElement extends LitElement {  @property({ type: Number })  count = 0;  // useIntlayer regista-se como um ReactiveController.  // O elemento é renderizado novamente de forma automática quando o idioma muda.  private content = useIntlayer(this, "app");  override render() {    const { content } = this;    return html`      <h1>${content.title}</h1>      <img src="/vite.svg" alt=${content.viteLogo.value} />      <img src="/lit.svg" alt=${content.litLogo.value} />      <button @click=${() => this.count++}>        ${content.count({ count: this.count })}      </button>      <p>${content.readTheDocs}</p>    `;  }}

    Quando precisar da string traduzida num atributo HTML nativo (ex: alt, aria-label, title), chame .value no nó folha:

    typescript
    html`<img alt=${content.viteLogo.value} />`;html`<img alt=${content.viteLogo.toString()} />`;html`<img alt=${String(content.viteLogo)} />`;

    (Opcional) Passo 7: Alterar o idioma do seu conteúdo

    Para alterar o idioma do seu conteúdo, use o método setLocale exposto pelo controlador useLocale.

    src/locale-switcher.ts
    import { LitElement, html } from "lit";import { customElement } from "lit/decorators.js";import { getLocaleName } from "intlayer";import { useLocale } from "lit-intlayer";@customElement("locale-switcher")export class LocaleSwitcher extends LitElement {  private locale = useLocale(this);  private _onChange(e: Event) {    const select = e.target as HTMLSelectElement;    this.locale.setLocale(select.value as any);  }  override render() {    return html`      <select @change=${this._onChange}>        ${this.locale.availableLocales.map(          (loc) => html`            <option value=${loc} ?selected=${loc === this.locale.locale}>              ${getLocaleName(loc)}            </option>          `        )}      </select>    `;  }}

    (Opcional) Passo 8: Renderizar conteúdo Markdown e HTML

    O Intlayer suporta declarações de conteúdo md() e html(). No Lit, a saída compilada é injetada como HTML bruto através da diretiva unsafeHTML.

    Renderize o HTML compilado no seu elemento:

    src/my-element.ts
    import { LitElement, html } from "lit";import { customElement } from "lit/decorators.js";import { unsafeHTML } from "lit/directives/unsafe-html.js";import { useIntlayer } from "lit-intlayer";import { compileMarkdown } from "lit-intlayer/markdown";@customElement("my-element")export class MyElement extends LitElement {  private content = useIntlayer(this, "app");  override render() {    return html`      <div class="edit-note">        ${unsafeHTML(compileMarkdown(String(this.content.editNote)))}      </div>    `;  }}
    TIP
    String(content.editNote) chama toString() no IntlayerNode, que retorna a string Markdown bruta. Passe-a para compileMarkdown para obter uma string HTML, e depois renderize-a com a diretiva unsafeHTML do Lit.

    (Opcional) Passo 9: Adicionar Localized Routing à sua aplicação

    Para criar rotas únicas para cada idioma (útil para SEO), pode usar um router do lado do cliente juntamente com os ajudantes localeMap / localeFlatMap do Intlayer, e o plugin Vite intlayerProxy para deteção de idioma do lado do servidor.

    Primeiro, adicione o intlayerProxy à sua configuração Vite:

    Note que para usar o intlayerProxy em produção, precisa de mover o vite-intlayer de devDependencies para dependencies.
    vite.config.ts
    import { defineConfig } from "vite";
    import { intlayer, intlayerProxy } from "vite-intlayer";
    
    export default defineConfig({
      plugins: [
        intlayerProxy(), // should be placed first
        intlayer(),
      ],
    });

    (Opcional) Passo 10: Alterar o URL quando o idioma muda

    Para atualizar o URL do navegador quando o idioma muda, use o useRewriteURL juntamente com o seletor de idioma:

    src/locale-switcher.ts
    import { LitElement, html } from "lit";import { customElement } from "lit/decorators.js";import { getLocaleName, getLocalizedUrl } from "intlayer";import { useLocale, useRewriteURL } from "lit-intlayer";@customElement("locale-switcher")export class LocaleSwitcher extends LitElement {  private locale = useLocale(this);  // Re-escreve automaticamente o URL atual quando o idioma muda.  private _rewriteURL = useRewriteURL(this);  private _onChange(e: Event) {    const select = e.target as HTMLSelectElement;    this.locale.setLocale(select.value as any);  }  override render() {    return html`      <select @change=${this._onChange}>        ${this.locale.availableLocales.map(          (loc) => html`            <option value=${loc} ?selected=${loc === this.locale.locale}>              ${getLocaleName(loc)}            </option>          `        )}      </select>    `;  }}

    (Opcional) Passo 11: Alternar os Atributos de Idioma e Direção HTML

    Atualize os atributos lang e dir da tag <html> para corresponderem ao idioma atual para acessibilidade e SEO.

    src/my-element.ts
    import { LitElement, html } from "lit";import { customElement } from "lit/decorators.js";import { getHTMLTextDir } from "intlayer";import { useLocale } from "lit-intlayer";@customElement("my-element")export class MyElement extends LitElement {  private locale = useLocale(this, {    onLocaleChange: (loc) => {      document.documentElement.lang = loc;      document.documentElement.dir = getHTMLTextDir(loc);    },  });  override render() {    return html`<!-- o seu conteúdo -->`;  }}

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

    Se tiver uma base de código existente, transformar milhares de ficheiros 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, pode adicionar uma secção compiler no seu ficheiro intlayer.config.ts:

    intlayer.config.ts
    import { type IntlayerConfig } from "intlayer";const config: IntlayerConfig = {  // ... Restante da sua configuração  compiler: {    /**     * Indica se o compilador deve estar habilitado.     */    enabled: true,    /**     * Define o caminho dos ficheiros de saída     */    output: ({ fileName, extension }) => `./${fileName}${extension}`,    /**     * Indica se os componentes devem ser guardados após serem transformados.     * Dessa forma, o compilador pode ser executado apenas uma vez para transformar a app, e depois pode ser removido.     */    saveComponents: false,    /**     * Prefixo da chave do dicionário     */    dictionaryKeyPrefix: "",  },};export default config;

    (Opcional) Sitemap e robots.txt (geração no build)

    A Intlayer expõe utilitários - generateSitemap e getMultilingualUrls - para formatar um sitemap.xml multilíngue e um robots.txt prontos para crawlers e os gravar automaticamente em public/. Normalmente corre um pequeno script Node antes do Vite (por exemplo hooks npm predev / prebuild) para que os ficheiros existam no build ou no servidor de desenvolvimento.

    Sitemap

    O gerador de sitemaps da Intlayer respeita as suas línguas e inclui os metadados habituais.

    O sitemap suporta o espaço de nomes xhtml:link (hreflang). Em vez de listar apenas URLs soltas, a Intlayer liga de forma bidireccional todas as versões localizadas de cada página (por exemplo /about, /fr/about ou /about?lang=fr consoante o modo de rotas).

    Robots.txt

    Use getMultilingualUrls para que as regras Disallow cubram todas as variantes localizadas de caminhos sensíveis.

    1. Criar generate-seo.mjs na raiz do projeto

    generate-seo.mjs
    import fs from "fs";import path from "path";import { fileURLToPath } from "url";import { generateSitemap, getMultilingualUrls } from "intlayer";const __dirname = path.dirname(fileURLToPath(import.meta.url));const SITE_URL = (process.env.SITE_URL || "http://localhost:5173").replace(  /\/$/,  "");const pathList = [  { path: "/", changefreq: "daily", priority: 1.0 },  { path: "/about", changefreq: "monthly", priority: 0.7 },];const sitemapXml = generateSitemap(pathList, { siteUrl: SITE_URL });fs.writeFileSync(path.join(__dirname, "public", "sitemap.xml"), sitemapXml);const getAllMultilingualUrls = (urls) =>  urls.flatMap((url) => Object.values(getMultilingualUrls(url)));const disallowedPaths = getAllMultilingualUrls(["/admin", "/private"]);const robotsTxt = [  "User-agent: *",  "Allow: /",  ...disallowedPaths.map((path) => `Disallow: ${path}`),  "",  `Sitemap: ${SITE_URL}/sitemap.xml`,].join("\n");fs.writeFileSync(path.join(__dirname, "public", "robots.txt"), robotsTxt);console.log("SEO files generated successfully.");

    O pacote intlayer tem de estar instalado. Defina SITE_URL no ambiente em produção (por exemplo na CI).

    Prefira generate-seo.mjs para ESM no Node. Se usar generate-seo.js, garanta "type": "module" no package.json ou execute o Node com ESM.

    2. Executar o script antes do Vite

    package.json
    {  "scripts": {    "dev": "vite",    "prebuild": "node generate-seo.mjs",    "build": "vite build",    "preview": "vite preview"  }}

    Ajuste os comandos se usar pnpm ou yarn. Também pode invocar o script a partir da CI ou de outro passo do pipeline.

    Configurar TypeScript

    Certifique-se de que a sua configuração TypeScript inclui os tipos autogerados.

    tsconfig.json
    {  "compilerOptions": {    // ...    "experimentalDecorators": true,    "useDefineForClassFields": false,  },  "include": ["src", ".intlayer/**/*.ts"],}
    experimentalDecorators e useDefineForClassFields: false são exigidos pelo Lit para suporte a decoradores.

    Configuração Git

    Recomenda-se ignorar os ficheiros gerados pelo Intlayer. Isso permite-lhe evitar submetê-los para o seu repositório Git.

    Para fazer isso, pode adicionar as seguintes instruções ao seu ficheiro .gitignore:

    bash
    # Ignorar os ficheiros gerados pelo Intlayer.intlayer

    Extensão VS Code

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

    Instalar a partir do VS Code Marketplace

    Esta extensão fornece:

    • Autocompletar para chaves de tradução.
    • Deteção de erros em tempo real para traduções em falta.
    • Pré-visualizaçõ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 Mais Longe

    Para ir mais longe, pode implementar o editor visual ou externalizar o seu conteúdo usando o CMS.