From 3c46c461c025b3cf381220e89b6d0644cb4aeca8 Mon Sep 17 00:00:00 2001 From: Raphael Michel Date: Mon, 13 Nov 2023 15:48:45 +0100 Subject: [PATCH] Translate question options in backend and PDFs (Z#23134850) (#3693) * Translate question options in backend and PDFs * Extend to invoices --- src/pretix/base/models/orders.py | 17 +++++++++++++++++ src/pretix/base/pdf.py | 2 +- src/pretix/base/services/invoices.py | 4 ++-- .../templates/pretixcontrol/order/index.html | 4 ++-- 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/src/pretix/base/models/orders.py b/src/pretix/base/models/orders.py index 3f5e35d63f..422b55e95b 100644 --- a/src/pretix/base/models/orders.py +++ b/src/pretix/base/models/orders.py @@ -1271,6 +1271,21 @@ class QuestionAnswer(models.Model): return self.file.name.split('.', 1)[-1] def __str__(self): + return self.to_string(use_cached=True) + + def to_string_i18n(self): + return self.to_string(use_cached=False) + + def to_string(self, use_cached=True): + """ + Render this answer as a string. + + :param use_cached: If ``True`` (default), choice and multiple choice questions will show their cached + value, i.e. the value of the selected options at the time of saving and in the language + the answer was saved in. If ``False``, the values will instead be loaded from the + database, yielding current and translated values of the options. However, additional database + queries might be required. + """ if self.question.type == Question.TYPE_BOOLEAN and self.answer == "True": return str(_("Yes")) elif self.question.type == Question.TYPE_BOOLEAN and self.answer == "False": @@ -1305,6 +1320,8 @@ class QuestionAnswer(models.Model): return PhoneNumber.from_string(self.answer).as_international except NumberParseException: return self.answer + elif self.question.type in (Question.TYPE_CHOICE, Question.TYPE_CHOICE_MULTIPLE) and self.answer and not use_cached: + return ", ".join(str(o.answer) for o in self.options.all()) else: return self.answer diff --git a/src/pretix/base/pdf.py b/src/pretix/base/pdf.py index 748dd3d6a4..7224066a1f 100644 --- a/src/pretix/base/pdf.py +++ b/src/pretix/base/pdf.py @@ -567,7 +567,7 @@ def variables_from_questions(sender, *args, **kwargs): if not a: return "" else: - return str(a) + return a.to_string_i18n() d = {} for q in sender.questions.all(): diff --git a/src/pretix/base/services/invoices.py b/src/pretix/base/services/invoices.py index 1039c2e6ba..86b30a7339 100644 --- a/src/pretix/base/services/invoices.py +++ b/src/pretix/base/services/invoices.py @@ -199,7 +199,7 @@ def build_invoice(invoice: Invoice) -> Invoice: positions = list( invoice.order.positions.select_related('addon_to', 'item', 'tax_rule', 'subevent', 'variation').annotate( addon_c=Count('addons') - ).prefetch_related('answers', 'answers__question').order_by('positionid', 'id') + ).prefetch_related('answers', 'answers__options', 'answers__question').order_by('positionid', 'id') ) reverse_charge = False @@ -247,7 +247,7 @@ def build_invoice(invoice: Invoice) -> Invoice: desc += "
{}{} {}".format( answ.question.question, "" if str(answ.question.question).endswith("?") else ":", - str(answ) + answ.to_string_i18n() ) if invoice.event.has_subevents: diff --git a/src/pretix/control/templates/pretixcontrol/order/index.html b/src/pretix/control/templates/pretixcontrol/order/index.html index 02ae8aa870..b6b6d89b00 100644 --- a/src/pretix/control/templates/pretixcontrol/order/index.html +++ b/src/pretix/control/templates/pretixcontrol/order/index.html @@ -589,9 +589,9 @@ {% endif %} {% elif q.type == "M" %} - {{ q.answer|rich_text_snippet }} + {{ q.answer.to_string_i18n|rich_text_snippet }} {% else %} - {{ q.answer|linebreaksbr }} + {{ q.answer.to_string_i18n|linebreaksbr }} {% endif %} {% else %} {% trans "not answered" %}