diff --git a/src/pretix/base/i18n.py b/src/pretix/base/i18n.py index f509204f1..c3a467434 100644 --- a/src/pretix/base/i18n.py +++ b/src/pretix/base/i18n.py @@ -1,5 +1,6 @@ import copy import json +from contextlib import contextmanager from django import forms from django.conf import settings @@ -75,11 +76,8 @@ class LazyI18nString: self.lazygettext = lazygettext def __getitem__(self, item): - lng = translation.get_language() - translation.activate(item) - s = str(ugettext(self.lazygettext)) - translation.activate(lng) - return s + with language(item): + return str(ugettext(self.lazygettext)) def __contains__(self, item): return True @@ -334,3 +332,13 @@ class LazyNumber: def __str__(self): return number_format(self.value, decimal_pos=self.decimal_pos) + + +@contextmanager +def language(lng): + _lng = translation.get_language() + translation.activate(lng or settings.LANGUAGE_CODE) + try: + yield + finally: + translation.activate(_lng) diff --git a/src/pretix/base/services/invoices.py b/src/pretix/base/services/invoices.py index 1aea79495..7afb67add 100644 --- a/src/pretix/base/services/invoices.py +++ b/src/pretix/base/services/invoices.py @@ -22,6 +22,7 @@ from reportlab.platypus import ( Table, TableStyle, ) +from pretix.base.i18n import language from pretix.base.models import Invoice, InvoiceAddress, InvoiceLine, Order from pretix.base.signals import register_payment_providers @@ -47,58 +48,56 @@ def generate_cancellation(invoice: Invoice): @transaction.atomic def generate_invoice(order: Order): locale = order.event.settings.get('invoice_language') - _lng = translation.get_language() if locale: if locale == '__user__': locale = order.locale - translation.activate(locale or settings.LANGUAGE_CODE) - i = Invoice(order=order, event=order.event) - i.invoice_from = order.event.settings.get('invoice_address_from') - i.additional_text = order.event.settings.get('invoice_additional_text') + with language(locale): + i = Invoice(order=order, event=order.event) + i.invoice_from = order.event.settings.get('invoice_address_from') + i.additional_text = order.event.settings.get('invoice_additional_text') - try: - addr_template = pgettext("invoice", """{i.company} -{i.name} -{i.street} -{i.zipcode} {i.city} -{i.country}""") - i.invoice_to = addr_template.format(i=order.invoice_address).strip() - if order.invoice_address.vat_id: - i.invoice_to += "\n" + pgettext("invoice", "VAT-ID: %s") % {i.vat_id} - except InvoiceAddress.DoesNotExist: - i.invoice_to = "" + try: + addr_template = pgettext("invoice", """{i.company} + {i.name} + {i.street} + {i.zipcode} {i.city} + {i.country}""") + i.invoice_to = addr_template.format(i=order.invoice_address).strip() + if order.invoice_address.vat_id: + i.invoice_to += "\n" + pgettext("invoice", "VAT-ID: %s") % {i.vat_id} + except InvoiceAddress.DoesNotExist: + i.invoice_to = "" - i.date = date.today() - i.locale = locale - i.save() + i.date = date.today() + i.locale = locale + i.save() - responses = register_payment_providers.send(order.event) - for receiver, response in responses: - provider = response(order.event) - if provider.identifier == order.payment_provider: - payment_provider = provider - break + responses = register_payment_providers.send(order.event) + for receiver, response in responses: + provider = response(order.event) + if provider.identifier == order.payment_provider: + payment_provider = provider + break - for p in order.positions.all(): - desc = str(p.item.name) - if p.variation: - desc += " - " + str(p.variation.value) - InvoiceLine.objects.create( - invoice=i, description=desc, - gross_value=p.price, tax_value=p.tax_value, - tax_rate=p.tax_rate - ) + for p in order.positions.all(): + desc = str(p.item.name) + if p.variation: + desc += " - " + str(p.variation.value) + InvoiceLine.objects.create( + invoice=i, description=desc, + gross_value=p.price, tax_value=p.tax_value, + tax_rate=p.tax_rate + ) - if order.payment_fee: - InvoiceLine.objects.create( - invoice=i, description=_('Payment via {method}').format(method=str(payment_provider.verbose_name)), - gross_value=order.payment_fee, tax_value=order.payment_fee_tax_value, - tax_rate=order.payment_fee_tax_rate - ) + if order.payment_fee: + InvoiceLine.objects.create( + invoice=i, description=_('Payment via {method}').format(method=str(payment_provider.verbose_name)), + gross_value=order.payment_fee, tax_value=order.payment_fee_tax_value, + tax_rate=order.payment_fee_tax_rate + ) - translation.activate(_lng) - invoice_pdf(i.pk) + invoice_pdf(i.pk) def _invoice_get_stylesheet(): @@ -316,17 +315,13 @@ def _invoice_generate_german(invoice, f): def invoice_pdf(invoice: int): i = Invoice.objects.get(pk=invoice) - _lng = translation.get_language() - translation.activate(i.locale) - - with tempfile.NamedTemporaryFile(suffix=".pdf") as f: - _invoice_generate_german(i, f) - f.seek(0) - i.file.save('invoice.pdf', ContentFile(f.read())) - i.save() - - translation.activate(_lng) - return i.file.name + with language(i.locale): + with tempfile.NamedTemporaryFile(suffix=".pdf") as f: + _invoice_generate_german(i, f) + f.seek(0) + i.file.save('invoice.pdf', ContentFile(f.read())) + i.save() + return i.file.name if settings.HAS_CELERY: diff --git a/src/pretix/base/services/mail.py b/src/pretix/base/services/mail.py index e6a35c52a..ed8bcd26b 100644 --- a/src/pretix/base/services/mail.py +++ b/src/pretix/base/services/mail.py @@ -7,7 +7,7 @@ from django.utils import translation from django.utils.translation import ugettext as _ from typing import Any, Dict -from pretix.base.i18n import LazyI18nString +from pretix.base.i18n import LazyI18nString, language from pretix.base.models import Event logger = logging.getLogger('pretix.base.mail') @@ -39,35 +39,29 @@ def mail(email: str, subject: str, template: str, the email has been sent, just that it has been queued by the e-mail backend. """ - _lng = translation.get_language() - if locale: - translation.activate(locale or settings.LANGUAGE_CODE) + with language(locale): + if isinstance(template, LazyI18nString): + body = str(template) + if context: + body = body.format_map(TolerantDict(context)) + else: + tpl = get_template(template) + body = tpl.render(context) - if isinstance(template, LazyI18nString): - body = str(template) - if context: - body = body.format_map(TolerantDict(context)) - else: - tpl = get_template(template) - body = tpl.render(context) + sender = event.settings.get('mail_from') if event else settings.MAIL_FROM - sender = event.settings.get('mail_from') if event else settings.MAIL_FROM + subject = str(subject) + if event: + prefix = event.settings.get('mail_prefix') + if prefix: + subject = "[%s] %s" % (prefix, subject) - subject = str(subject) - if event: - prefix = event.settings.get('mail_prefix') - if prefix: - subject = "[%s] %s" % (prefix, subject) - - body += "\r\n\r\n----\r\n" - body += _( - "You are receiving this e-mail because you placed an order for {event}." - ).format(event=event.name) - body += "\r\n" - try: + body += "\r\n\r\n----\r\n" + body += _( + "You are receiving this e-mail because you placed an order for {event}." + ).format(event=event.name) + body += "\r\n" return mail_send([email], subject, body, sender, event.id if event else None) - finally: - translation.activate(_lng) def mail_send(to: str, subject: str, body: str, sender: str, event: int=None) -> bool: diff --git a/src/pretix/base/services/orders.py b/src/pretix/base/services/orders.py index 609af75cb..7d0819ccd 100644 --- a/src/pretix/base/services/orders.py +++ b/src/pretix/base/services/orders.py @@ -2,11 +2,12 @@ from datetime import datetime, timedelta from django.conf import settings from django.db import transaction +from django.utils import translation from django.utils.timezone import now from django.utils.translation import ugettext_lazy as _ from typing import List -from pretix.base.i18n import LazyDate, LazyNumber +from pretix.base.i18n import LazyDate, LazyNumber, language from pretix.base.models import ( CartPosition, Event, EventLock, Order, OrderPosition, Quota, User, ) @@ -231,6 +232,7 @@ def _create_order(event: Event, email: str, positions: List[CartPosition], dt: d def _perform_order(event: str, payment_provider: str, position_ids: List[str], email: str, locale: str, address: int): + event = Event.objects.get(id=event) responses = register_payment_providers.send(event) pprov = None @@ -266,22 +268,24 @@ def _perform_order(event: str, payment_provider: str, position_ids: List[str], if event.settings.get('invoice_generate'): generate_invoice(order) - mail( - order.email, _('Your order: %(code)s') % {'code': order.code}, - event.settings.mail_text_order_placed, - { - 'total': LazyNumber(order.total), - 'currency': event.currency, - 'date': LazyDate(order.expires), - 'event': event.name, - 'url': build_absolute_uri(event, 'presale:event.order', kwargs={ - 'order': order.code, - 'secret': order.secret - }), - 'paymentinfo': str(pprov.order_pending_mail_render(order)) - }, - event, locale=order.locale - ) + with language(order.locale): + mail( + order.email, _('Your order: %(code)s') % {'code': order.code}, + event.settings.mail_text_order_placed, + { + 'total': LazyNumber(order.total), + 'currency': event.currency, + 'date': LazyDate(order.expires), + 'event': event.name, + 'url': build_absolute_uri(event, 'presale:event.order', kwargs={ + 'order': order.code, + 'secret': order.secret + }), + 'paymentinfo': str(pprov.order_pending_mail_render(order)) + }, + event, locale=order.locale + ) + return order.id diff --git a/src/pretix/control/views/orders.py b/src/pretix/control/views/orders.py index 9ccc26f9c..5e2e52bae 100644 --- a/src/pretix/control/views/orders.py +++ b/src/pretix/control/views/orders.py @@ -7,11 +7,12 @@ from django.core.urlresolvers import reverse from django.db.models import Q from django.http import Http404, HttpResponseNotAllowed from django.shortcuts import redirect, render -from django.utils.functional import cached_property +from django.utils.functional import cached_property, lazy from django.utils.timezone import now -from django.utils.translation import ugettext_lazy as _ +from django.utils.translation import gettext, ugettext_lazy as _ from django.views.generic import DetailView, ListView, TemplateView, View +from pretix.base.i18n import language from pretix.base.models import ( CachedFile, CachedTicket, EventLock, Invoice, Item, Order, Quota, ) @@ -206,18 +207,20 @@ class OrderResendLink(OrderView): permission = 'can_change_orders' def post(self, *args, **kwargs): - mail( - self.order.email, _('Your order: %(code)s') % {'code': self.order.code}, - self.order.event.settings.mail_text_resend_link, - { - 'event': self.order.event.name, - 'url': build_absolute_uri(self.order.event, 'presale:event.order', kwargs={ - 'order': self.order.code, - 'secret': self.order.secret - }), - }, - self.order.event, locale=self.order.locale - ) + with language(self.order.locale): + mail( + self.order.email, + _('Your order: %(code)s') % {'code': self.order.code}, + self.order.event.settings.mail_text_resend_link, + { + 'event': self.order.event.name, + 'url': build_absolute_uri(self.order.event, 'presale:event.order', kwargs={ + 'order': self.order.code, + 'secret': self.order.secret + }), + }, + self.order.event, locale=self.order.locale + ) messages.success(self.request, _('The email has been queued to be sent.')) self.order.log_action('pretix.base.order.resend', user=self.request.user) return redirect(self.get_order_url())