Found while implementing #8019 (old-address change-email notice). Filed unassigned; triage grades it. Not a defect in that PR — it is the surface that PR landed on.
Measured
EmailService.sendTemplate resolves templates by (name, locale) and honours an explicit input.locale; with none named it resolves DEFAULT_TEMPLATE_LOCALE (en-US) — deliberately, per #7731. Two facts make every other locale row unreachable through the platform's own send path:
- No auth send names a locale. Every
sendTemplate call in packages/plugins/plugin-auth/src/auth-manager.ts (password reset, verification, MCP, and the new change-email notice) omits locale.
- There is no per-recipient locale to name.
packages/platform-objects/src/identity/sys-user.object.ts declares no locale / language field, so nothing on the user row expresses a preference.
Consequence: a zh-CN deployment receives English password-reset, verification and invitation mail. Before #8019 this was invisible because every built-in auth template was en-US-only — packages/plugins/plugin-email/src/templates/auth-templates.ts had exactly one row per template, and in fact no template anywhere in the repo shipped a non-en-US row.
Why it surfaces now
The #8019 ruling scoped its new template to all four supported locales, so auth.email_change_notice ships as four rows (en-US, zh-CN, ja-JP, es-ES). Three of them are correct, seeded, and currently unselectable by the platform itself — they become live the moment a caller or a tenant overlay names a locale. That PR deliberately did not wire a locale resolution, because making one template locale-aware while the other five stay en-US-only manufactures exactly the mixed-language artefact II18nService.setSupportedLocales' docstring describes: a user would get a Chinese "your email is being changed" notice and an English "verify your email" in the same flow.
Two halves, gradeable separately
- Dormant surface (observation-class): three locale rows the platform cannot select today.
- User-visible gap (concrete): outbound auth mail is English-only on a platform that supports four locales and whose UI already switches.
What a fix would need to decide
- Where recipient locale comes from — a
sys_user column, the deployment default (II18nService.getDefaultLocale(), reachable from the plugin layer), or the request's Accept-Language. This is a product decision, not a lookup.
- Whether the other five auth templates get localized in the same change. Localizing the resolution without localizing the templates just moves the mixed-language problem.
Related
#8019 / the change-email notice PR (the four-locale template that exposed this) · #7731 (why a no-locale send resolves en-US rather than an arbitrary row) · #7801 (row locale vs. render-filter locale) · #5419 (the console's mirror of this on the UI side)
Found while implementing #8019 (old-address change-email notice). Filed unassigned; triage grades it. Not a defect in that PR — it is the surface that PR landed on.
Measured
EmailService.sendTemplateresolves templates by(name, locale)and honours an explicitinput.locale; with none named it resolvesDEFAULT_TEMPLATE_LOCALE(en-US) — deliberately, per #7731. Two facts make every other locale row unreachable through the platform's own send path:sendTemplatecall inpackages/plugins/plugin-auth/src/auth-manager.ts(password reset, verification, MCP, and the new change-email notice) omitslocale.packages/platform-objects/src/identity/sys-user.object.tsdeclares nolocale/languagefield, so nothing on the user row expresses a preference.Consequence: a
zh-CNdeployment receives English password-reset, verification and invitation mail. Before #8019 this was invisible because every built-in auth template wasen-US-only —packages/plugins/plugin-email/src/templates/auth-templates.tshad exactly one row per template, and in fact no template anywhere in the repo shipped a non-en-USrow.Why it surfaces now
The #8019 ruling scoped its new template to all four supported locales, so
auth.email_change_noticeships as four rows (en-US,zh-CN,ja-JP,es-ES). Three of them are correct, seeded, and currently unselectable by the platform itself — they become live the moment a caller or a tenant overlay names a locale. That PR deliberately did not wire a locale resolution, because making one template locale-aware while the other five stayen-US-only manufactures exactly the mixed-language artefactII18nService.setSupportedLocales' docstring describes: a user would get a Chinese "your email is being changed" notice and an English "verify your email" in the same flow.Two halves, gradeable separately
What a fix would need to decide
sys_usercolumn, the deployment default (II18nService.getDefaultLocale(), reachable from the plugin layer), or the request'sAccept-Language. This is a product decision, not a lookup.Related
#8019 / the change-email notice PR (the four-locale template that exposed this) · #7731 (why a no-locale send resolves
en-USrather than an arbitrary row) · #7801 (row locale vs. render-filter locale) · #5419 (the console's mirror of this on the UI side)