Skip to content

feat(i18n): generated humanized + pluralized entity-name translations#6132

Open
delchev wants to merge 3 commits into
masterfrom
feat/entity-name-translations
Open

feat(i18n): generated humanized + pluralized entity-name translations#6132
delchev wants to merge 3 commits into
masterfrom
feat/entity-name-translations

Conversation

@delchev

@delchev delchev commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Problem

The sidebar, list titles and detail panels show pluralized humanized entity names ("Sales Invoices"), while forms and captions show the singular ("Sales Invoice") - but the generated catalog carried only one ambiguous t.<dataName> key per entity, holding the RAW identifier (SalesInvoice). The names could not be translated properly: a single key cannot be both "Фактура за продажба" and "Фактури за продажба", and several templates bound the singular key with a plural fallback.

What this adds

Generation time - the translate action now emits both display names per entity into the project catalog (translations/en-US/<model>.json), following the existing key convention:

<tprefix>.t.<dataName>          = humanized singular    ("Sales Invoice")
<tprefix>.t.<dataName>_plural   = humanized pluralized  ("Sales Invoices")

The model's own entityLabel/menuLabel (from EdmIntentGenerator) win; hand-authored .edm models without them get the same derivation via JS ports of IntentNaming.humanize/pluralize (including the UoM irregular overrides). Translators then localize per language, e.g. bg-BG: "salesInvoice": "Фактура за продажба", "salesInvoice_plural": "Фактури за продажба".

Consumption - every plural surface now binds the _plural key:

  • standalone SPA sidebar entries + the breadcrumb nav-key map
  • manage/master list titles, the document line-items title
  • the detail-panel registry tkey (its label is the pluralized menuLabel)

Shared application shell - each generated perspective now contributes tkey: '<project>:<tprefix>.t.<dataName>_plural'; the shell sidebar, dashboard tiles and Settings list translate through it. Since the shell has no project namespace of its own, the shared i18n service gains AppI18nAddNamespaces() - the shell calls it with the namespaces of the aggregated perspectives, catalogs are fetched on demand (i18next.addResourceBundle), and already-rendered labels re-evaluate through a reactive store version bump. In the default language everything keeps rendering from the baked literals with zero extra requests.

Verification

All 17 affected templates rendered through Velocity 2.4.1 with a synthetic model context; every generated JS file passes node --check; generateUtils.js (ESM), i18n.js and appShell.js checked directly; the humanize/pluralize ports unit-tested against IntentNaming's cases (SalesInvoice/Country/Box/Status/UoM).

Regenerate an app to get the enriched catalog; existing catalogs keep working (the new keys simply fall back to the baked English labels until regenerated).

🤖 Generated with Claude Code

delchev and others added 3 commits July 3, 2026 19:56
The sidebar / list titles / detail panels show pluralized humanized entity
names ('Sales Invoices') and the forms singular ones ('Sales Invoice'), but
the generated catalog carried only one ambiguous key per entity holding the
RAW name - so the names could not be translated properly (a single key cannot
be both 'Фактура за продажба' and 'Фактури за продажба').

- generate (translate action): every entity now emits BOTH display names into
  the project catalog (translations/en-US/<model>.json):
    <tprefix>.t.<dataName>         = humanized singular  (entityLabel)
    <tprefix>.t.<dataName>_plural  = humanized pluralized (menuLabel)
  Models without baked labels (hand-authored .edm) get the same derivation
  via JS ports of IntentNaming.humanize/pluralize (incl. the UoM overrides).
- Harmonia templates: every plural surface now binds the _plural key - the
  standalone sidebar entries, the manage/master list titles, the breadcrumb
  nav-key map, the document line-items title, and the detail-panel registry
  tkey (its label is the pluralized menuLabel).
- shared application shell: each generated perspective contributes
  tkey ('<project>:<tprefix>.t.<dataName>_plural'); the shell sidebar,
  dashboard tiles and Settings list translate through it. The shell (which
  has no project namespace of its own) loads the contributing projects'
  catalogs on demand: new AppI18nAddNamespaces() in the shared i18n service
  fetches additional namespaces after init and re-renders already-bound
  labels through a reactive store version bump.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The master view's selected-record title concatenated the raw baked
'${entityLabel} #id' literal - the one singular entity-name surface that
bypassed T(). It now resolves through the same t.<dataName> singular key
as the other captions.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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