feat(i18n): add eloqnt lint, and fix what it found - #9106
Conversation
Each key was verified unreferenced with a repository-wide literal search (excluding the locale catalogs). Eighteen are leftovers from the removed search-chat feature, and navBar.links.guides/.security no longer have entries in navigation.json. components.metabar.addedIn/.viewAs occur only as Storybook fixture data, and no blog post uses the advisory-board category. Keys are removed from ar.json as well, although that locale is disabled, so it does not drift further.
Both dropped an argument the English source defines and rendered
silently, because use-intl drops an unused tag or value rather than
throwing:
- es layouts.download.codeBox.unsupportedVersionWarning lost its <link>
tag, so the sentence ended on a colon and the EOL-support link never
rendered.
- zh-tw layouts.download.codeBox.platformInfo.default lost {platform},
so the sentence named no package manager.
Note: these two strings are machine-suggested and should be replaced
via 'eloqnt translate' or reviewed by a native speaker before release.
Removes 812 stale entries across ten translation files, covering keys that were dropped from the source catalog but survived in translations. Most of it is one fact: the components.navigation.learn.* subtree (57 keys) was removed from en.json when the learn section moved to an external link, and lived on in ten locales. The list is derived from 'eloqnt lint --json' superfluous-key findings, not transcribed by hand. en.json itself is untouched.
Adds @eloqnt/cli and a config covering the 14 enabled locales from packages/i18n/src/config.json (ar is disabled and deliberately absent). The orphan-message rule resolves a key only when the call site names it as a literal string. This codebase builds some keys at runtime — labels come from navigation.json and constants.json, and several components interpolate a variable into the key — so the rule is turned off for exactly those keys via lint.overrides. Namespaces that also hold statically referenced keys list the dynamic ones individually instead of using a wildcard, so the rule keeps covering the rest. Result: eloqnt lint reports 0 errors and 562 pre-existing missing-translation warnings.
…nents from srcPath The locale list now comes from packages/i18n/src/config.json (enabled locales only) instead of being duplicated. 'infer' is not used because it would pick up the disabled ar.json from disk. packages/ui-components does not use next-intl — components receive translated strings as props — and removing it from srcPath leaves the lint result unchanged (verified: 0 errors, 562 warnings).
The i18n message cleanup does not need a release; the empty changeset keeps the Changesets CI check satisfied without bumping the package.
Adds a root lint:i18n script following the same pattern as the root prettier task: the tool spans apps/site and packages/i18n, so it is installed at the workspace root and wired into the Quality checks job via a turbo root task. Also shortens the config comment per review.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Note Your Pull Request seems to be updating Translations of the Node.js Website. Whilst we appreciate your intent; Any Translation update should be done through our Crowdin Project. Thank you! |
eloqnt lint, and fix what it found
858738f to
cfa92d5
Compare
cfa92d5 to
db0b4db
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #9106 +/- ##
===========================================
+ Coverage 75.13% 86.13% +10.99%
===========================================
Files 102 86 -16
Lines 9114 6051 -3063
Branches 376 357 -19
===========================================
- Hits 6848 5212 -1636
+ Misses 2262 835 -1427
Partials 4 4 ☔ View full report in Codecov by Harness. |
📦 Build Size ComparisonSummary
Changes🔄 Modified Routes (5)
|
|
Sure thing, glad to hear if this looks useful to you! Maybe you need to upload both source files as well as translations to Crowdin to avoid the next Crowdin sync from reintroducing already fixed bugs? |
Description
Not sure if you've seen it, but I've worked on
eloqnt/cli, a linter for i18n issues that is specifically made fornext-intlusers.Since nodejs.org is open source, I gave it a go on your messages. It found 920 errors that were fixable.
Claude Code added some inline comments for explanation.
Up to you if you're interested in adopting
eloqnt/cli, but I think the errors are worth fixing in any case!What it found
Two user-visible translation bugs, both silent at runtime because
use-intldrops an unused tag or value rather than throwing:<link>tag, so the sentence ends on a colon and the link never renders.{platform}, so it names no package manager.36 dead keys, including 18 left over from a removed search-chat feature, and two navigation labels (
navBar.links.guides,.security) that no longer appear innavigation.json.140 keys in translation files with no counterpart in
en.json— 57 of them thecomponents.navigation.learn.*subtree, left behind when the learn section moved to an external link.Result
eloqnt lintreports 0 errors. The remaining 562 warnings are untranslated strings, which are pre-existing and unrelated to this PR.Validation
pnpm run lint:i18ngoes from 920 errors / 719 warnings to 0 errors / 562 warnings; every remaining warning is amissing-translation, all pre-existing (the drop from 719 came from removing translations of the dead keys).withMetaBar.tsx,navigation.json, blog category front matter) were checked by hand.git diffonpackages/i18n/src/localestouches every locale file and only locale files; the superfluous-key removal did not changeen.json.pnpm testandpnpm buildpass;tsc --noEmitran via the pre-commit hook on every commit.Related Issues
Check List
pnpm formatto ensure the code follows the style guide.pnpm testto check if all tests are passing.pnpm buildto check if the website builds without errors.