Skip to content

Commit 95f75bc

Browse files
authored
[ST-1553] apps/notifications: Fix email template rendering (#3033)
1 parent 4e03641 commit 95f75bc

File tree

27 files changed

+957
-880
lines changed

27 files changed

+957
-880
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ This project (not yet) adheres to [Semantic Versioning](https://semver.org/spec/
1616
### Fixed
1717

1818
- Fix duplicate notifications bug
19-
- Fix translation of ProjectCompleted email subject
19+
- Fix email variable interpolation
2020

2121
### Fixed
2222

apps/notifications/services.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,26 @@ def render(self, template_name, context):
4444
site_name=(
4545
context.get("site", "").name if context.get("site") else ""
4646
),
47-
project_name=context.get("project"),
47+
event_name=context.get("event_name"),
48+
project_name=context.get("project_name"),
49+
project_type=context.get("project_type"),
50+
article=context.get("article", ""),
51+
content_type_display=context.get("content_type_display", ""),
52+
commenter_name=context.get("commenter_name", ""),
53+
post_name=context.get("post_name", ""),
54+
)
55+
if "headline" in context:
56+
context["headline"] = context["headline"].format(
57+
project_name=context.get(
58+
"project_name", context.get("project_name", "")
59+
),
60+
project_type=context.get("project_type", ""),
61+
organisation_name=context.get("organisation_name", ""),
62+
article=context.get("article", ""),
63+
article_lower=context.get("article_lower", ""),
64+
content_type=context.get("content_type", ""),
65+
content_type_display=context.get("content_type_display", ""),
66+
creator_name=context.get("creator_name", ""),
4867
)
4968
if "greeting" in context:
5069
context["greeting"] = context["greeting"].format(

apps/notifications/strategies/comment_strategies.py

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,7 @@ def create_notification_data(self, comment) -> dict:
3030

3131
email_context = {
3232
"subject": _("A moderator highlighted your comment"),
33-
"headline": _("Project {project_name}").format(
34-
project_name=comment.project.name
35-
),
33+
"headline": _("Project {project_name}"),
3634
"cta_url": cta_url,
3735
"cta_label": cta_label,
3836
"reason": _(
@@ -42,6 +40,7 @@ def create_notification_data(self, comment) -> dict:
4240
"content_template": "a4_candy_notifications/emails/content/moderator_highlighted_comment.en.email",
4341
# Template variables
4442
"project": comment.project.name,
43+
"project_name": comment.project.name,
4544
"project_url": comment.project.get_absolute_url(),
4645
"post_url": post_url,
4746
}
@@ -84,9 +83,7 @@ def create_notification_data(self, comment) -> dict:
8483
post_name = getattr(comment.content_object, "name", _("post"))
8584

8685
email_context = {
87-
"subject": _("{commenter} commented on your post {post}").format(
88-
commenter=comment.creator.username, post=post_name
89-
),
86+
"subject": _("{commenter_name} commented on your post {post_name}"),
9087
"headline": _("New comment on your post"),
9188
"subheadline": comment.project.name,
9289
"cta_url": comment.content_object.get_absolute_url(),
@@ -144,9 +141,7 @@ def create_notification_data(self, comment) -> dict:
144141
parent_comment = self._get_parent_comment(comment)
145142

146143
email_context = {
147-
"subject": _("{commenter} replied to your comment").format(
148-
commenter=comment.creator.username
149-
),
144+
"subject": _("{commenter_name} replied to your comment"),
150145
"headline": _("New reply to your comment"),
151146
"subheadline": comment.project.name,
152147
"cta_url": comment.get_absolute_url(),

apps/notifications/strategies/event_strategies.py

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,7 @@ def get_recipients(self, event) -> list[User]:
1919

2020
def create_notification_data(self, offline_event):
2121
email_context = {
22-
"subject": _("Event added to project {project}").format(
23-
project=offline_event.project.name
24-
),
22+
"subject": _("Event added to project {project_name}"),
2523
"headline": _("Event"),
2624
"subheadline": offline_event.name,
2725
"cta_url": offline_event.get_absolute_url(),
@@ -33,6 +31,7 @@ def create_notification_data(self, offline_event):
3331
"content_template": "a4_candy_notifications/emails/content/event_added.en.email",
3432
# Template variables
3533
"project": offline_event.project.name,
34+
"project_name": offline_event.project.name,
3635
"event": offline_event.name,
3736
"event_date": format_event_date(offline_event.date),
3837
"organisation": offline_event.project.organisation.name,
@@ -67,9 +66,7 @@ def get_recipients(self, event) -> list[User]:
6766

6867
def create_notification_data(self, offline_event):
6968
email_context = {
70-
"subject": _("Event {event} in project {project} cancelled").format(
71-
event=offline_event.name, project=offline_event.project.name
72-
),
69+
"subject": _("Event {event_name} in project {project_name} cancelled"),
7370
"headline": _("Event"),
7471
"subheadline": offline_event.name,
7572
"reason": _(
@@ -79,7 +76,9 @@ def create_notification_data(self, offline_event):
7976
"content_template": "a4_candy_notifications/emails/content/event_deleted.en.email",
8077
# Template variables
8178
"project": offline_event.project.name,
79+
"project_name": offline_event.project.name,
8280
"event": offline_event.name,
81+
"event_name": offline_event.name,
8382
"event_date": format_event_date(offline_event.date),
8483
"organisation": offline_event.project.organisation.name,
8584
}
@@ -112,9 +111,7 @@ def get_recipients(self, event) -> list[User]:
112111

113112
def create_notification_data(self, offline_event):
114113
email_context = {
115-
"subject": _("Event in project {project}").format(
116-
project=offline_event.project.name
117-
),
114+
"subject": _("Event in project {project_name}"),
118115
"headline": _("Event"),
119116
"subheadline": offline_event.name,
120117
"cta_url": offline_event.get_absolute_url(),
@@ -126,6 +123,7 @@ def create_notification_data(self, offline_event):
126123
"content_template": "a4_candy_notifications/emails/content/event_soon.en.email",
127124
# Template variables
128125
"project": offline_event.project.name,
126+
"project_name": offline_event.project.name,
129127
"event": offline_event.name,
130128
"event_date": format_event_date(offline_event.date),
131129
"organisation": offline_event.project.organisation.name,
@@ -158,9 +156,7 @@ def get_recipients(self, event) -> list[User]:
158156

159157
def create_notification_data(self, offline_event):
160158
email_context = {
161-
"subject": _("Event {event} in project {project} updated").format(
162-
event=offline_event.name, project=offline_event.project.name
163-
),
159+
"subject": _("Event {event_name} in project {project_name} updated"),
164160
"headline": _("Event"),
165161
"subheadline": offline_event.name,
166162
"reason": _(
@@ -172,7 +168,9 @@ def create_notification_data(self, offline_event):
172168
"content_template": "a4_candy_notifications/emails/content/event_updated.en.email",
173169
# Template variables
174170
"project": offline_event.project.name,
171+
"project_name": offline_event.project.name,
175172
"event": offline_event.name,
173+
"event_name": offline_event.name,
176174
"event_date": format_event_date(offline_event.date),
177175
"organisation": offline_event.project.organisation.name,
178176
}

apps/notifications/strategies/moderation_strategies.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,7 @@ def create_notification_data(self, feedback) -> dict:
2727
site_name = ""
2828

2929
email_context = {
30-
"subject": _("Feedback for your contribution on {site_name}").format(
31-
site_name=site_name
32-
),
30+
"subject": _("Feedback for your contribution on {site_name}"),
3331
"headline": _("Feedback for your contribution"),
3432
"subheadline": project.name,
3533
"cta_url": user_comment.get_absolute_url(),
@@ -40,6 +38,7 @@ def create_notification_data(self, feedback) -> dict:
4038
"content_template": "a4_candy_notifications/emails/content/moderator_feedback_on_comment.en.email",
4139
# Template variables
4240
"project": project,
41+
"site_name": site_name,
4342
"organisation": project.organisation.name,
4443
"organisation_name": project.organisation.name,
4544
"moderator_feedback": feedback.feedback_text,

apps/notifications/strategies/project_strategies.py

Lines changed: 14 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,7 @@ def create_notification_data(self, project) -> dict:
6767
)
6868

6969
email_context = {
70-
"subject": _("Here we go: {project_name} starts now!").format(
71-
project_name=project.name
72-
),
70+
"subject": _("Here we go: {project_name} starts now!"),
7371
"headline": _("Here we go!"),
7472
"subheadline": project.name,
7573
"cta_url": project.get_absolute_url(),
@@ -101,17 +99,15 @@ def get_recipients(self, project) -> List[User]:
10199

102100
def create_notification_data(self, project) -> dict:
103101
email_context = {
104-
"subject": _("{project_name} has completed.").format(
105-
project_name=project.name
106-
),
102+
"subject": _("{project_name} has completed."),
107103
"subheadline": project.name,
108104
"cta_url": project.get_absolute_url(),
109105
"cta_label": _("View now"),
110106
"reason": _(
111107
"This email was sent to {receiver_email}. You have received the e-mail because you are following the above project."
112108
),
113109
"content_template": "a4_candy_notifications/emails/content/project_ended.en.email",
114-
"project": project.name,
110+
"project_name": project.name,
115111
}
116112

117113
return {
@@ -146,12 +142,8 @@ def create_notification_data(self, invitation) -> dict:
146142
project_type = "semi-public" if is_semipublic else "private"
147143

148144
email_context = {
149-
"subject": _(
150-
"Invitation to the {project_type} project: {project_name}"
151-
).format(project_type=project_type, project_name=project.name),
152-
"headline": _(
153-
'Invitation to the {project_type} project: "{project_name}"'
154-
).format(project_type=project_type, project_name=project.name),
145+
"subject": _("Invitation to the {project_type} project: {project_name}"),
146+
"headline": _('Invitation to the {project_type} project: "{project_name}"'),
155147
"cta_url": f"{invitation.get_absolute_url()}",
156148
"cta_label": _("Accept invitation"),
157149
"reason": _("This email was sent to {receiver_email}."),
@@ -194,19 +186,14 @@ def get_recipients(self, invitation) -> List[User]:
194186
def create_notification_data(self, invitation) -> dict:
195187
project = invitation.project
196188
email_context = {
197-
"subject": _("Moderator invitation for project {project_name}").format(
198-
project_name=project.name
199-
),
189+
"subject": _("Moderator invitation for project {project_name}"),
200190
"headline": _("Moderator Invitation"),
201191
"cta_url": invitation.get_absolute_url(),
202192
"cta_label": _("View Invitation"),
203193
"reason": _("This email was sent to {receiver_email}."),
204194
"content_template": "a4_candy_notifications/emails/content/project_moderation_invitation.en.email",
205195
"project_name": project.name,
206196
}
207-
translated = _(
208-
"You have been invited to be a moderator of project {project_name}. View {invitation}"
209-
)
210197
return {
211198
"notification_type": NotificationType.PROJECT_MODERATION_INVITATION,
212199
"message_template": "You have been invited to be a moderator of project {project_name}. View {invitation}",
@@ -218,7 +205,6 @@ def create_notification_data(self, invitation) -> dict:
218205
"invitation": "invitation",
219206
"invitation_url": invitation.get_absolute_url(),
220207
"project_url": None, # Explicitly no project link
221-
"irrelevant": translated, # translation hack, to remove
222208
},
223209
"email_context": email_context,
224210
}
@@ -233,8 +219,6 @@ def create_notification_data(self, project) -> dict:
233219
"subject": _("New project {project_name} on {site_name}"),
234220
"headline": _(
235221
"The new project {project_name} was created for {organisation_name}"
236-
).format(
237-
project_name=project.name, organisation_name=project.organisation.name
238222
),
239223
"cta_url": project.get_absolute_url(),
240224
"cta_label": _("Show project"),
@@ -270,16 +254,15 @@ def get_recipients(self, project) -> List[User]:
270254
def create_notification_data(self, project) -> dict:
271255
email_context = {
272256
"subject": _("Deletion of project"),
273-
"headline": _("The project {project} was deleted.").format(
274-
project=project.name
275-
),
257+
"headline": _("The project {project_name} was deleted."),
276258
"reason": _(
277259
"This email was sent to {receiver_email}. This email was sent to you because you are an initiator of the organisation '{organisation_name}', in which a project was deleted."
278260
),
279261
# Content template
280262
"content_template": "a4_candy_notifications/emails/content/project_deleted.en.email",
281263
# Template variables
282264
"project": project.name,
265+
"project_name": project.name,
283266
"organisation": project.organisation.name,
284267
"site": project.organisation.site,
285268
}
@@ -318,30 +301,22 @@ def create_notification_data(self, obj) -> dict:
318301
content_type_article = "An"
319302
email_context = {
320303
"subject": _(
321-
"{article} {content_type} was added to the project {project}"
322-
).format(
323-
article=content_type_article,
324-
content_type=content_type_display,
325-
project=obj.project.name,
304+
"{article} {content_type_display} was added to the project {project_name}"
326305
),
327306
"headline": _(
328-
"{creator_name} created {article} {content_type} on the project {project}"
329-
).format(
330-
article=content_type_article.lower(),
331-
creator_name=obj.creator.username,
332-
content_type=content_type_display,
333-
project=obj.project.name,
307+
"{creator_name} created {article_lower} {content_type_display} on the project {project_name}"
334308
),
335309
"cta_url": obj.get_absolute_url(),
336-
"cta_label": _("Check the {content_type}").format(
337-
content_type=content_type_display
338-
),
310+
"cta_label": _("Check the {content_type_display}"),
339311
"reason": _(
340312
"This email was sent to {receiver_email}. This email was sent to you because you are a moderator in the project."
341313
),
342314
# Content template
343315
"content_template": "a4_candy_notifications/emails/content/user_content_created.en.email",
344316
# Template variables
317+
"article": content_type_article,
318+
"article_lower": content_type_article.lower(),
319+
"project_name": obj.project.name,
345320
"project": obj.project.name,
346321
"creator_name": obj.creator.username,
347322
"content_type": content_type.lower(),

apps/users/emails.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,18 @@ class EmailAplus(Email):
2626
def get_languages(self, receiver):
2727
languages = super().get_languages(receiver)
2828
organisation = self.get_organisation()
29-
if User.objects.filter(email=receiver).exists():
30-
languages.insert(0, User.objects.get(email=receiver).language)
29+
30+
# Handle User object
31+
if isinstance(receiver, User):
32+
user_lang = receiver.language
33+
# Handle email string
34+
elif isinstance(receiver, str) and User.objects.filter(email=receiver).exists():
35+
user_lang = User.objects.get(email=receiver).language
36+
else:
37+
user_lang = None
38+
39+
if user_lang:
40+
languages.insert(0, user_lang)
3141
elif organisation is not None:
3242
languages.insert(0, organisation.language)
3343
elif hasattr(settings, "DEFAULT_USER_LANGUAGE_CODE"):

0 commit comments

Comments
 (0)