Autor:
    Criação:2026-08-12Última atualização:2026-08-13

    Plugin ESLint x OXLint

    O eslint-plugin-intlayer detecta os tipos de erros de i18n que o TypeScript não consegue identificar:

    1. Texto codificado diretamente (hardcoded) que nunca chegou a um dicionário.
    2. Chamadas dinâmicas que passam na verificação de tipos e são executadas, mas que o compilador do Intlayer não consegue otimizar.
    3. Conteúdo morto — dicionários e campos que nada no projeto lê (ativação opcional).

    Chaves de dicionário desconhecidas, caminhos de campos desconhecidos e idiomas ausentes já são erros de compilação, portanto o plugin não os repete.

    Instalação

    bash
    npm install --save-dev eslint-plugin-intlayer

    Requer o ESLint 9 ou superior (flat config). O ESLint 10 é compatível.

    Utilização

    O plugin funciona tanto no ESLint quanto no oxlint — com as mesmas regras e as mesmas opções.

    Ou espalhe uma configuração e defina você mesmo as severidades:

    Configurações

    Configuração no-raw-text static-dictionary-key no-dynamic-field-access enforce-adapter-import no-unused-content
    recommended warn error error off off
    strict error (+ literais fora de JSX) error error error off
    contract-only off error error off off

    A configuração recommended mantém deliberadamente no-raw-text como warn: apontá-la para uma base de código existente traz à tona todas as strings não traduzidas de uma só vez, o que não deve quebrar a sua compilação logo no primeiro dia.

    O enforce-adapter-import fica desativado por padrão — ative-o explicitamente se desejar.

    O no-unused-content fica desativado em todas as configurações, inclusive na strict. É a única regra que lê sua configuração do Intlayer e percorre seus arquivos de código no disco; portanto, ativá-la deve ser uma escolha consciente e não algo imposto por uma predefinição.

    Regras

    no-raw-text

    Reporta texto voltado ao usuário que não esteja declarado em um dicionário. Ele usa a mesma detecção do intlayer extract, portanto nomes de marcas, classes CSS e identificadores técnicos são ignorados.

    jsx
    // ✗ Reportado<h1>Welcome to our documentation</h1><input placeholder="Enter your email address" />// ✓ Corretoconst { title } = useIntlayer("home");<h1>{title}</h1>

    Arquivos de declaração de conteúdo (*.content.ts, …) são ignorados.

    Para corrigir um arquivo inteiro de uma só vez, execute npx intlayer extract e deixe o compilador mover as strings para um dicionário para você.

    Opções

    static-dictionary-key

    Exige que a chave do dicionário seja uma string literal.

    O compilador só consegue pré-carregar um dicionário quando pode ler a chave diretamente no local da chamada. Com uma chave calculada, ele pula silenciosamente a otimização e inclui todos os dicionários no bundle.

    typescript
    // ✗ ReportadouseIntlayer(dictionaryKey);useIntlayer(`home-${suffix}`);getTranslations({ namespace: page });// ✗ Uma variável ainda não é um literalconst key = "home";useIntlayer(key);// ✓ CorretouseIntlayer("home");getTranslations({ namespace: "home" });

    Isso se aplica ao useIntlayer, getIntlayer e a todos os adaptadores de compatibilidade (useTranslation, useTranslations, formatMessage, <FormattedMessage id>, <Trans i18nKey>, …).

    no-dynamic-field-access

    Exige que o campo lido de um dicionário seja conhecido estaticamente.

    O compilador remove campos que não são identificados como utilizados. Um acesso computado é invisível para ele, portanto a leitura pode retornar undefined em tempo de execução.

    typescript
    // ✗ Reportadoconst content = useIntlayer("home");content[fieldName];const t = useTranslations("home");t(messageKey);// ✓ Corretocontent.title;content["title"];content.items[0];t("hero.title");

    enforce-adapter-import

    Prefere o adaptador de compatibilidade @intlayer/* ao pacote original. O original só é resolvido para o Intlayer quando o alias do empacotador está configurado; o adaptador sempre funciona. Corrigível automaticamente com --fix.

    typescript
    // ✗ Reportadoimport { useTranslation } from "react-i18next";import { getTranslations } from "next-intl/server";// ✓ Corretoimport { useTranslation } from "@intlayer/react-i18next";import { getTranslations } from "@intlayer/next-intl/server";

    no-unused-content

    Desativada por padrão. Reporta conteúdo que nada em seu projeto lê, além de chaves de dicionário declaradas em mais de um local.

    src/home.content.ts
    export default {  key: "home", // ✗ Reportado se nenhum chamador no projeto solicitar "home"  content: {    title: t({ pt: "Título", en: "Title" }),    // ✗ Reportado se nada ler `hero`    hero: {      subtitle: t({ pt: "Subtítulo", en: "Subtitle" }),    },  },};

    Ao contrário das outras regras, esta não pode responder apenas com base no arquivo analisado — um campo só é considerado não utilizado em relação ao projeto inteiro. Na primeira declaração de conteúdo de uma execução do linter, ela carrega a sua configuração do Intlayer, busca os arquivos de código declarados por essa configuração (build.traversePattern, compiler.transformPattern) e executa o mesmo analisador de uso que alimenta o @intlayer/lsp e o tachado de "não utilizado" na extensão do VS Code. O resultado é armazenado em cache por cacheTtl milissegundos, para que a varredura ocorra uma vez por execução e não a cada arquivo.

    Opções

    Diminua cacheTtl ao executar o lint a partir de um servidor de editor de longa duração e quiser que as alterações apareçam mais rápido; defina baseDir quando uma única execução de lint cobrir vários projetos Intlayer em um monorepo.

    Tende ao silêncio. Um falso positivo aqui apagaria uma tradução; portanto, nada é reportado quando o dicionário é consumido de uma forma que a análise não consiga rastrear: o objeto de conteúdo passado por completo, uma função de tradução vinculada a partir dele (const t = useTranslations("home")), uma declaração acessada por importação direta (useDictionary(myDictionary)), um nest() de outro dicionário ou uma lista de campos tornada não exaustiva por um spread. Componentes de arquivo único (.vue, .svelte, .astro) são considerados como usuários de todos os campos dos dicionários mencionados, pois seus blocos de script não são analisados aqui.

    O reportDuplicateKeys lê os dicionários não mesclados que o build grava em .intlayer/, portanto permanece em silêncio até que o projeto tenha sido construído pelo menos uma vez. Duas declarações compartilhando uma chave são mescladas, o que é um padrão válido — o aviso existe porque um campo definido em ambos os lados mantém silenciosamente apenas um dos dois valores.

    O analisador é carregado a partir do @intlayer/lsp, distribuído como ESM. A regra requer, portanto, uma versão do Node compatível com require() em módulos ES — Node 20.19+ ou 22.12+. Em versões anteriores, ela não reporta nada em vez de falhar a execução do lint.

    Frameworks

    Todas as regras funcionam em todas as integrações do Intlayer, inclusive dentro de templates Vue, Svelte e Angular. Você só precisa informar ao ESLint qual parser lê cada tipo de arquivo.

    Framework Arquivos Parser
    React, Preact, Solid, Lit .jsx .tsx typescript-eslint
    Next.js .jsx .tsx typescript-eslint
    Vue, Nuxt .vue vue-eslint-parser
    Svelte, SvelteKit .svelte svelte-eslint-parser
    Angular .ts typescript-eslint
    Templates do Angular .component.html @angular-eslint/template-parser
    Astro .astro astro-eslint-parser

    Instale apenas os parsers de que seu projeto precisa.

    Limitação conhecida. Em templates do Vue e Angular, uma expressão como {{ content[key] }} não é verificada pelo no-dynamic-field-access. Leituras dinâmicas escritas no bloco script são identificadas normalmente.