@contractspec/module.notifications 2.3.0 → 2.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/browser/channels/index.js +187 -1
  2. package/dist/browser/contracts/index.js +12 -0
  3. package/dist/browser/entities/index.js +12 -0
  4. package/dist/browser/i18n/catalogs/en.js +64 -0
  5. package/dist/browser/i18n/catalogs/es.js +64 -0
  6. package/dist/browser/i18n/catalogs/fr.js +64 -0
  7. package/dist/browser/i18n/catalogs/index.js +165 -0
  8. package/dist/browser/i18n/index.js +225 -0
  9. package/dist/browser/i18n/keys.js +33 -0
  10. package/dist/browser/i18n/locale.js +25 -0
  11. package/dist/browser/i18n/messages.js +186 -0
  12. package/dist/browser/index.js +279 -3
  13. package/dist/browser/notifications.capability.js +12 -0
  14. package/dist/browser/notifications.feature.js +12 -0
  15. package/dist/browser/templates/index.js +104 -2
  16. package/dist/channels/index.d.ts +4 -0
  17. package/dist/channels/index.js +187 -1
  18. package/dist/contracts/index.js +12 -0
  19. package/dist/entities/index.js +12 -0
  20. package/dist/i18n/catalogs/en.d.ts +6 -0
  21. package/dist/i18n/catalogs/en.js +65 -0
  22. package/dist/i18n/catalogs/es.d.ts +6 -0
  23. package/dist/i18n/catalogs/es.js +65 -0
  24. package/dist/i18n/catalogs/fr.d.ts +6 -0
  25. package/dist/i18n/catalogs/fr.js +65 -0
  26. package/dist/i18n/catalogs/index.d.ts +8 -0
  27. package/dist/i18n/catalogs/index.js +166 -0
  28. package/dist/i18n/i18n.test.d.ts +1 -0
  29. package/dist/i18n/index.d.ts +14 -0
  30. package/dist/i18n/index.js +226 -0
  31. package/dist/i18n/keys.d.ts +29 -0
  32. package/dist/i18n/keys.js +34 -0
  33. package/dist/i18n/locale.d.ts +8 -0
  34. package/dist/i18n/locale.js +26 -0
  35. package/dist/i18n/messages.d.ts +14 -0
  36. package/dist/i18n/messages.js +187 -0
  37. package/dist/index.js +279 -3
  38. package/dist/node/channels/index.js +187 -1
  39. package/dist/node/contracts/index.js +12 -0
  40. package/dist/node/entities/index.js +12 -0
  41. package/dist/node/i18n/catalogs/en.js +64 -0
  42. package/dist/node/i18n/catalogs/es.js +64 -0
  43. package/dist/node/i18n/catalogs/fr.js +64 -0
  44. package/dist/node/i18n/catalogs/index.js +165 -0
  45. package/dist/node/i18n/index.js +225 -0
  46. package/dist/node/i18n/keys.js +33 -0
  47. package/dist/node/i18n/locale.js +25 -0
  48. package/dist/node/i18n/messages.js +186 -0
  49. package/dist/node/index.js +279 -3
  50. package/dist/node/notifications.capability.js +12 -0
  51. package/dist/node/notifications.feature.js +12 -0
  52. package/dist/node/templates/index.js +104 -2
  53. package/dist/notifications.capability.js +12 -0
  54. package/dist/notifications.feature.js +12 -0
  55. package/dist/templates/index.d.ts +17 -7
  56. package/dist/templates/index.js +104 -2
  57. package/package.json +147 -6
@@ -1,3 +1,183 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __export = (target, all) => {
3
+ for (var name in all)
4
+ __defProp(target, name, {
5
+ get: all[name],
6
+ enumerable: true,
7
+ configurable: true,
8
+ set: (newValue) => all[name] = () => newValue
9
+ });
10
+ };
11
+ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
12
+
13
+ // src/i18n/catalogs/en.ts
14
+ import { defineTranslation } from "@contractspec/lib.contracts-spec/translations";
15
+ var enMessages;
16
+ var init_en = __esm(() => {
17
+ enMessages = defineTranslation({
18
+ meta: {
19
+ key: "notifications.messages",
20
+ version: "1.0.0",
21
+ domain: "notifications",
22
+ description: "Template and channel strings for the notifications module",
23
+ owners: ["platform"],
24
+ stability: "experimental"
25
+ },
26
+ locale: "en",
27
+ fallback: "en",
28
+ messages: {
29
+ "template.welcome.name": {
30
+ value: "Welcome",
31
+ description: "Welcome template display name"
32
+ },
33
+ "template.welcome.description": {
34
+ value: "Sent when a user signs up.",
35
+ description: "Welcome template description"
36
+ },
37
+ "template.orgInvite.name": {
38
+ value: "Organization Invitation",
39
+ description: "Org invite template display name"
40
+ },
41
+ "template.orgInvite.description": {
42
+ value: "Sent when a user is invited to an organization.",
43
+ description: "Org invite template description"
44
+ },
45
+ "template.mention.name": {
46
+ value: "Mention",
47
+ description: "Mention template display name"
48
+ },
49
+ "template.mention.description": {
50
+ value: "Sent when a user is mentioned.",
51
+ description: "Mention template description"
52
+ },
53
+ "channel.webhook.noUrl": {
54
+ value: "No webhook URL configured",
55
+ description: "Error when webhook channel has no URL"
56
+ }
57
+ }
58
+ });
59
+ });
60
+
61
+ // src/i18n/catalogs/fr.ts
62
+ import { defineTranslation as defineTranslation2 } from "@contractspec/lib.contracts-spec/translations";
63
+ var frMessages;
64
+ var init_fr = __esm(() => {
65
+ frMessages = defineTranslation2({
66
+ meta: {
67
+ key: "notifications.messages",
68
+ version: "1.0.0",
69
+ domain: "notifications",
70
+ description: "Template and channel strings (French)",
71
+ owners: ["platform"],
72
+ stability: "experimental"
73
+ },
74
+ locale: "fr",
75
+ fallback: "en",
76
+ messages: {
77
+ "template.welcome.name": {
78
+ value: "Bienvenue",
79
+ description: "Welcome template display name"
80
+ },
81
+ "template.welcome.description": {
82
+ value: "Envoyé lorsqu'un utilisateur s'inscrit.",
83
+ description: "Welcome template description"
84
+ },
85
+ "template.orgInvite.name": {
86
+ value: "Invitation à l'organisation",
87
+ description: "Org invite template display name"
88
+ },
89
+ "template.orgInvite.description": {
90
+ value: "Envoyé lorsqu'un utilisateur est invité à une organisation.",
91
+ description: "Org invite template description"
92
+ },
93
+ "template.mention.name": {
94
+ value: "Mention",
95
+ description: "Mention template display name"
96
+ },
97
+ "template.mention.description": {
98
+ value: "Envoyé lorsqu'un utilisateur est mentionné.",
99
+ description: "Mention template description"
100
+ },
101
+ "channel.webhook.noUrl": {
102
+ value: "Aucune URL de webhook configurée",
103
+ description: "Error when webhook channel has no URL"
104
+ }
105
+ }
106
+ });
107
+ });
108
+
109
+ // src/i18n/catalogs/es.ts
110
+ import { defineTranslation as defineTranslation3 } from "@contractspec/lib.contracts-spec/translations";
111
+ var esMessages;
112
+ var init_es = __esm(() => {
113
+ esMessages = defineTranslation3({
114
+ meta: {
115
+ key: "notifications.messages",
116
+ version: "1.0.0",
117
+ domain: "notifications",
118
+ description: "Template and channel strings (Spanish)",
119
+ owners: ["platform"],
120
+ stability: "experimental"
121
+ },
122
+ locale: "es",
123
+ fallback: "en",
124
+ messages: {
125
+ "template.welcome.name": {
126
+ value: "Bienvenida",
127
+ description: "Welcome template display name"
128
+ },
129
+ "template.welcome.description": {
130
+ value: "Enviado cuando un usuario se registra.",
131
+ description: "Welcome template description"
132
+ },
133
+ "template.orgInvite.name": {
134
+ value: "Invitación a la organización",
135
+ description: "Org invite template display name"
136
+ },
137
+ "template.orgInvite.description": {
138
+ value: "Enviado cuando un usuario es invitado a una organización.",
139
+ description: "Org invite template description"
140
+ },
141
+ "template.mention.name": {
142
+ value: "Mención",
143
+ description: "Mention template display name"
144
+ },
145
+ "template.mention.description": {
146
+ value: "Enviado cuando un usuario es mencionado.",
147
+ description: "Mention template description"
148
+ },
149
+ "channel.webhook.noUrl": {
150
+ value: "No se ha configurado una URL de webhook",
151
+ description: "Error when webhook channel has no URL"
152
+ }
153
+ }
154
+ });
155
+ });
156
+
157
+ // src/i18n/messages.ts
158
+ var exports_messages = {};
159
+ __export(exports_messages, {
160
+ resetI18nRegistry: () => resetI18nRegistry,
161
+ getDefaultI18n: () => getDefaultI18n,
162
+ createNotificationsI18n: () => createNotificationsI18n
163
+ });
164
+ import {
165
+ createI18nFactory
166
+ } from "@contractspec/lib.contracts-spec/translations";
167
+ var factory, createNotificationsI18n, getDefaultI18n, resetI18nRegistry;
168
+ var init_messages = __esm(() => {
169
+ init_en();
170
+ init_fr();
171
+ init_es();
172
+ factory = createI18nFactory({
173
+ specKey: "notifications.messages",
174
+ catalogs: [enMessages, frMessages, esMessages]
175
+ });
176
+ createNotificationsI18n = factory.create;
177
+ getDefaultI18n = factory.getDefault;
178
+ resetI18nRegistry = factory.resetRegistry;
179
+ });
180
+
1
181
  // src/channels/index.ts
2
182
  class InAppChannel {
3
183
  channelId = "IN_APP";
@@ -46,11 +226,17 @@ class PushChannel {
46
226
 
47
227
  class WebhookChannel {
48
228
  channelId = "WEBHOOK";
229
+ locale;
230
+ constructor(options) {
231
+ this.locale = options?.locale;
232
+ }
49
233
  async send(notification) {
50
234
  if (!notification.webhook?.url) {
235
+ const { createNotificationsI18n: createNotificationsI18n2 } = await Promise.resolve().then(() => (init_messages(), exports_messages));
236
+ const i18n = createNotificationsI18n2(this.locale);
51
237
  return {
52
238
  success: false,
53
- responseMessage: "No webhook URL configured"
239
+ responseMessage: i18n.t("channel.webhook.noUrl")
54
240
  };
55
241
  }
56
242
  try {
@@ -665,8 +851,8 @@ function renderTemplate(content, variables) {
665
851
  return String(value);
666
852
  });
667
853
  }
668
- function renderNotificationTemplate(template, channel, variables) {
669
- const channelContent = template.channels[channel];
854
+ function renderNotificationTemplate(template, channel, variables, locale) {
855
+ const channelContent = (locale && template.localeChannels?.[locale]?.[channel]) ?? template.channels[channel];
670
856
  if (!channelContent) {
671
857
  return null;
672
858
  }
@@ -734,6 +920,38 @@ var WelcomeTemplate = defineTemplate({
734
920
  body: "Thanks for joining. Click to complete your profile.",
735
921
  actionUrl: "{{actionUrl}}"
736
922
  }
923
+ },
924
+ localeChannels: {
925
+ fr: {
926
+ email: {
927
+ subject: "Bienvenue sur {{appName}}, {{name}} !",
928
+ body: `
929
+ <h1>Bienvenue, {{name}} !</h1>
930
+ <p>Merci d’avoir rejoint {{appName}}. Nous sommes ravis de vous compter parmi nous.</p>
931
+ <p><a href="{{actionUrl}}">Commencer maintenant</a></p>
932
+ `
933
+ },
934
+ inApp: {
935
+ title: "Bienvenue sur {{appName}} !",
936
+ body: "Merci de nous avoir rejoint. Cliquez pour compléter votre profil.",
937
+ actionUrl: "{{actionUrl}}"
938
+ }
939
+ },
940
+ es: {
941
+ email: {
942
+ subject: "¡Bienvenido a {{appName}}, {{name}}!",
943
+ body: `
944
+ <h1>¡Bienvenido, {{name}}!</h1>
945
+ <p>Gracias por unirte a {{appName}}. Estamos encantados de tenerte.</p>
946
+ <p><a href="{{actionUrl}}">Comenzar ahora</a></p>
947
+ `
948
+ },
949
+ inApp: {
950
+ title: "¡Bienvenido a {{appName}}!",
951
+ body: "Gracias por unirte. Haz clic para completar tu perfil.",
952
+ actionUrl: "{{actionUrl}}"
953
+ }
954
+ }
737
955
  }
738
956
  });
739
957
  var OrgInviteTemplate = defineTemplate({
@@ -763,6 +981,40 @@ var OrgInviteTemplate = defineTemplate({
763
981
  actionUrl: "{{actionUrl}}",
764
982
  actionText: "Accept"
765
983
  }
984
+ },
985
+ localeChannels: {
986
+ fr: {
987
+ email: {
988
+ subject: "{{inviterName}} vous invite à rejoindre {{orgName}}",
989
+ body: `
990
+ <h1>Vous êtes invité !</h1>
991
+ <p>{{inviterName}} vous a invité à rejoindre <strong>{{orgName}}</strong> en tant que {{role}}.</p>
992
+ <p><a href="{{actionUrl}}">Accepter l’invitation</a></p>
993
+ `
994
+ },
995
+ inApp: {
996
+ title: "Invitation à {{orgName}}",
997
+ body: "{{inviterName}} vous a invité à rejoindre en tant que {{role}}.",
998
+ actionUrl: "{{actionUrl}}",
999
+ actionText: "Accepter"
1000
+ }
1001
+ },
1002
+ es: {
1003
+ email: {
1004
+ subject: "{{inviterName}} te invitó a unirte a {{orgName}}",
1005
+ body: `
1006
+ <h1>¡Has sido invitado!</h1>
1007
+ <p>{{inviterName}} te ha invitado a unirte a <strong>{{orgName}}</strong> como {{role}}.</p>
1008
+ <p><a href="{{actionUrl}}">Aceptar invitación</a></p>
1009
+ `
1010
+ },
1011
+ inApp: {
1012
+ title: "Invitación a {{orgName}}",
1013
+ body: "{{inviterName}} te invitó a unirte como {{role}}.",
1014
+ actionUrl: "{{actionUrl}}",
1015
+ actionText: "Aceptar"
1016
+ }
1017
+ }
766
1018
  }
767
1019
  });
768
1020
  var MentionTemplate = defineTemplate({
@@ -787,6 +1039,30 @@ var MentionTemplate = defineTemplate({
787
1039
  title: "{{mentionerName}} mentioned you",
788
1040
  body: "{{preview}}"
789
1041
  }
1042
+ },
1043
+ localeChannels: {
1044
+ fr: {
1045
+ inApp: {
1046
+ title: "{{mentionerName}} vous a mentionné",
1047
+ body: "Dans {{context}} : « {{preview}} »",
1048
+ actionUrl: "{{actionUrl}}"
1049
+ },
1050
+ push: {
1051
+ title: "{{mentionerName}} vous a mentionné",
1052
+ body: "{{preview}}"
1053
+ }
1054
+ },
1055
+ es: {
1056
+ inApp: {
1057
+ title: "{{mentionerName}} te mencionó",
1058
+ body: 'En {{context}}: "{{preview}}"',
1059
+ actionUrl: "{{actionUrl}}"
1060
+ },
1061
+ push: {
1062
+ title: "{{mentionerName}} te mencionó",
1063
+ body: "{{preview}}"
1064
+ }
1065
+ }
790
1066
  }
791
1067
  });
792
1068
 
@@ -1,3 +1,15 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __export = (target, all) => {
3
+ for (var name in all)
4
+ __defProp(target, name, {
5
+ get: all[name],
6
+ enumerable: true,
7
+ configurable: true,
8
+ set: (newValue) => all[name] = () => newValue
9
+ });
10
+ };
11
+ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
12
+
1
13
  // src/notifications.capability.ts
2
14
  import {
3
15
  defineCapability,
@@ -1,3 +1,15 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __export = (target, all) => {
3
+ for (var name in all)
4
+ __defProp(target, name, {
5
+ get: all[name],
6
+ enumerable: true,
7
+ configurable: true,
8
+ set: (newValue) => all[name] = () => newValue
9
+ });
10
+ };
11
+ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
12
+
1
13
  // src/notifications.feature.ts
2
14
  import { defineFeature } from "@contractspec/lib.contracts-spec";
3
15
  var NotificationsFeature = defineFeature({
@@ -1,3 +1,15 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __export = (target, all) => {
3
+ for (var name in all)
4
+ __defProp(target, name, {
5
+ get: all[name],
6
+ enumerable: true,
7
+ configurable: true,
8
+ set: (newValue) => all[name] = () => newValue
9
+ });
10
+ };
11
+ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
12
+
1
13
  // src/templates/index.ts
2
14
  function defineTemplate(def) {
3
15
  return def;
@@ -11,8 +23,8 @@ function renderTemplate(content, variables) {
11
23
  return String(value);
12
24
  });
13
25
  }
14
- function renderNotificationTemplate(template, channel, variables) {
15
- const channelContent = template.channels[channel];
26
+ function renderNotificationTemplate(template, channel, variables, locale) {
27
+ const channelContent = (locale && template.localeChannels?.[locale]?.[channel]) ?? template.channels[channel];
16
28
  if (!channelContent) {
17
29
  return null;
18
30
  }
@@ -80,6 +92,38 @@ var WelcomeTemplate = defineTemplate({
80
92
  body: "Thanks for joining. Click to complete your profile.",
81
93
  actionUrl: "{{actionUrl}}"
82
94
  }
95
+ },
96
+ localeChannels: {
97
+ fr: {
98
+ email: {
99
+ subject: "Bienvenue sur {{appName}}, {{name}} !",
100
+ body: `
101
+ <h1>Bienvenue, {{name}} !</h1>
102
+ <p>Merci d’avoir rejoint {{appName}}. Nous sommes ravis de vous compter parmi nous.</p>
103
+ <p><a href="{{actionUrl}}">Commencer maintenant</a></p>
104
+ `
105
+ },
106
+ inApp: {
107
+ title: "Bienvenue sur {{appName}} !",
108
+ body: "Merci de nous avoir rejoint. Cliquez pour compléter votre profil.",
109
+ actionUrl: "{{actionUrl}}"
110
+ }
111
+ },
112
+ es: {
113
+ email: {
114
+ subject: "¡Bienvenido a {{appName}}, {{name}}!",
115
+ body: `
116
+ <h1>¡Bienvenido, {{name}}!</h1>
117
+ <p>Gracias por unirte a {{appName}}. Estamos encantados de tenerte.</p>
118
+ <p><a href="{{actionUrl}}">Comenzar ahora</a></p>
119
+ `
120
+ },
121
+ inApp: {
122
+ title: "¡Bienvenido a {{appName}}!",
123
+ body: "Gracias por unirte. Haz clic para completar tu perfil.",
124
+ actionUrl: "{{actionUrl}}"
125
+ }
126
+ }
83
127
  }
84
128
  });
85
129
  var OrgInviteTemplate = defineTemplate({
@@ -109,6 +153,40 @@ var OrgInviteTemplate = defineTemplate({
109
153
  actionUrl: "{{actionUrl}}",
110
154
  actionText: "Accept"
111
155
  }
156
+ },
157
+ localeChannels: {
158
+ fr: {
159
+ email: {
160
+ subject: "{{inviterName}} vous invite à rejoindre {{orgName}}",
161
+ body: `
162
+ <h1>Vous êtes invité !</h1>
163
+ <p>{{inviterName}} vous a invité à rejoindre <strong>{{orgName}}</strong> en tant que {{role}}.</p>
164
+ <p><a href="{{actionUrl}}">Accepter l’invitation</a></p>
165
+ `
166
+ },
167
+ inApp: {
168
+ title: "Invitation à {{orgName}}",
169
+ body: "{{inviterName}} vous a invité à rejoindre en tant que {{role}}.",
170
+ actionUrl: "{{actionUrl}}",
171
+ actionText: "Accepter"
172
+ }
173
+ },
174
+ es: {
175
+ email: {
176
+ subject: "{{inviterName}} te invitó a unirte a {{orgName}}",
177
+ body: `
178
+ <h1>¡Has sido invitado!</h1>
179
+ <p>{{inviterName}} te ha invitado a unirte a <strong>{{orgName}}</strong> como {{role}}.</p>
180
+ <p><a href="{{actionUrl}}">Aceptar invitación</a></p>
181
+ `
182
+ },
183
+ inApp: {
184
+ title: "Invitación a {{orgName}}",
185
+ body: "{{inviterName}} te invitó a unirte como {{role}}.",
186
+ actionUrl: "{{actionUrl}}",
187
+ actionText: "Aceptar"
188
+ }
189
+ }
112
190
  }
113
191
  });
114
192
  var MentionTemplate = defineTemplate({
@@ -133,6 +211,30 @@ var MentionTemplate = defineTemplate({
133
211
  title: "{{mentionerName}} mentioned you",
134
212
  body: "{{preview}}"
135
213
  }
214
+ },
215
+ localeChannels: {
216
+ fr: {
217
+ inApp: {
218
+ title: "{{mentionerName}} vous a mentionné",
219
+ body: "Dans {{context}} : « {{preview}} »",
220
+ actionUrl: "{{actionUrl}}"
221
+ },
222
+ push: {
223
+ title: "{{mentionerName}} vous a mentionné",
224
+ body: "{{preview}}"
225
+ }
226
+ },
227
+ es: {
228
+ inApp: {
229
+ title: "{{mentionerName}} te mencionó",
230
+ body: 'En {{context}}: "{{preview}}"',
231
+ actionUrl: "{{actionUrl}}"
232
+ },
233
+ push: {
234
+ title: "{{mentionerName}} te mencionó",
235
+ body: "{{preview}}"
236
+ }
237
+ }
136
238
  }
137
239
  });
138
240
  export {
@@ -1,4 +1,16 @@
1
1
  // @bun
2
+ var __defProp = Object.defineProperty;
3
+ var __export = (target, all) => {
4
+ for (var name in all)
5
+ __defProp(target, name, {
6
+ get: all[name],
7
+ enumerable: true,
8
+ configurable: true,
9
+ set: (newValue) => all[name] = () => newValue
10
+ });
11
+ };
12
+ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
13
+
2
14
  // src/notifications.capability.ts
3
15
  import {
4
16
  defineCapability,
@@ -1,4 +1,16 @@
1
1
  // @bun
2
+ var __defProp = Object.defineProperty;
3
+ var __export = (target, all) => {
4
+ for (var name in all)
5
+ __defProp(target, name, {
6
+ get: all[name],
7
+ enumerable: true,
8
+ configurable: true,
9
+ set: (newValue) => all[name] = () => newValue
10
+ });
11
+ };
12
+ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
13
+
2
14
  // src/notifications.feature.ts
3
15
  import { defineFeature } from "@contractspec/lib.contracts-spec";
4
16
  var NotificationsFeature = defineFeature({
@@ -18,6 +18,13 @@ export interface ChannelTemplateContent {
18
18
  actionUrl?: string;
19
19
  actionText?: string;
20
20
  }
21
+ /** Channel content map for a template. */
22
+ export interface ChannelContentMap {
23
+ email?: ChannelTemplateContent;
24
+ inApp?: ChannelTemplateContent;
25
+ push?: ChannelTemplateContent;
26
+ webhook?: ChannelTemplateContent;
27
+ }
21
28
  /**
22
29
  * Notification template definition.
23
30
  */
@@ -28,12 +35,12 @@ export interface NotificationTemplateDefinition {
28
35
  category?: string;
29
36
  variables?: TemplateVariable[];
30
37
  defaultChannels?: string[];
31
- channels: {
32
- email?: ChannelTemplateContent;
33
- inApp?: ChannelTemplateContent;
34
- push?: ChannelTemplateContent;
35
- webhook?: ChannelTemplateContent;
36
- };
38
+ channels: ChannelContentMap;
39
+ /**
40
+ * Per-locale channel content overrides.
41
+ * Falls back to `channels` for unlisted locales.
42
+ */
43
+ localeChannels?: Record<string, Partial<ChannelContentMap>>;
37
44
  }
38
45
  /**
39
46
  * Rendered notification content.
@@ -58,8 +65,11 @@ export declare function defineTemplate(def: NotificationTemplateDefinition): Not
58
65
  export declare function renderTemplate(content: string, variables: Record<string, unknown>): string;
59
66
  /**
60
67
  * Render a notification template for a specific channel.
68
+ *
69
+ * When `locale` is provided, the renderer first looks for channel content
70
+ * under `localeChannels[locale]`, falling back to the default `channels`.
61
71
  */
62
- export declare function renderNotificationTemplate(template: NotificationTemplateDefinition, channel: keyof NotificationTemplateDefinition['channels'], variables: Record<string, unknown>): RenderedNotification | null;
72
+ export declare function renderNotificationTemplate(template: NotificationTemplateDefinition, channel: keyof ChannelContentMap, variables: Record<string, unknown>, locale?: string): RenderedNotification | null;
63
73
  /**
64
74
  * Template registry for managing templates.
65
75
  */