You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(automation): flow `notify` nodes can reference an email template for localized delivery — `template` + `templateData` on `NotifyNodeConfig`, resolved by `(name, recipient locale)` at delivery time (#9205)
8
+
9
+
Ruled 「立项,走 emailTemplates 路线」: instead of widening the `flows`
10
+
translation surface (whose guidance excludes notification text, #7646), a
11
+
`notify` node now bridges to the existing localized email-template subsystem.
12
+
13
+
-**Spec** — `NotifyConfigSchema` gains `template` (a `sys_email_template`
14
+
name, read raw like `topic`/`channels`) and `templateData` (render context
15
+
for the template's `{{var}}` holes; values interpolate `{token}` templates
16
+
per run) as the localizable alternative to inline `title`/`message`. Inline
17
+
strings stay fully valid and byte-identical for existing flows — they are
18
+
the non-localizable path, and the describes now say so. A node carrying BOTH
19
+
paths, or `templateData` without `template`, or NEITHER path, is refused
20
+
loudly with the fix in the message (the `objectNavTargetExclusivity`
21
+
posture: unrepresentable over silent precedence).
22
+
-**service-automation** — the notify executor forwards the template
23
+
reference and its interpolated render context in the emit payload (the
24
+
outbox snapshots it onto each delivery row), and no longer demands an
25
+
inline title when a template is referenced.
26
+
-**service-messaging** — the email channel routes a template-carrying
27
+
delivery through `IEmailService.sendTemplate({ template, locale, data })`,
28
+
resolving the recipient locale per delivery: `payload.locale` if the
29
+
producer set one, else the deployment default
30
+
(`II18nService.getDefaultLocale()`, the #8195 ruled source), else
Copy file name to clipboardExpand all lines: content/docs/references/automation/io-node-config.mdx
+4-2Lines changed: 4 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -96,8 +96,10 @@ const result = HttpConfigSchema.parse(data);
96
96
| Property | Type | Required | Description |
97
97
| :--- | :--- | :--- | :--- |
98
98
|**recipients**|`string \| string[]`| ✅ | Recipient user id(s) / audience selector(s); `{token}` templates resolve per run |
99
-
|**title**|`string`| ✅ | Notification title |
100
-
|**message**|`string`| optional | Notification body |
99
+
|**title**|`string`| optional | Notification title, sent to every recipient verbatim (not localizable — use `template` for per-locale content). Either this or `template` is required; the two are mutually exclusive. |
100
+
|**message**|`string`| optional | Notification body, sent verbatim like `title` (not localizable). Only valid with inline `title`, never with `template`. |
101
+
|**template**|`string`| optional | Email template name (`sys_email_template.name`, e.g. `crm.large_deal_won`) — the localizable content path: the delivery path resolves `(name, recipient locale)` at delivery time and renders subject/body per recipient. Mutually exclusive with inline `title`/`message`, which are the non-localizable path. Read raw — no `{token}` interpolation. |
102
+
|**templateData**|`Record<string, any>`| optional | Render context for the referenced template's `{{var}}` placeholders; values interpolate `{token}` templates per run. Only valid together with `template`. |
101
103
|**channels**|`string \| string[]`| optional | Channels to fan out to (default: inbox) |
description: 'Notification title, sent verbatim (not localizable — use template for per-locale content). Either this or template is required; mutually exclusive with template.',
174
+
},
175
+
message: {
176
+
type: 'string',
177
+
description: 'Notification body, sent verbatim (not localizable). Only valid with inline title, never with template.',
// Mirrors `NotifyConfigSchema.template`/`templateData`; the
181
+
// mutual exclusion with title/message lives in the Zod
182
+
// contract's superRefine (executed at parse time), matching
183
+
// how requiredness is owned there rather than by the form.
184
+
template: {
185
+
type: 'string',
186
+
description: 'Email template name (sys_email_template.name) — resolved by (name, recipient locale) at delivery time and rendered per recipient. Mutually exclusive with inline title/message.',
187
+
},
188
+
templateData: {
189
+
type: 'object',
190
+
description: 'Render context for the referenced template\'s {{var}} placeholders; values interpolate {token} templates per run. Only valid together with template.',
191
+
},
173
192
channels: {
174
193
type: 'array',items: {type: 'string'},
175
194
description: 'Channels to fan out to (default: inbox)',
@@ -228,6 +247,14 @@ export function registerNotifyNode(engine: AutomationEngine, ctx: PluginContext)
228
247
// useless `[object Object]` (#3450). Serialize it readably instead.
0 commit comments