Skip to content

feat(i18n): add eloqnt lint to catch translation errors - #4477

Open
amannn wants to merge 1 commit into
umami-software:devfrom
amannn:add-eloqnt-lint
Open

amannn wants to merge 1 commit into
umami-software:devfrom
amannn:add-eloqnt-lint

Conversation

@amannn

@amannn amannn commented Aug 25, 2026

Copy link
Copy Markdown

Hey! I'm the maintainer of next-intl and I've recently been working on eloqnt/cli, a linter for translation files. I've been running it against public repos to see whether their catalogs carry errors.

On the Umami repo, it found 83 errors across the 53 translated locales:

The largest group is message.share-url, where the English string was reworded and lost its argument, but 37 locales still interpolate {target}:

en-US: Your website stats are publicly available at the following URL:
es-ES: Esta es la URL pública para {target}.

All four call sites (WebsiteShareForm, BoardShareDialog, LinkShareForm, PixelShareForm) call t(messages.shareUrl) without values, so in those 37 locales next-intl fails with MISSING_FORMAT_VALUE and renders the key instead of the sentence.

This PR fixes all 83 and adds the linter so they don't come back. The handful of strings where source text had changed meaning were regenerated with eloqnt translate.

Up to you if you're interested in adopting eloqnt/cli, but you might want the translation fixes in this PR to fix runtime errors and more.

Related:

  • I found your check-missing-messages.js does a similar thing, eloqnt lint goes a bit further though
  • It seems like your ga-ES.json contains Galician, ga is however Irish (Gaeilge)—maybe this should be fixed too?

View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

@vercel

vercel Bot commented Aug 25, 2026

Copy link
Copy Markdown

@amannn is attempting to deploy a commit to the Umami Software Team on Vercel.

A member of the Team first needs to authorize it.

@greptile-apps

greptile-apps Bot commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds Eloqnt translation linting to CI and repairs ICU argument and plural inconsistencies across the locale catalogs.

  • Adds .eloqnt/config.ts, the lint:i18n package script, and a CI lint step.
  • Adds @eloqnt/cli and its transitive dependencies.
  • Updates affected translations to match the source catalog's interpolation and plural structure.

Confidence Score: 4/5

The PR appears safe to merge, with only non-blocking lockfile cleanup recommended to avoid unrelated dependency churn.

The translation and CI changes have no identified behavioral defect, but the generated lockfile modifies existing build-tool resolutions beyond the dependency graph needed for the new linter.

Files Needing Attention: pnpm-lock.yaml

Important Files Changed

Filename Overview
.eloqnt/config.ts Configures the en-US source catalog, inferred JSON locales, and disables orphan detection for dynamically mapped message keys.
.github/workflows/ci.yml Runs translation linting after dependency installation and before tests and builds.
package.json Adds the Eloqnt lint script and CLI development dependency.
pnpm-lock.yaml Locks the new CLI and its transitive dependencies but also contains unrelated dependency-resolution and platform-metadata churn.
public/intl/messages/ga-ES.json Corrects localized ICU argument structure to remain compatible with source-message call sites.
public/intl/messages/km-KH.json Corrects localized ICU argument structure to remain compatible with source-message call sites.

Reviews (1): Last reviewed commit: "feat(i18n): add `eloqnt lint` to catch t..." | Re-trigger Greptile

Comment thread pnpm-lock.yaml
Comment on lines +1096 to +1098
'@eloqnt/cli@0.6.18':
resolution: {integrity: sha512-gIgQu1VOdh6lY91uOC/USmO9MEslRNHtxW9G4rUBUdscvW6DNFSI5Ha6+w+2YzF5EkymtO5TCtnfwLpIajL46g==}
hasBin: true

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Unrelated lockfile resolution churn

Adding @eloqnt/cli also changes existing build-tool resolutions, including tsup's @swc/core version, and removes platform metadata throughout the lockfile. Regenerate it with the repository's CI pnpm version so the dependency change remains scoped and future updates stay auditable.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Adds @eloqnt/cli with a `lint:i18n` script, runs it in CI, and fixes
the 73 errors it found across the 51 translated locales:

- 56 inconsistent-args: stale `{target}` in message.share-url (37
  locales), unescaped `<head>...</head>`, dropped and renamed
  placeholders
- 16 unreachable-plural-case: plural cases with no CLDR category in
  the target locale
- 1 inconsistent-exact-plurals: an =0 case absent from the source

The CI step runs non-strict, so missing translations are reported as
warnings without failing the build.

orphan-message is disabled because keys are resolved through the
labels/messages maps rather than named at call sites.
@amannn

amannn commented Sep 14, 2026

Copy link
Copy Markdown
Author

@franciscao633 I've just rebased this PR, are you by chance interested?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant