Convention — backend i18n keys
What it is
The naming scheme for backend resource-string keys in ErrorMessages.resx / ErrorMessages.ar.resx. Error and validation messages follow a hierarchical, per-entity key shape so that delete-block and system-row messages compose predictably and stay in English/Arabic lockstep. Locked in MIQ-132 (decision 42) and carried through MIQ-133.
When to use it
Whenever you add a localized backend message for a lookup-CRUD entity — a referenced-block body, a system-row guard, or a validation message.
The key scheme
For an entity <Entity>:
| Key | Used for |
|---|---|
<Entity>.IsSystem.Body |
The system-row protection message (SystemRowProtectedException<T>). |
<Entity>.Referenced.Header |
First line of a delete-blocked-by-FK message. |
<Entity>.Referenced.Intro |
"This … is referenced by:" lead-in. |
<Entity>.Referenced.Surface.<Table> |
One line per referencing table (e.g. .Surface.Employees), emitted only when its count is non-zero. |
<Entity>.Referenced.Footer |
Closing remediation line ("Reassign these…, then retry."). |
<Entity>.Validation.<Rule> |
A FluentValidation message (e.g. Terminal.Validation.TimeZoneIdInvalid). |
Real keys from ErrorMessages.resx:
Grade.Referenced.Header = "Cannot delete {0}."
Grade.Referenced.Intro = "This grade is referenced by:"
Grade.Referenced.Surface.Employees = "• {0} employees"
Grade.Referenced.Footer = "Reassign these employees to other grades, then retry."
Grade.IsSystem.Body = "This grade is a system row and cannot be modified or deleted."
Terminal.Validation.TimeZoneIdInvalid = "TimeZoneId must be a valid IANA timezone identifier (e.g. Asia/Riyadh)."
The service composes the full "referenced by" body top-to-bottom (Header → Intro → one Surface line per non-zero FK → Footer) via IStringLocalizer<ErrorMessages>. See Exceptions for how the composed body reaches the 409 response.
Gotchas / constraints
- Both locales in lockstep. Every key added to
ErrorMessages.resxmust also exist inErrorMessages.ar.resx. A frontend render test assertsen.json/ar.jsonparity on the FE side; keep the BE resx pair equally aligned. - Compose in the service. Keys are looked up and assembled in the service (where
IStringLocalizeris injected), not in the controller or the exception. - One
Surface.<Table>key per referencing FK — Terminal has 8 surfaces, Grade has 1. Name them by the referencing table. - This is backend product i18n — distinct from the resx-vs-i18next split covered in Internationalisation, and distinct again from the wiki's own Arabic-translation track.
Build status
Available — the scheme is live across the seven lookup entities' resx entries (MIQ-132 decision 42; MIQ-133 decision 42).
Related
- Exceptions — the messages this scheme names.
- Internationalisation — the overall i18n architecture.
- Lookup CRUD template
- Source: MIQ-132 / MIQ-133 reports (
manpoweriq/docs/);Application/Resources/ErrorMessages*.resx.