Vendure counted plurals with an English suffix inside a placeholder, so every locale rendered English grammar

vendurehq/vendure, TypeScript, 8.6k stars. The free diagnosis covers the cause, the files and the plan, written for your issue within one working day. The tests come in the sprint.

The issue, in one line

The dashboard built plurals by putting the English suffix in a JSX expression, which Lingui extracts as a second placeholder, so translators filled a placeholder and every non-English locale shipped the English grammar. The issue.

The cause

Each dashboard count put its plural marker in a JSX expression that Lingui extracts as a variable, so the message becomes ‘Found {0} eligible shipping method{1}’ and the second value is the literal string ‘s’ or ‘’. A translator fills a placeholder rather than choosing a plural form, so German shipped ‘2 geeignete Versandmethodes gefunden’ and country/countries stayed English in every non-English catalog.

Where it lives

  • packages/dashboard/src/app/routes/_authenticated/_shipping-methods/components/test-shipping-methods-result.tsx, the ‘found N eligible shipping methods’ count, the exact string from the bug report
  • packages/dashboard/src/app/routes/_authenticated/_test-order/components/test-order-builder.tsx, the item count, which had no translation at all before this change
  • packages/dashboard/src/app/routes/_authenticated/_collections/components/move-collections-dialog.tsx, the dialog description and the target alert
  • packages/dashboard/src/app/routes/_authenticated/_zones/components/zone-bulk-actions.tsx, the remove-from-zone confirmation and success toast
  • packages/dashboard/src/lib/components/shared/asset/asset-gallery.tsx, the ‘# assets found’ count
  • packages/dashboard/src/i18n/plural-messages.spec.ts, new spec that fails on master, rejects a count ternary in a catalog and checks every translated plural parses and has an other arm
  • packages/dashboard/src/i18n/locales/*.po, 28 catalogs re-extracted, 9 messages translated with each language’s own plural categories

The fix, planned in the free diagnosis

  • <Trans> strings replaced with <Plural> and plural(), the pattern already used in delete-stock-locations-dialog.tsx
  • the ‘this collection’ string uses an exact =1 match instead of the one category, because one also covers 21 and 31 in several locales
  • the test-order item count, which had no translation at all, is now a translatable plural with a named placeholder
  • lingui extract re-run so the catalogs carry the real plural forms, then 9 messages translated for all 28 locales
  • plural-messages.spec.ts added to stop a count ternary from reaching a catalog again

How it’s proven, in the sprint

  • src/i18n/plural-messages.spec.ts fails on master and passes on the branch, per the PR description
  • vitest run src/i18n, 60 passed
  • lingui extract is a no-op on the branch, so no message was left untranslated
  • check-types reports no errors in the changed files
  • the maintainer reproduced the bug on master and verified the fix at runtime (see the reviewer line below)

What wasn’t tested, said up front

No screenshots, because the change is text in non-English locales. GitHub’s check-runs API reports no checks on the merged commit, so CI results are not visible from here; the vitest, lingui and check-types runs above are the author’s local output. The maintainer’s Playwright run is on the review, not in this data.

What happened next, after the sprint

It was merged on 2026-10-16 about 12 days after it opened, with 1699 lines added and 648 removed. The reviewer wrote “German dashboard shows ‘2 countries’ on master and ‘2 Länder’ with this fix” (source). Open the pull request.

Send me an issue

Written from the public pull request and issue. Your diagnosis stays private unless you say otherwise.

Next step

Send me your project, or the part your team can’t get to.

Send me your project

My last client result, a reports page cut from 3,800 requests per load to 3. The brief and the repo are enough to start.

How it starts

  1. [1]Send your project
  2. [2]Get a free plan
  3. [3]Approve the first milestone