Context
After #143, all client-facing error messages are static constants in ErrorMessages.cs nested classes (e.g. ErrorMessages.Admin.RoleNotFound). No interpolated runtime values leak to clients. This was an intentional design to make i18n extraction mechanical when the need arises.
Problem
The current const string approach only supports a single language. If the template is deployed in a multi-locale context, error messages need to be translatable.
Considerations
Several approaches exist — the issue is to evaluate and pick one when needed:
| Approach |
Pros |
Cons |
.resx resource files |
Built-in .NET support, compile-time safety, satellite assemblies |
Verbose XML, merge conflicts, no hot-reload |
IStringLocalizer with JSON provider |
Simpler file format, hot-reload possible |
Loses compile-time key safety without a source generator |
DB-backed via IStringLocalizer |
Runtime editable, no redeployment |
Adds DB dependency for error messages, caching complexity |
Current state (good foundation)
- All messages are
const string in ErrorMessages.cs — each is a natural translation key
- Nested class structure (
Admin, Roles, User, Auth, ...) maps to resource file organization
- Zero interpolated strings in
Result.Failure() calls — no format string complications
- Password validation errors are intentionally kept as Identity passthroughs (English-only from ASP.NET Identity unless Identity itself is localized)
Scope
Not in scope
- Frontend i18n (already handled by the existing
$lib/i18n setup)
- Localizing audit log messages or server-side log messages (these stay English for operational tooling)
Context
After #143, all client-facing error messages are static constants in
ErrorMessages.csnested classes (e.g.ErrorMessages.Admin.RoleNotFound). No interpolated runtime values leak to clients. This was an intentional design to make i18n extraction mechanical when the need arises.Problem
The current
const stringapproach only supports a single language. If the template is deployed in a multi-locale context, error messages need to be translatable.Considerations
Several approaches exist — the issue is to evaluate and pick one when needed:
.resxresource filesIStringLocalizerwith JSON providerIStringLocalizerCurrent state (good foundation)
const stringinErrorMessages.cs— each is a natural translation keyAdmin,Roles,User,Auth, ...) maps to resource file organizationResult.Failure()calls — no format string complicationsScope
const stringlookups with localizable lookups (keep the same call-site ergonomics)IdentityErrorDescriberoverride)AGENTS.mderror messages section with the new patternNot in scope
$lib/i18nsetup)