require-explicit-id matches ICU components by JSX name, not import — false positives on UI Select and false negatives on aliased macros
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 33
- Forks
- 25
- Avg merge
- 1d 16h
- Merged PRs (30d)
- 9
Description
## First, thank you
We've been using `eslint-plugin-lingui` across a large monorepo for some time and it's become something we genuinely rely on. With a big team — many of whom don't need to know the intricacies of i18n day to day — these rules quietly enforce the right thing: making sure every message carries the context translators need. That confidence collapses our development cycles, since problems are caught at lint time instead of surfacing later in review or translation. `require-explicit-id` is a big part of that, which is why we wanted to report this carefully rather than just disable it.
## Describe the bug
Since the ICU-component check was added to `require-explicit-id` (#131, released in `0.14.0`), the rule matches purely on the **JSX element name** (`Plural`, `Select`, `SelectOrdinal`), with no check on the import binding. This produces two symmetric problems:
1. **False positive** — any element *named* `Select` is flagged as a "Lingui ICU component", even a plain UI dropdown (shadcn/ui, Radix, MUI, Ant Design, …) that has nothing to do with Lingui. `Select` is an extremely common component name, so this fires broadly. In our codebase, enabling `0.14.0` produced 30 errors — only 4 were genuine `` messages; the other 26 were ordinary UI `` components.
2. **False negative** — a genuine Lingui ICU macro imported under an alias (`import { Select as I18nSelect }`) is silently ignored, because the JSX name as written (`I18nSelect`) no longer matches.
The ICU query matches on element name only:
```js
// helpers.ts
export const LinguiIcuComponentQuery =
':matches(JSXElement[openingElement.name.name=Plural], JSXElement[openingElement.name.name=SelectOrdinal], JSXElement[openingElement.name.name=Select])'
```
## To Reproduce
Minimal repro: https://github.com/Zach-Jaensch/lingui-require-explicit-id-repro
```sh
git clone https://github.com/Zach-Jaensch/lingui-require-explicit-id-repro
cd lingui-require-explicit-id-repro
npm install
npm run lint
```
`src/example.tsx` contains three cases:
| Element | Source | Should report? | Actual |
| --- | --- | --- | --- |
| `` (`ThemePicker`) | local UI component (`./ui/select`) | ❌ no | ⚠️ reported |
| `` (`ItemCount`) | `@lingui/react/macro` (canonical name) | ✅ yes | ✅ reported |
| `` (`Greeting`) | `@lingui/react/macro` (`Select as I18nSelect`) | ✅ yes | ❌ not reported |
### Actual output
```
src/example.tsx
15:5 error Lingui ICU component requires an explicit 'id' attribute lingui/require-explicit-id
27:10 error Lingui ICU component requires an explicit 'id' attribute lingui/require-explicit-id
```
The exact inversion — a non-Lingui `Select` reported while a real (aliased) Lingui `Select` is not — confirms the check is keyed on the element name rather than the import.
## Expected behavior
The rule should apply only to elements actually imported from a Lingui macro entry point, regardless of local alias — mirroring the "only apply to code that is 100% sure to be processed by lingui" principle already established for `text-restrictions` / `no-unlocalized-strings` in #41.
## Suggested fix
Gate the ICU-component check (and ideally the `` check too) on the element's binding resolving to an import from `@lingui/react/macro` / `@lingui/macro`, rather than matching the raw JSX name. This resolves the false positive and the false negative in one change.
## Environment
- `eslint-plugin-lingui`: `0.14.0`
- `eslint`: `9.x`
- `@typescript-eslint/parser`: `8.x`
- Node: `>=18`
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with helpers.ts and the require-explicit-id rule, then run npm install and npm run lint in the linked minimal reproduction. Done means the local UI Select is not reported, while canonical and aliased Lingui ICU components are both checked for an explicit id.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 58/100