i18n in emails
parent
027e15475d
commit
2d960c7a5d
|
@ -58,7 +58,7 @@ def send_register_email(user) -> bool:
|
|||
cancel_token = get_token_for_user(user, "cancel_account")
|
||||
context = {"user": user, "cancel_token": cancel_token}
|
||||
mbuilder = MagicMailBuilder(template_mail_cls=InlineCSSTemplateMail)
|
||||
email = mbuilder.registered_user(user.email, context)
|
||||
email = mbuilder.registered_user(user, context)
|
||||
return bool(email.send())
|
||||
|
||||
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
import datetime
|
||||
|
||||
from optparse import make_option
|
||||
|
||||
from django.db.models.loading import get_model
|
||||
from django.core.management.base import BaseCommand
|
||||
from django.utils import timezone
|
||||
|
@ -30,6 +32,11 @@ from taiga.users.models import User
|
|||
|
||||
class Command(BaseCommand):
|
||||
args = '<email>'
|
||||
option_list = BaseCommand.option_list + (
|
||||
make_option('--locale', '-l', default=None, dest='locale',
|
||||
help='Send emails in an specific language.'),
|
||||
)
|
||||
|
||||
help = 'Send an example of all emails'
|
||||
|
||||
def handle(self, *args, **options):
|
||||
|
@ -37,12 +44,13 @@ class Command(BaseCommand):
|
|||
print("Usage: ./manage.py test_emails <email-address>")
|
||||
return
|
||||
|
||||
locale = options.get('locale')
|
||||
test_email = args[0]
|
||||
|
||||
mbuilder = MagicMailBuilder(template_mail_cls=InlineCSSTemplateMail)
|
||||
|
||||
# Register email
|
||||
context = {"user": User.objects.all().order_by("?").first(), "cancel_token": "cancel-token"}
|
||||
context = {"lang": locale, "user": User.objects.all().order_by("?").first(), "cancel_token": "cancel-token"}
|
||||
email = mbuilder.registered_user(test_email, context)
|
||||
email.send()
|
||||
|
||||
|
@ -51,17 +59,18 @@ class Command(BaseCommand):
|
|||
membership.invited_by = User.objects.all().order_by("?").first()
|
||||
membership.invitation_extra_text = "Text example, Text example,\nText example,\n\nText example"
|
||||
|
||||
context = {"membership": membership}
|
||||
context = {"lang": locale, "membership": membership}
|
||||
email = mbuilder.membership_invitation(test_email, context)
|
||||
email.send()
|
||||
|
||||
# Membership notification
|
||||
context = {"membership": Membership.objects.order_by("?").filter(user__isnull=False).first()}
|
||||
context = {"lang": locale, "membership": Membership.objects.order_by("?").filter(user__isnull=False).first()}
|
||||
email = mbuilder.membership_notification(test_email, context)
|
||||
email.send()
|
||||
|
||||
# Feedback
|
||||
context = {
|
||||
"lang": locale,
|
||||
"feedback_entry": {
|
||||
"full_name": "Test full name",
|
||||
"email": "test@email.com",
|
||||
|
@ -76,17 +85,18 @@ class Command(BaseCommand):
|
|||
email.send()
|
||||
|
||||
# Password recovery
|
||||
context = {"user": User.objects.all().order_by("?").first()}
|
||||
context = {"lang": locale, "user": User.objects.all().order_by("?").first()}
|
||||
email = mbuilder.password_recovery(test_email, context)
|
||||
email.send()
|
||||
|
||||
# Change email
|
||||
context = {"user": User.objects.all().order_by("?").first()}
|
||||
context = {"lang": locale, "user": User.objects.all().order_by("?").first()}
|
||||
email = mbuilder.change_email(test_email, context)
|
||||
email.send()
|
||||
|
||||
# Export/Import emails
|
||||
context = {
|
||||
"lang": locale,
|
||||
"user": User.objects.all().order_by("?").first(),
|
||||
"project": Project.objects.all().order_by("?").first(),
|
||||
"error_subject": "Error generating project dump",
|
||||
|
@ -95,6 +105,7 @@ class Command(BaseCommand):
|
|||
email = mbuilder.export_error(test_email, context)
|
||||
email.send()
|
||||
context = {
|
||||
"lang": locale,
|
||||
"user": User.objects.all().order_by("?").first(),
|
||||
"error_subject": "Error importing project dump",
|
||||
"error_message": "Error importing project dump",
|
||||
|
@ -104,6 +115,7 @@ class Command(BaseCommand):
|
|||
|
||||
deletion_date = timezone.now() + datetime.timedelta(seconds=60*60*24)
|
||||
context = {
|
||||
"lang": locale,
|
||||
"url": "http://dummyurl.com",
|
||||
"user": User.objects.all().order_by("?").first(),
|
||||
"project": Project.objects.all().order_by("?").first(),
|
||||
|
@ -113,6 +125,7 @@ class Command(BaseCommand):
|
|||
email.send()
|
||||
|
||||
context = {
|
||||
"lang": locale,
|
||||
"user": User.objects.all().order_by("?").first(),
|
||||
"project": Project.objects.all().order_by("?").first(),
|
||||
}
|
||||
|
@ -139,6 +152,7 @@ class Command(BaseCommand):
|
|||
]
|
||||
|
||||
context = {
|
||||
"lang": locale,
|
||||
"project": Project.objects.all().order_by("?").first(),
|
||||
"changer": User.objects.all().order_by("?").first(),
|
||||
"history_entries": HistoryEntry.objects.all().order_by("?")[0:5],
|
||||
|
|
|
@ -49,7 +49,7 @@ def dump_project(self, user, project):
|
|||
"error_message": "Error generating project dump",
|
||||
"project": project
|
||||
}
|
||||
email = mbuilder.export_error(user.email, ctx)
|
||||
email = mbuilder.export_error(user, ctx)
|
||||
email.send()
|
||||
return
|
||||
|
||||
|
@ -60,7 +60,7 @@ def dump_project(self, user, project):
|
|||
"user": user,
|
||||
"deletion_date": deletion_date
|
||||
}
|
||||
email = mbuilder.dump_project(user.email, ctx)
|
||||
email = mbuilder.dump_project(user, ctx)
|
||||
email.send()
|
||||
|
||||
|
||||
|
@ -81,10 +81,10 @@ def load_project_dump(user, dump):
|
|||
"error_subject": "Error loading project dump",
|
||||
"error_message": "Error loading project dump",
|
||||
}
|
||||
email = mbuilder.import_error(user.email, ctx)
|
||||
email = mbuilder.import_error(user, ctx)
|
||||
email.send()
|
||||
return
|
||||
|
||||
ctx = {"user": user, "project": project}
|
||||
email = mbuilder.load_dump(user.email, ctx)
|
||||
email = mbuilder.load_dump(user, ctx)
|
||||
email.send()
|
||||
|
|
|
@ -269,6 +269,7 @@ def send_sync_notifications(notification_id):
|
|||
|
||||
for user in notification.notify_users.distinct():
|
||||
context["user"] = user
|
||||
context["lang"] = user.lang
|
||||
email.send(user.email, context)
|
||||
|
||||
notification.delete()
|
||||
|
|
|
@ -9,10 +9,11 @@ def send_invitation(invitation):
|
|||
mbuilder = MagicMailBuilder(template_mail_cls=InlineCSSTemplateMail)
|
||||
if invitation.user:
|
||||
template = mbuilder.membership_notification
|
||||
email = template(invitation.user, {"membership": invitation})
|
||||
else:
|
||||
template = mbuilder.membership_invitation
|
||||
email = template(invitation.email, {"membership": invitation})
|
||||
|
||||
email = template(invitation.email, {"membership": invitation})
|
||||
email.send()
|
||||
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ class UserAdmin(DjangoUserAdmin):
|
|||
fieldsets = (
|
||||
(None, {'fields': ('username', 'password')}),
|
||||
(_('Personal info'), {'fields': ('full_name', 'email', 'bio', 'photo')}),
|
||||
(_('Extra info'), {'fields': ('color', 'default_language', 'default_timezone', 'token', 'colorize_tags', 'email_token', 'new_email')}),
|
||||
(_('Extra info'), {'fields': ('color', 'lang', 'timezone', 'token', 'colorize_tags', 'email_token', 'new_email')}),
|
||||
(_('Permissions'), {'fields': ('is_active', 'is_superuser',)}),
|
||||
(_('Important dates'), {'fields': ('last_login', 'date_joined')}),
|
||||
)
|
||||
|
|
|
@ -97,7 +97,7 @@ class UsersViewSet(ModelCrudViewSet):
|
|||
user.save(update_fields=["token"])
|
||||
|
||||
mbuilder = MagicMailBuilder(template_mail_cls=InlineCSSTemplateMail)
|
||||
email = mbuilder.password_recovery(user.email, {"user": user})
|
||||
email = mbuilder.password_recovery(user, {"user": user})
|
||||
email.send()
|
||||
|
||||
return response.Ok({"detail": _("Mail sended successful!"),
|
||||
|
@ -231,7 +231,8 @@ class UsersViewSet(ModelCrudViewSet):
|
|||
request.user.new_email = new_email
|
||||
request.user.save(update_fields=["email_token", "new_email"])
|
||||
mbuilder = MagicMailBuilder(template_mail_cls=InlineCSSTemplateMail)
|
||||
email = mbuilder.change_email(request.user.new_email, {"user": request.user})
|
||||
email = mbuilder.change_email(request.user.new_email, {"user": request.user,
|
||||
"lang": request.user.lang})
|
||||
email.send()
|
||||
|
||||
return ret
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
"username": "admin",
|
||||
"full_name": "",
|
||||
"bio": "",
|
||||
"default_language": "",
|
||||
"lang": "",
|
||||
"color": "",
|
||||
"photo": "",
|
||||
"is_active": true,
|
||||
"colorize_tags": false,
|
||||
"default_timezone": "",
|
||||
"timezone": "",
|
||||
"is_superuser": true,
|
||||
"token": "",
|
||||
"last_login": "2013-04-04T07:36:09.880Z",
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import models, migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('users', '0008_auto_20150213_1701'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameField(
|
||||
model_name='user',
|
||||
old_name='default_language',
|
||||
new_name='lang',
|
||||
),
|
||||
migrations.RenameField(
|
||||
model_name='user',
|
||||
old_name='default_timezone',
|
||||
new_name='timezone',
|
||||
),
|
||||
]
|
|
@ -116,10 +116,10 @@ class User(AbstractBaseUser, PermissionsMixin):
|
|||
max_length=500, null=True, blank=True,
|
||||
verbose_name=_("photo"))
|
||||
date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
|
||||
default_language = models.CharField(max_length=20, null=False, blank=True, default="",
|
||||
verbose_name=_("default language"))
|
||||
default_timezone = models.CharField(max_length=20, null=False, blank=True, default="",
|
||||
verbose_name=_("default timezone"))
|
||||
lang = models.CharField(max_length=20, null=False, blank=True, default="",
|
||||
verbose_name=_("default language"))
|
||||
timezone = models.CharField(max_length=20, null=False, blank=True, default="",
|
||||
verbose_name=_("default timezone"))
|
||||
colorize_tags = models.BooleanField(null=False, blank=True, default=False,
|
||||
verbose_name=_("colorize tags"))
|
||||
token = models.CharField(max_length=200, null=True, blank=True, default=None,
|
||||
|
@ -166,8 +166,8 @@ class User(AbstractBaseUser, PermissionsMixin):
|
|||
self.full_name = "Deleted user"
|
||||
self.color = ""
|
||||
self.bio = ""
|
||||
self.default_language = ""
|
||||
self.default_timezone = ""
|
||||
self.lang = ""
|
||||
self.timezone = ""
|
||||
self.colorize_tags = True
|
||||
self.token = None
|
||||
self.set_unusable_password()
|
||||
|
|
|
@ -43,8 +43,8 @@ class UserSerializer(ModelSerializer):
|
|||
# IMPORTANT: Maintain the UserAdminSerializer Meta up to date
|
||||
# with this info (including there the email)
|
||||
fields = ("id", "username", "full_name", "full_name_display",
|
||||
"color", "bio", "default_language",
|
||||
"default_timezone", "is_active", "photo", "big_photo")
|
||||
"color", "bio", "lang", "timezone", "is_active",
|
||||
"photo", "big_photo")
|
||||
read_only_fields = ("id",)
|
||||
|
||||
def validate_username(self, attrs, source):
|
||||
|
@ -81,8 +81,8 @@ class UserAdminSerializer(UserSerializer):
|
|||
# IMPORTANT: Maintain the UserSerializer Meta up to date
|
||||
# with this info (including here the email)
|
||||
fields = ("id", "username", "full_name", "full_name_display", "email",
|
||||
"color", "bio", "default_language",
|
||||
"default_timezone", "is_active", "photo", "big_photo")
|
||||
"color", "bio", "lang", "timezone", "is_active", "photo",
|
||||
"big_photo")
|
||||
read_only_fields = ("id", "email")
|
||||
|
||||
|
||||
|
|
|
@ -80,7 +80,7 @@ def test_api_create_bulk_members_with_extra_text(client, outbox):
|
|||
|
||||
|
||||
def test_api_resend_invitation(client, outbox):
|
||||
invitation = f.create_invitation()
|
||||
invitation = f.create_invitation(user=None)
|
||||
f.MembershipFactory(project=invitation.project, user=invitation.project.owner, is_owner=True)
|
||||
url = reverse("memberships-resend-invitation", kwargs={"pk": invitation.pk})
|
||||
|
||||
|
|
Loading…
Reference in New Issue