Use a context manager for temporary locale switches

This commit is contained in:
Raphael Michel
2016-03-15 17:59:32 +01:00
parent 1d8f2034de
commit 1f665e6f48
5 changed files with 119 additions and 115 deletions

View File

@@ -1,5 +1,6 @@
import copy import copy
import json import json
from contextlib import contextmanager
from django import forms from django import forms
from django.conf import settings from django.conf import settings
@@ -75,11 +76,8 @@ class LazyI18nString:
self.lazygettext = lazygettext self.lazygettext = lazygettext
def __getitem__(self, item): def __getitem__(self, item):
lng = translation.get_language() with language(item):
translation.activate(item) return str(ugettext(self.lazygettext))
s = str(ugettext(self.lazygettext))
translation.activate(lng)
return s
def __contains__(self, item): def __contains__(self, item):
return True return True
@@ -334,3 +332,13 @@ class LazyNumber:
def __str__(self): def __str__(self):
return number_format(self.value, decimal_pos=self.decimal_pos) 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)

View File

@@ -22,6 +22,7 @@ from reportlab.platypus import (
Table, TableStyle, Table, TableStyle,
) )
from pretix.base.i18n import language
from pretix.base.models import Invoice, InvoiceAddress, InvoiceLine, Order from pretix.base.models import Invoice, InvoiceAddress, InvoiceLine, Order
from pretix.base.signals import register_payment_providers from pretix.base.signals import register_payment_providers
@@ -47,58 +48,56 @@ def generate_cancellation(invoice: Invoice):
@transaction.atomic @transaction.atomic
def generate_invoice(order: Order): def generate_invoice(order: Order):
locale = order.event.settings.get('invoice_language') locale = order.event.settings.get('invoice_language')
_lng = translation.get_language()
if locale: if locale:
if locale == '__user__': if locale == '__user__':
locale = order.locale locale = order.locale
translation.activate(locale or settings.LANGUAGE_CODE)
i = Invoice(order=order, event=order.event) with language(locale):
i.invoice_from = order.event.settings.get('invoice_address_from') i = Invoice(order=order, event=order.event)
i.additional_text = order.event.settings.get('invoice_additional_text') i.invoice_from = order.event.settings.get('invoice_address_from')
i.additional_text = order.event.settings.get('invoice_additional_text')
try: try:
addr_template = pgettext("invoice", """{i.company} addr_template = pgettext("invoice", """{i.company}
{i.name} {i.name}
{i.street} {i.street}
{i.zipcode} {i.city} {i.zipcode} {i.city}
{i.country}""") {i.country}""")
i.invoice_to = addr_template.format(i=order.invoice_address).strip() i.invoice_to = addr_template.format(i=order.invoice_address).strip()
if order.invoice_address.vat_id: if order.invoice_address.vat_id:
i.invoice_to += "\n" + pgettext("invoice", "VAT-ID: %s") % {i.vat_id} i.invoice_to += "\n" + pgettext("invoice", "VAT-ID: %s") % {i.vat_id}
except InvoiceAddress.DoesNotExist: except InvoiceAddress.DoesNotExist:
i.invoice_to = "" i.invoice_to = ""
i.date = date.today() i.date = date.today()
i.locale = locale i.locale = locale
i.save() i.save()
responses = register_payment_providers.send(order.event) responses = register_payment_providers.send(order.event)
for receiver, response in responses: for receiver, response in responses:
provider = response(order.event) provider = response(order.event)
if provider.identifier == order.payment_provider: if provider.identifier == order.payment_provider:
payment_provider = provider payment_provider = provider
break break
for p in order.positions.all(): for p in order.positions.all():
desc = str(p.item.name) desc = str(p.item.name)
if p.variation: if p.variation:
desc += " - " + str(p.variation.value) desc += " - " + str(p.variation.value)
InvoiceLine.objects.create( InvoiceLine.objects.create(
invoice=i, description=desc, invoice=i, description=desc,
gross_value=p.price, tax_value=p.tax_value, gross_value=p.price, tax_value=p.tax_value,
tax_rate=p.tax_rate tax_rate=p.tax_rate
) )
if order.payment_fee: if order.payment_fee:
InvoiceLine.objects.create( InvoiceLine.objects.create(
invoice=i, description=_('Payment via {method}').format(method=str(payment_provider.verbose_name)), 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, gross_value=order.payment_fee, tax_value=order.payment_fee_tax_value,
tax_rate=order.payment_fee_tax_rate tax_rate=order.payment_fee_tax_rate
) )
translation.activate(_lng) invoice_pdf(i.pk)
invoice_pdf(i.pk)
def _invoice_get_stylesheet(): def _invoice_get_stylesheet():
@@ -316,17 +315,13 @@ def _invoice_generate_german(invoice, f):
def invoice_pdf(invoice: int): def invoice_pdf(invoice: int):
i = Invoice.objects.get(pk=invoice) i = Invoice.objects.get(pk=invoice)
_lng = translation.get_language() with language(i.locale):
translation.activate(i.locale) with tempfile.NamedTemporaryFile(suffix=".pdf") as f:
_invoice_generate_german(i, f)
with tempfile.NamedTemporaryFile(suffix=".pdf") as f: f.seek(0)
_invoice_generate_german(i, f) i.file.save('invoice.pdf', ContentFile(f.read()))
f.seek(0) i.save()
i.file.save('invoice.pdf', ContentFile(f.read())) return i.file.name
i.save()
translation.activate(_lng)
return i.file.name
if settings.HAS_CELERY: if settings.HAS_CELERY:

View File

@@ -7,7 +7,7 @@ from django.utils import translation
from django.utils.translation import ugettext as _ from django.utils.translation import ugettext as _
from typing import Any, Dict from typing import Any, Dict
from pretix.base.i18n import LazyI18nString from pretix.base.i18n import LazyI18nString, language
from pretix.base.models import Event from pretix.base.models import Event
logger = logging.getLogger('pretix.base.mail') 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 the email has been sent, just that it has been queued by the e-mail
backend. backend.
""" """
_lng = translation.get_language() with language(locale):
if locale: if isinstance(template, LazyI18nString):
translation.activate(locale or settings.LANGUAGE_CODE) body = str(template)
if context:
body = body.format_map(TolerantDict(context))
else:
tpl = get_template(template)
body = tpl.render(context)
if isinstance(template, LazyI18nString): sender = event.settings.get('mail_from') if event else settings.MAIL_FROM
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 subject = str(subject)
if event:
prefix = event.settings.get('mail_prefix')
if prefix:
subject = "[%s] %s" % (prefix, subject)
subject = str(subject) body += "\r\n\r\n----\r\n"
if event: body += _(
prefix = event.settings.get('mail_prefix') "You are receiving this e-mail because you placed an order for {event}."
if prefix: ).format(event=event.name)
subject = "[%s] %s" % (prefix, subject) body += "\r\n"
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:
return mail_send([email], subject, body, sender, event.id if event else None) 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: def mail_send(to: str, subject: str, body: str, sender: str, event: int=None) -> bool:

View File

@@ -2,11 +2,12 @@ from datetime import datetime, timedelta
from django.conf import settings from django.conf import settings
from django.db import transaction from django.db import transaction
from django.utils import translation
from django.utils.timezone import now from django.utils.timezone import now
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from typing import List from typing import List
from pretix.base.i18n import LazyDate, LazyNumber from pretix.base.i18n import LazyDate, LazyNumber, language
from pretix.base.models import ( from pretix.base.models import (
CartPosition, Event, EventLock, Order, OrderPosition, Quota, User, 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], def _perform_order(event: str, payment_provider: str, position_ids: List[str],
email: str, locale: str, address: int): email: str, locale: str, address: int):
event = Event.objects.get(id=event) event = Event.objects.get(id=event)
responses = register_payment_providers.send(event) responses = register_payment_providers.send(event)
pprov = None pprov = None
@@ -266,22 +268,24 @@ def _perform_order(event: str, payment_provider: str, position_ids: List[str],
if event.settings.get('invoice_generate'): if event.settings.get('invoice_generate'):
generate_invoice(order) generate_invoice(order)
mail( with language(order.locale):
order.email, _('Your order: %(code)s') % {'code': order.code}, mail(
event.settings.mail_text_order_placed, order.email, _('Your order: %(code)s') % {'code': order.code},
{ event.settings.mail_text_order_placed,
'total': LazyNumber(order.total), {
'currency': event.currency, 'total': LazyNumber(order.total),
'date': LazyDate(order.expires), 'currency': event.currency,
'event': event.name, 'date': LazyDate(order.expires),
'url': build_absolute_uri(event, 'presale:event.order', kwargs={ 'event': event.name,
'order': order.code, 'url': build_absolute_uri(event, 'presale:event.order', kwargs={
'secret': order.secret 'order': order.code,
}), 'secret': order.secret
'paymentinfo': str(pprov.order_pending_mail_render(order)) }),
}, 'paymentinfo': str(pprov.order_pending_mail_render(order))
event, locale=order.locale },
) event, locale=order.locale
)
return order.id return order.id

View File

@@ -7,11 +7,12 @@ from django.core.urlresolvers import reverse
from django.db.models import Q from django.db.models import Q
from django.http import Http404, HttpResponseNotAllowed from django.http import Http404, HttpResponseNotAllowed
from django.shortcuts import redirect, render 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.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 django.views.generic import DetailView, ListView, TemplateView, View
from pretix.base.i18n import language
from pretix.base.models import ( from pretix.base.models import (
CachedFile, CachedTicket, EventLock, Invoice, Item, Order, Quota, CachedFile, CachedTicket, EventLock, Invoice, Item, Order, Quota,
) )
@@ -206,18 +207,20 @@ class OrderResendLink(OrderView):
permission = 'can_change_orders' permission = 'can_change_orders'
def post(self, *args, **kwargs): def post(self, *args, **kwargs):
mail( with language(self.order.locale):
self.order.email, _('Your order: %(code)s') % {'code': self.order.code}, mail(
self.order.event.settings.mail_text_resend_link, self.order.email,
{ _('Your order: %(code)s') % {'code': self.order.code},
'event': self.order.event.name, self.order.event.settings.mail_text_resend_link,
'url': build_absolute_uri(self.order.event, 'presale:event.order', kwargs={ {
'order': self.order.code, 'event': self.order.event.name,
'secret': self.order.secret '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 }),
) },
self.order.event, locale=self.order.locale
)
messages.success(self.request, _('The email has been queued to be sent.')) messages.success(self.request, _('The email has been queued to be sent.'))
self.order.log_action('pretix.base.order.resend', user=self.request.user) self.order.log_action('pretix.base.order.resend', user=self.request.user)
return redirect(self.get_order_url()) return redirect(self.get_order_url())