Skip to content

Commit 84d4f54

Browse files
codedsunSuneet Srivastavaiamareebjamal
authored
feat: Email made translatable (#7416)
Co-authored-by: Suneet Srivastava <[email protected]> Co-authored-by: iamareebjamal <[email protected]>
1 parent f0cf6a2 commit 84d4f54

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+1111
-61715
lines changed

Diff for: .gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,4 @@ celerybeat-schedule.*
6161
.coverage
6262
.pytype
6363
.tool-versions
64+
*.mo

Diff for: Dockerfile

+1
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ RUN fc-cache -f
2929

3030
WORKDIR /data/app
3131
ADD . .
32+
RUN ["sh", "scripts/l10n.sh", "generate"]
3233

3334
EXPOSE 8080
3435
ENTRYPOINT ["sh", "scripts/container_start.sh"]

Diff for: app/api/auth.py

+31-17
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from functools import wraps
77

88
import requests
9-
from flask import Blueprint, jsonify, make_response, request, send_file
9+
from flask import Blueprint, jsonify, make_response, render_template, request, send_file
1010
from flask_jwt_extended import (
1111
create_access_token,
1212
create_refresh_token,
@@ -30,8 +30,9 @@
3030
)
3131
from app.api.helpers.files import make_frontend_url
3232
from app.api.helpers.jwt import jwt_authenticate
33-
from app.api.helpers.mail import send_email_confirmation, send_email_with_action
33+
from app.api.helpers.mail import send_email, send_email_confirmation
3434
from app.api.helpers.notification import send_notification_with_action
35+
from app.api.helpers.system_mails import MAILS
3536
from app.api.helpers.third_party_auth import (
3637
FbOAuth,
3738
GoogleOAuth,
@@ -342,25 +343,33 @@ def reset_password_post():
342343
else:
343344
link = make_frontend_url('/reset-password', {'token': user.reset_password})
344345
if user.was_registered_with_order:
345-
send_email_with_action(
346-
user,
347-
PASSWORD_RESET_AND_VERIFY,
348-
app_name=get_settings()['app_name'],
349-
link=link,
346+
send_email(
347+
to=user,
348+
action=PASSWORD_RESET_AND_VERIFY,
349+
subject=MAILS[PASSWORD_RESET_AND_VERIFY]['subject'].format(
350+
app_name=get_settings()['app_name']
351+
),
352+
html=render_template('email/password_reset_and_verify.html', link=link),
350353
)
354+
351355
else:
352-
send_email_with_action(
353-
user,
354-
PASSWORD_RESET,
355-
app_name=get_settings()['app_name'],
356-
link=link,
357-
token=user.reset_password,
356+
send_email(
357+
to=user,
358+
action=PASSWORD_RESET,
359+
subject=MAILS[PASSWORD_RESET]['subject'].format(
360+
app_name=get_settings()['app_name']
361+
),
362+
html=render_template(
363+
'email/password_reset.html',
364+
link=link,
365+
settings=get_settings(),
366+
token=user.reset_password,
367+
),
358368
)
359369

360370
return make_response(
361371
jsonify(
362-
message="If your email was registered with us, you'll get an \
363-
email with reset link shortly",
372+
message="If your email was registered with us, you'll get an email with reset link shortly",
364373
email=email,
365374
),
366375
200,
@@ -413,8 +422,13 @@ def change_password():
413422
)
414423
user.password = new_password
415424
save_to_db(user)
416-
send_email_with_action(
417-
user, PASSWORD_CHANGE, app_name=get_settings()['app_name']
425+
send_email(
426+
to=user,
427+
action=PASSWORD_CHANGE,
428+
subject=MAILS[PASSWORD_CHANGE]['subject'].format(
429+
app_name=get_settings()['app_name']
430+
),
431+
html=render_template('email/password_change.html'),
418432
)
419433
send_notification_with_action(
420434
user, PASSWORD_CHANGE_NOTIF, app_name=get_settings()['app_name']

Diff for: app/api/helpers/system_mails.py

-20
Original file line numberDiff line numberDiff line change
@@ -163,15 +163,6 @@
163163
USER_REGISTER: {
164164
'recipient': 'User',
165165
'subject': 'Welcome to {app_name}. Please verify your account',
166-
'message': (
167-
"Hello,"
168-
"<br/><br/>Your account has been created on {app_name}. Congratulations!"
169-
"<br/><br/>Your login is: {email}"
170-
"<br/><br/>Please visit the following link to verify your email: {link}"
171-
"<br/><br/>Thank You,"
172-
"<br/><br/>{app_name} Team"
173-
"<br/>{frontend_url}"
174-
),
175166
},
176167
USER_REGISTER_WITH_PASSWORD: {
177168
'recipient': 'User',
@@ -200,25 +191,14 @@
200191
PASSWORD_RESET: {
201192
'recipient': 'User',
202193
'subject': '{app_name}: Password Reset',
203-
'message': (
204-
"Please use the following link to reset your password.<br> <a href='{link}' target='_blank'>{link}</a>"
205-
+ " Or paste this token in your {app_name} App: {token} "
206-
),
207194
},
208195
PASSWORD_RESET_AND_VERIFY: {
209196
'recipient': 'User',
210197
'subject': '{app_name}: Reset your password and verify your account',
211-
'message': (
212-
"Please use the following link to reset your password and verify your account."
213-
+ "<br> <a href='{link}' target='_blank'>{link}</a>"
214-
),
215198
},
216199
PASSWORD_CHANGE: {
217200
'recipient': 'User',
218201
'subject': '{app_name}: Password Change',
219-
'message': (
220-
"Your password has been successfully changed. Please login with your new password."
221-
),
222202
},
223203
EVENT_ROLE: {
224204
'recipient': 'User',

Diff for: app/api/users.py

+13-9
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import base64
22
import logging
33

4-
from flask import Blueprint, abort, jsonify, make_response, request
4+
from flask import Blueprint, abort, jsonify, make_response, render_template, request
55
from flask_jwt_extended import current_user, verify_fresh_jwt_in_request
66
from flask_rest_jsonapi import ResourceDetail, ResourceList, ResourceRelationship
77
from sqlalchemy import or_
@@ -11,9 +11,10 @@
1111
from app.api.helpers.db import get_count, safe_query_kwargs
1212
from app.api.helpers.errors import ConflictError, ForbiddenError, UnprocessableEntityError
1313
from app.api.helpers.files import make_frontend_url
14-
from app.api.helpers.mail import send_email_change_user_email, send_email_with_action
14+
from app.api.helpers.mail import send_email, send_email_change_user_email
1515
from app.api.helpers.permission_manager import has_access
1616
from app.api.helpers.permissions import is_user_itself
17+
from app.api.helpers.system_mails import MAILS
1718
from app.api.helpers.user import (
1819
modify_email_for_user_to_be_deleted,
1920
modify_email_for_user_to_be_restored,
@@ -93,13 +94,16 @@ def after_create_object(self, user, data, view_kwargs):
9394
)
9495
link = make_frontend_url('/verify', {'token': hash})
9596
settings = get_settings()
96-
send_email_with_action(
97-
user,
98-
USER_REGISTER,
99-
app_name=settings['app_name'],
100-
email=user.email,
101-
link=link,
102-
frontend_url=settings['frontend_url'],
97+
send_email(
98+
to=user,
99+
action=USER_REGISTER,
100+
subject=MAILS[USER_REGISTER]['subject'].format(app_name=settings['app_name']),
101+
html=render_template(
102+
'email/user_register.html',
103+
email=user.email,
104+
link=link,
105+
settings=get_settings(),
106+
),
103107
)
104108
# TODO Handle in a celery task
105109
# if data.get('original_image_url'):

Diff for: app/instance.py

+15-1
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@
88
import sqlalchemy as sa
99
import stripe
1010
from celery.signals import after_task_publish
11+
from flask_babel import Babel
1112
from envparse import env
12-
from flask import Flask, json, make_response
13+
from flask import Flask, json, make_response, request
1314
from flask_cors import CORS
1415
from flask_jwt_extended import JWTManager
1516
from flask_login import current_user
@@ -226,6 +227,19 @@ def create_app():
226227
current_app = create_app()
227228
init_filters(app)
228229

230+
# Babel
231+
babel = Babel(current_app)
232+
233+
234+
@babel.localeselector
235+
def get_locale():
236+
# Try to guess the language from the user accept
237+
# header the browser transmits. We support de/fr/en in this
238+
# example. The best match wins.
239+
# pytype: disable=mro-error
240+
return request.accept_languages.best_match(current_app.config['ACCEPTED_LANGUAGES'])
241+
# pytype: enable=mro-error
242+
229243

230244
# http://stackoverflow.com/questions/26724623/
231245
@app.before_request

Diff for: app/templates/email/password_change.html

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
{{ _('Your password has been successfully changed.') }}
2+
<br/>{{ _('Please login with your new password.') }}

Diff for: app/templates/email/password_reset.html

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{{ _('Please use the following link to reset your password.') }}
2+
<br/>{{ link }}
3+
<br/>{{ _('Or paste this token in your') }} {{ settings.app_name }} App: {{ token }}

Diff for: app/templates/email/password_reset_and_verify.html

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
{{ _('Please use the following link to reset your password and verify your account.') }}
2+
<br> {{ link }}

Diff for: app/templates/email/ticket_purchased.html

+14-14
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
1-
Hello,
2-
<br/><br/>Thank you for your ticket order for {{ order.event.name }}.
3-
<br/><br/>This is your order confirmation. You can download your tickets at: {{ order_view_url }}
4-
<br/><br/>Order Summary:
5-
<br/>Order: {{ order.invoice_number }}
6-
<br/>Name: {{ order.user.full_name }}
1+
{{ _('Hello') }},
2+
<br/><br/>{{ _('Thank you for your ticket order for') }} {{ order.event.name }}.
3+
<br/><br/>{{ _('This is your order confirmation. You can download your tickets at') }} : {{ order_view_url }}
4+
<br/><br/>{{ _('Order Summary') }}:
5+
<br/>{{ _('Order') }}: {{ order.invoice_number }}
6+
<br/>{{ _('Name') }}: {{ order.user.full_name }}
77
<br/>
8-
{% for _, attendee in attendees | groupby('ticket_id') %}
9-
<br/>Ticket: {{ attendee.0.ticket.name }}
10-
<br/>Quantity: {{ attendee | length }}
8+
{% for i, attendee in attendees | groupby('ticket_id') %}
9+
<br/>{{ _('Ticket') }}: {{ attendee.0.ticket.name }}
10+
<br/>{{ _('Quantity') }}: {{ attendee | length }}
1111
<br/>
1212
{% endfor %}
13-
<br/>About this event:
14-
<br/>Date: {{ order.event.starts_at_tz | datetime }} - {{ order.event.ends_at_tz | datetime }}
13+
<br/>{{ _('About this event') }} :
14+
<br/>{{ _('Date') }}: {{ order.event.starts_at_tz | datetime }} - {{ order.event.ends_at_tz | datetime }}
1515
<br/>{{ order.event.normalized_location }}
16-
<br/><br/>Best regards,
17-
<br/>{{ settings.app_name }} Team
16+
<br/><br/>{{ _('Best regards') }},
17+
<br/>{{ settings.app_name }} {{ _('Team') }}
1818
<br/>--
19-
<br/>Login to manage your orders at {{ settings.frontend_url }}
19+
<br/>{{ _('Login to manage your orders at') }} {{ settings.frontend_url }}

Diff for: app/templates/email/ticket_purchased_attendee.html

+12-12
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
1-
Hello,
2-
<br/><br/>This is a confirmation mail of your tickets for the event {{ order.event.name }}. You can download your tickets at: {{ order_view_url }}
3-
<br/><br/>Ticket Summary:
4-
<br/>Name: {{ attendees.0.user.full_name }}
1+
{{ _('Hello') }},
2+
<br/><br/>{{ _('This is a confirmation mail of your tickets for the event') }} {{ order.event.name }}. {{ _('You can download your tickets at') }}: {{ order_view_url }}
3+
<br/><br/>{{ _('Ticket Summary') }}:
4+
<br/>{{ _('Name') }}: {{ attendees.0.user.full_name }}
55
<br/>
6-
{% for _, attendee in attendees | groupby('ticket_id') %}
7-
<br/>Ticket: {{ attendee.0.ticket.name }}
8-
<br/>Quantity: {{ attendee | length }}
6+
{% for i, attendee in attendees | groupby('ticket_id') %}
7+
<br/>{{ _('Ticket') }}: {{ attendee.0.ticket.name }}
8+
<br/>{{ _('Quantity') }}: {{ attendee | length }}
99
<br/>
1010
{% endfor %}
11-
<br/>About this event:
12-
<br/>Date: {{ order.event.starts_at_tz | datetime }} - {{ order.event.ends_at_tz | datetime }}
11+
<br/>{{ _('About this event') }}:
12+
<br/>{{ _('Date') }}: {{ order.event.starts_at_tz | datetime }} - {{ order.event.ends_at_tz | datetime }}
1313
<br/>{{ order.event.normalized_location }}
14-
<br/><br/>Best regards,
15-
<br/>{{ settings.app_name }} Team
14+
<br/><br/>{{ _('Best regards') }},
15+
<br/>{{ settings.app_name }} {{ _('Team') }}
1616
<br/>--
17-
<br/>Login to manage your orders at {{ settings.frontend_url }}
17+
<br/>{{ _('Login to manage your orders at') }} {{ settings.frontend_url }}

Diff for: app/templates/email/user_register.html

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{{ _('Hello') }},
2+
<br/><br/>{{ _('Your account has been created on') }} {{ settings.app_name }}. {{ _('Congratulations!') }}
3+
<br/><br/>{{ _('Your login is')}}: {{ email }}
4+
<br/><br/>{{ _('Please visit the following link to verify your email:') }} {{ link }}
5+
<br/><br/>{{ _('Thank You') }},
6+
<br/><br/>{{ settings.app_name }} {{ _('Team') }}
7+
<br/>{{ settings.frontend_url }}

Diff for: app/translations/bn/LC_MESSAGES/messages.mo

-45.6 KB
Binary file not shown.

0 commit comments

Comments
 (0)