@lee-donghyun/eslint-plugin-lingui
v2.2.0
Published
Disallow **raw strings** (`Literal` or `TemplateLiteral`) that are **not** wrapped by a Lingui helper (`t\`\``, `msg\`\``, or `<Trans>\`). The rule targets React / TypeScript projects that use [LinguiJS](https://lingui.dev/) for i18n and encourages exhaus
Maintainers
Readme
@lee-donghyun/lingui/no-unlocalized-strings
Disallow raw strings (Literal or TemplateLiteral) that are not wrapped by a Lingui helper (t\`, msg``, or `).
The rule targets React / TypeScript projects that use LinguiJS for i18n and encourages exhaustive localisation.
Installation
pnpm add -D @lee-donghyun/eslint-plugin-linguiConfiguration
Flat-config (ESLint ≥ 8.21)
// @ts-check
import { defineConfig } from "eslint-config-react-app-essentials";
import pluginLingui from "eslint-plugin-lingui";
import PluginLingui2 from "@lee-donghyun/eslint-plugin-lingui";
export default defineConfig({
tsconfigRootDir: "./tsconfig.json",
scope: ["src/**/*.{ts,tsx}"],
extends: [
pluginLingui.configs["flat/recommended"],
PluginLingui2.configs.recommended,
{
rules: {
"@lee-donghyun/lingui/no-unlocalized-strings": [
"error",
{
ignoreAttributes: ["className", "src", "data-testid"],
ignore: ["^[a-zA-Z0-9\\s\\p{P}\\p{S}]*$"],
},
],
},
},
],
});Rule details
Problems reported
| Message ID | Trigger |
| -------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| default | • A string Literal (e.g. "Hello") or• a TemplateLiteral (e.g. `Hello ${name}`)that is not: • wrapped by t or msg (tagged templates) • placed in a <Trans> element • marked as const ("foo" as const) • matched by an ignore option |
| forJsxText | Raw JSXText between tags (e.g. <p>Hello</p>) |
| forAttribute | Raw string used directly as a JSX attribute value |
The rule is not autofixable – localisation usually needs developer input.
Correct examples
import { t, msg } from "@lingui/macro";
import { Trans } from "@lingui/react";
<button aria-label={t`Close`}>
<Trans>Close</Trans>
</button>;
const TITLE = t`Dashboard`; // tagged template
const error = msg`Error: ${statusCode}`; // tagged template
const HTTP_OK = "200" as const; // allowed (as const)Incorrect examples
console.log("Untranslated log"); // Literal
<button aria-label="닫기">닫기</button>; // attribute + JSXText
<input placeholder={`Search ${name}`} />; // TemplateLiteralOptions
| Option | Type | Default | Description |
| ------------------ | ---------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| ignoreAttributes | string[] | [] | Regex patterns (no flags). Attribute names matching any pattern are skipped. Useful for className, src, testing IDs, etc. |
| ignore | string[] | [] | Regex patterns (Unicode flag u is forced). If all quasis of a template literal or a literal value match, the string is ignored. |
Example:
{
"@lee-donghyun/lingui/no-unlocalized-strings": [
"error",
{
"ignoreAttributes": ["^aria-", "data-testid$"],
"ignore": ["^[0-9]+$", "^\\s*$"] // numbers or whitespace-only
}
]
}