mirror of
https://github.com/pretix/pretix.git
synced 2026-06-17 02:21:05 +00:00
Compare commits
134 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| dd3821983f | |||
| 119cc50897 | |||
| 61f9cf13b4 | |||
| f24429a7c5 | |||
| 29ed07ccce | |||
| dd0cd7ab0b | |||
| d7df906995 | |||
| 839f4b4657 | |||
| 74f7e1f61c | |||
| 47919afab0 | |||
| 819daa99f7 | |||
| 8512e79d68 | |||
| 52672ae25b | |||
| ad752dc617 | |||
| 43c6c33bd8 | |||
| 88c9f8c047 | |||
| 2d2663f15f | |||
| ae6014708b | |||
| d1686df07c | |||
| 4d60d7bfbc | |||
| c0b93fedc5 | |||
| 2eaa6c3069 | |||
| db982c9ef4 | |||
| f9f6ee94ae | |||
| 99c257d392 | |||
| e2cb83ce28 | |||
| d7b7d3cc5f | |||
| 721ac8a500 | |||
| 5796cfe03f | |||
| 63f1c4f793 | |||
| 47f409171d | |||
| 27fcdff17f | |||
| a38a96f186 | |||
| 700ea77e39 | |||
| 06104ff483 | |||
| fb5697a27b | |||
| 9a9ad6d6d1 | |||
| a05845790e | |||
| a0830dd033 | |||
| dba2529f6b | |||
| 9c0ea8f179 | |||
| 1f0501a647 | |||
| d2e6446238 | |||
| d519fcfe0d | |||
| c7226303be | |||
| 9406e941bc | |||
| 919e598f8a | |||
| 672692d578 | |||
| 9429dc7e91 | |||
| 5c8dbd99dd | |||
| cfbb8310f0 | |||
| d37d9a861c | |||
| 43a9cf29b2 | |||
| 047ad438a7 | |||
| ec8d921fcf | |||
| 39e6ef4365 | |||
| 4d8b032591 | |||
| e8193e408b | |||
| 6723d8c07c | |||
| c30134f36c | |||
| 0617fc04ec | |||
| e90b54280a | |||
| 39ea2889ba | |||
| 76230bd37b | |||
| 86b8c5e90f | |||
| 7a2027c61b | |||
| 55de5ef45b | |||
| 39e6954828 | |||
| 7849d98672 | |||
| c325164059 | |||
| 8fc19c62dd | |||
| 20feaebbbd | |||
| 4587a9e630 | |||
| 9fe0e6eb67 | |||
| bab7e54f35 | |||
| 352efa40e7 | |||
| 50da7d4261 | |||
| 53cc59d41d | |||
| 9879e99c59 | |||
| dc49d5bcf7 | |||
| d4460045b4 | |||
| cead2898a7 | |||
| 6a594a6166 | |||
| 0e7bb43a5a | |||
| 3a3ae6e66c | |||
| 48aecb80f6 | |||
| d58a6e2503 | |||
| 8c4e0bdb82 | |||
| c40e34af57 | |||
| 1492ec51bf | |||
| 7ca2a0c910 | |||
| 0e41cb53a2 | |||
| 1d579d12c5 | |||
| f3fa323351 | |||
| 67434bbe08 | |||
| 1f38d48ab7 | |||
| 0b99ab74a1 | |||
| 9508e13ea8 | |||
| 7efac71d62 | |||
| 26fdcc2872 | |||
| 0e5e2193ed | |||
| 1e2900ad2a | |||
| 4f521022f5 | |||
| 5ce28ce258 | |||
| e51e765fcd | |||
| bb8301fbac | |||
| 5023081d6a | |||
| f2bf8e01e1 | |||
| 65645a7e93 | |||
| 296b17fb7b | |||
| fdc6de2a3d | |||
| 5c2c9c94c7 | |||
| 277e63cce7 | |||
| b0a031de93 | |||
| 6d770c66d6 | |||
| d73155b69a | |||
| 839deabac3 | |||
| 59c702588a | |||
| e1aaa422c9 | |||
| 27ae5ae018 | |||
| 56c528795c | |||
| 6e70562839 | |||
| f7eff231ff | |||
| 52f78157f3 | |||
| e9a2633b01 | |||
| 40932685fe | |||
| 5e66f21193 | |||
| 48683ce11d | |||
| 8fc719b483 | |||
| c38859478c | |||
| 210115acef | |||
| 4db2384e93 | |||
| 803d0b1570 | |||
| 65fe7b3396 |
@@ -208,20 +208,6 @@ Additionally, when creating a device through the user interface or API, a user c
|
||||
the device. These include an allow list of specific API calls that may be made by the device. pretix ships with security
|
||||
policies for official pretix apps like pretixSCAN and pretixPOS.
|
||||
|
||||
Removing a device
|
||||
-----------------
|
||||
|
||||
If you want implement a way to to deprovision a device in your software, you can call the ``revoke`` endpoint to
|
||||
invalidate your API key. There is no way to reverse this operation.
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
POST /api/v1/device/revoke HTTP/1.1
|
||||
Host: pretix.eu
|
||||
Authorization: Device 1kcsh572fonm3hawalrncam4l1gktr2rzx25a22l8g9hx108o9oi0rztpcvwnfnd
|
||||
|
||||
This can also be done by the user through the web interface.
|
||||
|
||||
Event selection
|
||||
---------------
|
||||
|
||||
|
||||
@@ -60,6 +60,9 @@ The following values for ``action_types`` are valid with pretix core:
|
||||
* ``pretix.event.added``
|
||||
* ``pretix.event.changed``
|
||||
* ``pretix.event.deleted``
|
||||
* ``pretix.giftcards.created``
|
||||
* ``pretix.giftcards.modified``
|
||||
* ``pretix.giftcards.transaction.*``
|
||||
* ``pretix.voucher.added``
|
||||
* ``pretix.voucher.changed``
|
||||
* ``pretix.voucher.deleted``
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
sphinx==9.1.*
|
||||
sphinx-rtd-theme~=3.1.0
|
||||
sphinxcontrib-httpdomain~=1.8.1
|
||||
sphinxcontrib-httpdomain~=2.0.0
|
||||
sphinxcontrib-images~=1.0.1
|
||||
sphinxcontrib-jquery~=4.1
|
||||
sphinxcontrib-spelling~=8.0.2
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
-e ../
|
||||
sphinx==9.1.*
|
||||
sphinx-rtd-theme~=3.1.0
|
||||
sphinxcontrib-httpdomain~=1.8.1
|
||||
sphinxcontrib-httpdomain~=2.0.0
|
||||
sphinxcontrib-images~=1.0.1
|
||||
sphinxcontrib-jquery~=4.1
|
||||
sphinxcontrib-spelling~=8.0.2
|
||||
|
||||
+4
-4
@@ -33,7 +33,7 @@ dependencies = [
|
||||
"celery==5.6.*",
|
||||
"chardet==5.2.*",
|
||||
"cryptography>=44.0.0",
|
||||
"css-inline==0.19.*",
|
||||
"css-inline==0.20.*",
|
||||
"defusedcsv>=1.1.0",
|
||||
"dnspython==2.*",
|
||||
"Django[argon2]==4.2.*,>=4.2.26",
|
||||
@@ -65,7 +65,7 @@ dependencies = [
|
||||
"kombu==5.6.*",
|
||||
"libsass==0.23.*",
|
||||
"lxml",
|
||||
"markdown==3.10.1", # 3.3.5 requires importlib-metadata>=4.4, but django-bootstrap3 requires importlib-metadata<3.
|
||||
"markdown==3.10.2", # 3.3.5 requires importlib-metadata>=4.4, but django-bootstrap3 requires importlib-metadata<3.
|
||||
# We can upgrade markdown again once django-bootstrap3 upgrades or once we drop Python 3.6 and 3.7
|
||||
"mt-940==4.30.*",
|
||||
"oauthlib==3.3.*",
|
||||
@@ -73,7 +73,7 @@ dependencies = [
|
||||
"packaging",
|
||||
"paypalrestsdk==1.13.*",
|
||||
"paypal-checkout-serversdk==1.0.*",
|
||||
"PyJWT==2.10.*",
|
||||
"PyJWT==2.11.*",
|
||||
"phonenumberslite==9.0.*",
|
||||
"Pillow==12.1.*",
|
||||
"pretix-plugin-build",
|
||||
@@ -92,7 +92,7 @@ dependencies = [
|
||||
"redis==7.1.*",
|
||||
"reportlab==4.4.*",
|
||||
"requests==2.32.*",
|
||||
"sentry-sdk==2.50.*",
|
||||
"sentry-sdk==2.52.*",
|
||||
"sepaxml==2.7.*",
|
||||
"stripe==7.9.*",
|
||||
"text-unidecode==1.*",
|
||||
|
||||
@@ -19,4 +19,4 @@
|
||||
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
|
||||
# <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
__version__ = "2026.1.0"
|
||||
__version__ = "2026.2.0.dev0"
|
||||
|
||||
@@ -1743,6 +1743,7 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
|
||||
rounding_mode = self.context["event"].settings.tax_rounding
|
||||
changed = apply_rounding(
|
||||
rounding_mode,
|
||||
ia,
|
||||
self.context["event"].currency,
|
||||
[*pos_map.values(), *fees]
|
||||
)
|
||||
|
||||
@@ -49,7 +49,7 @@ from pretix.base.plugins import (
|
||||
PLUGIN_LEVEL_EVENT, PLUGIN_LEVEL_EVENT_ORGANIZER_HYBRID,
|
||||
PLUGIN_LEVEL_ORGANIZER,
|
||||
)
|
||||
from pretix.base.services.mail import SendMailException, mail
|
||||
from pretix.base.services.mail import mail
|
||||
from pretix.base.settings import validate_organizer_settings
|
||||
from pretix.helpers.urls import build_absolute_uri as build_global_uri
|
||||
from pretix.multidomain.urlreverse import build_absolute_uri
|
||||
@@ -363,24 +363,21 @@ class TeamInviteSerializer(serializers.ModelSerializer):
|
||||
)
|
||||
|
||||
def _send_invite(self, instance):
|
||||
try:
|
||||
mail(
|
||||
instance.email,
|
||||
_('pretix account invitation'),
|
||||
'pretixcontrol/email/invitation.txt',
|
||||
{
|
||||
'user': self,
|
||||
'organizer': self.context['organizer'].name,
|
||||
'team': instance.team.name,
|
||||
'url': build_global_uri('control:auth.invite', kwargs={
|
||||
'token': instance.token
|
||||
})
|
||||
},
|
||||
event=None,
|
||||
locale=get_language_without_region() # TODO: expose?
|
||||
)
|
||||
except SendMailException:
|
||||
pass # Already logged
|
||||
mail(
|
||||
instance.email,
|
||||
_('pretix account invitation'),
|
||||
'pretixcontrol/email/invitation.txt',
|
||||
{
|
||||
'user': self,
|
||||
'organizer': self.context['organizer'].name,
|
||||
'team': instance.team.name,
|
||||
'url': build_global_uri('control:auth.invite', kwargs={
|
||||
'token': instance.token
|
||||
})
|
||||
},
|
||||
event=None,
|
||||
locale=get_language_without_region() # TODO: expose?
|
||||
)
|
||||
|
||||
def create(self, validated_data):
|
||||
if 'email' in validated_data:
|
||||
|
||||
@@ -90,7 +90,6 @@ from pretix.base.services.invoices import (
|
||||
generate_cancellation, generate_invoice, invoice_pdf, invoice_qualified,
|
||||
regenerate_invoice, transmit_invoice,
|
||||
)
|
||||
from pretix.base.services.mail import SendMailException
|
||||
from pretix.base.services.orders import (
|
||||
OrderChangeManager, OrderError, _order_placed_email,
|
||||
_order_placed_email_attendee, approve_order, cancel_order, deny_order,
|
||||
@@ -439,8 +438,6 @@ class EventOrderViewSet(OrderViewSetMixin, viewsets.ModelViewSet):
|
||||
return Response({'detail': str(e)}, status=status.HTTP_400_BAD_REQUEST)
|
||||
except PaymentException as e:
|
||||
return Response({'detail': str(e)}, status=status.HTTP_400_BAD_REQUEST)
|
||||
except SendMailException:
|
||||
pass
|
||||
|
||||
return self.retrieve(request, [], **kwargs)
|
||||
return Response(
|
||||
@@ -634,10 +631,7 @@ class EventOrderViewSet(OrderViewSetMixin, viewsets.ModelViewSet):
|
||||
order = self.get_object()
|
||||
if not order.email:
|
||||
return Response({'detail': 'There is no email address associated with this order.'}, status=status.HTTP_400_BAD_REQUEST)
|
||||
try:
|
||||
order.resend_link(user=self.request.user, auth=self.request.auth)
|
||||
except SendMailException:
|
||||
return Response({'detail': _('There was an error sending the mail. Please try again later.')}, status=status.HTTP_503_SERVICE_UNAVAILABLE)
|
||||
order.resend_link(user=self.request.user, auth=self.request.auth)
|
||||
|
||||
return Response(
|
||||
status=status.HTTP_204_NO_CONTENT
|
||||
@@ -1616,8 +1610,6 @@ class PaymentViewSet(CreateModelMixin, viewsets.ReadOnlyModelViewSet):
|
||||
)
|
||||
except Quota.QuotaExceededException:
|
||||
pass
|
||||
except SendMailException:
|
||||
pass
|
||||
|
||||
serializer = OrderPaymentSerializer(r, context=serializer.context)
|
||||
|
||||
@@ -1655,8 +1647,6 @@ class PaymentViewSet(CreateModelMixin, viewsets.ReadOnlyModelViewSet):
|
||||
return Response({'detail': str(e)}, status=status.HTTP_400_BAD_REQUEST)
|
||||
except PaymentException as e:
|
||||
return Response({'detail': str(e)}, status=status.HTTP_400_BAD_REQUEST)
|
||||
except SendMailException:
|
||||
pass
|
||||
return self.retrieve(request, [], **kwargs)
|
||||
|
||||
@action(detail=True, methods=['POST'])
|
||||
|
||||
@@ -249,12 +249,17 @@ class GiftCardViewSet(viewsets.ModelViewSet):
|
||||
def perform_create(self, serializer):
|
||||
value = serializer.validated_data.pop('value')
|
||||
inst = serializer.save(issuer=self.request.organizer)
|
||||
inst.transactions.create(value=value, acceptor=self.request.organizer)
|
||||
inst.log_action(
|
||||
'pretix.giftcards.transaction.manual',
|
||||
action='pretix.giftcards.created',
|
||||
user=self.request.user,
|
||||
auth=self.request.auth,
|
||||
data=merge_dicts(self.request.data, {'id': inst.pk})
|
||||
)
|
||||
inst.transactions.create(value=value, acceptor=self.request.organizer)
|
||||
inst.log_action(
|
||||
action='pretix.giftcards.transaction.manual',
|
||||
user=self.request.user,
|
||||
auth=self.request.auth,
|
||||
data=merge_dicts(self.request.data, {'id': inst.pk, 'acceptor_id': self.request.organizer.id})
|
||||
)
|
||||
|
||||
@transaction.atomic()
|
||||
@@ -269,7 +274,7 @@ class GiftCardViewSet(viewsets.ModelViewSet):
|
||||
inst = serializer.save(secret=serializer.instance.secret, currency=serializer.instance.currency,
|
||||
testmode=serializer.instance.testmode)
|
||||
inst.log_action(
|
||||
'pretix.giftcards.modified',
|
||||
action='pretix.giftcards.modified',
|
||||
user=self.request.user,
|
||||
auth=self.request.auth,
|
||||
data=self.request.data,
|
||||
@@ -282,10 +287,10 @@ class GiftCardViewSet(viewsets.ModelViewSet):
|
||||
diff = value - old_value
|
||||
inst.transactions.create(value=diff, acceptor=self.request.organizer)
|
||||
inst.log_action(
|
||||
'pretix.giftcards.transaction.manual',
|
||||
action='pretix.giftcards.transaction.manual',
|
||||
user=self.request.user,
|
||||
auth=self.request.auth,
|
||||
data={'value': diff}
|
||||
data={'value': diff, 'acceptor_id': self.request.organizer.id}
|
||||
)
|
||||
|
||||
return inst
|
||||
@@ -309,10 +314,14 @@ class GiftCardViewSet(viewsets.ModelViewSet):
|
||||
}, status=status.HTTP_409_CONFLICT)
|
||||
gc.transactions.create(value=value, text=text, info=info, acceptor=self.request.organizer)
|
||||
gc.log_action(
|
||||
'pretix.giftcards.transaction.manual',
|
||||
action='pretix.giftcards.transaction.manual',
|
||||
user=self.request.user,
|
||||
auth=self.request.auth,
|
||||
data={'value': value, 'text': text}
|
||||
data={
|
||||
'value': value,
|
||||
'text': text,
|
||||
'acceptor_id': self.request.organizer.id
|
||||
}
|
||||
)
|
||||
return Response(GiftCardSerializer(gc, context=self.get_serializer_context()).data, status=status.HTTP_200_OK)
|
||||
|
||||
|
||||
@@ -174,6 +174,35 @@ class ParametrizedEventWebhookEvent(ParametrizedWebhookEvent):
|
||||
}
|
||||
|
||||
|
||||
class ParametrizedGiftcardWebhookEvent(ParametrizedWebhookEvent):
|
||||
def build_payload(self, logentry: LogEntry):
|
||||
giftcard = logentry.content_object
|
||||
if not giftcard:
|
||||
return None
|
||||
|
||||
return {
|
||||
'notification_id': logentry.pk,
|
||||
'issuer_id': logentry.organizer_id,
|
||||
'giftcard': giftcard.pk,
|
||||
'action': logentry.action_type,
|
||||
}
|
||||
|
||||
|
||||
class ParametrizedGiftcardTransactionWebhookEvent(ParametrizedWebhookEvent):
|
||||
def build_payload(self, logentry: LogEntry):
|
||||
giftcard = logentry.content_object
|
||||
if not giftcard:
|
||||
return None
|
||||
|
||||
return {
|
||||
'notification_id': logentry.pk,
|
||||
'issuer_id': logentry.organizer_id,
|
||||
'acceptor_id': logentry.parsed_data.get('acceptor_id'),
|
||||
'giftcard': giftcard.pk,
|
||||
'action': logentry.action_type,
|
||||
}
|
||||
|
||||
|
||||
class ParametrizedVoucherWebhookEvent(ParametrizedWebhookEvent):
|
||||
|
||||
def build_payload(self, logentry: LogEntry):
|
||||
@@ -433,6 +462,18 @@ def register_default_webhook_events(sender, **kwargs):
|
||||
'pretix.customer.anonymized',
|
||||
_('Customer account anonymized'),
|
||||
),
|
||||
ParametrizedGiftcardWebhookEvent(
|
||||
'pretix.giftcards.created',
|
||||
_('Gift card added'),
|
||||
),
|
||||
ParametrizedGiftcardWebhookEvent(
|
||||
'pretix.giftcards.modified',
|
||||
_('Gift card modified'),
|
||||
),
|
||||
ParametrizedGiftcardTransactionWebhookEvent(
|
||||
'pretix.giftcards.transaction.*',
|
||||
_('Gift card used in transcation'),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ from pretix.base.templatetags.rich_text import (
|
||||
DEFAULT_CALLBACKS, EMAIL_RE, URL_RE, abslink_callback,
|
||||
markdown_compile_email, truelink_callback,
|
||||
)
|
||||
from pretix.helpers.format import SafeFormatter, format_map
|
||||
from pretix.helpers.format import FormattedString, SafeFormatter, format_map
|
||||
|
||||
from pretix.base.services.placeholders import ( # noqa
|
||||
get_available_placeholders, PlaceholderContext
|
||||
@@ -141,6 +141,7 @@ class TemplateBasedMailRenderer(BaseHTMLMailRenderer):
|
||||
return markdown_compile_email(plaintext, context=context)
|
||||
|
||||
def render(self, plain_body: str, plain_signature: str, subject: str, order, position, context) -> str:
|
||||
apply_format_map = not isinstance(plain_body, FormattedString)
|
||||
body_md = self.compile_markdown(plain_body, context)
|
||||
if context:
|
||||
linker = bleach.Linker(
|
||||
@@ -149,12 +150,13 @@ class TemplateBasedMailRenderer(BaseHTMLMailRenderer):
|
||||
callbacks=DEFAULT_CALLBACKS + [truelink_callback, abslink_callback],
|
||||
parse_email=True
|
||||
)
|
||||
body_md = format_map(
|
||||
body_md,
|
||||
context=context,
|
||||
mode=SafeFormatter.MODE_RICH_TO_HTML,
|
||||
linkifier=linker
|
||||
)
|
||||
if apply_format_map:
|
||||
body_md = format_map(
|
||||
body_md,
|
||||
context=context,
|
||||
mode=SafeFormatter.MODE_RICH_TO_HTML,
|
||||
linkifier=linker
|
||||
)
|
||||
htmlctx = {
|
||||
'site': settings.PRETIX_INSTANCE_NAME,
|
||||
'site_url': settings.SITE_URL,
|
||||
|
||||
@@ -890,18 +890,18 @@ class BaseQuestionsForm(forms.Form):
|
||||
if not help_text:
|
||||
if q.valid_date_min and q.valid_date_max:
|
||||
help_text = format_lazy(
|
||||
'Please enter a date between {min} and {max}.',
|
||||
_('Please enter a date between {min} and {max}.'),
|
||||
min=date_format(q.valid_date_min, "SHORT_DATE_FORMAT"),
|
||||
max=date_format(q.valid_date_max, "SHORT_DATE_FORMAT"),
|
||||
)
|
||||
elif q.valid_date_min:
|
||||
help_text = format_lazy(
|
||||
'Please enter a date no earlier than {min}.',
|
||||
_('Please enter a date no earlier than {min}.'),
|
||||
min=date_format(q.valid_date_min, "SHORT_DATE_FORMAT"),
|
||||
)
|
||||
elif q.valid_date_max:
|
||||
help_text = format_lazy(
|
||||
'Please enter a date no later than {max}.',
|
||||
_('Please enter a date no later than {max}.'),
|
||||
max=date_format(q.valid_date_max, "SHORT_DATE_FORMAT"),
|
||||
)
|
||||
if initial and initial.answer:
|
||||
@@ -939,18 +939,18 @@ class BaseQuestionsForm(forms.Form):
|
||||
if not help_text:
|
||||
if q.valid_datetime_min and q.valid_datetime_max:
|
||||
help_text = format_lazy(
|
||||
'Please enter a date and time between {min} and {max}.',
|
||||
_('Please enter a date and time between {min} and {max}.'),
|
||||
min=date_format(q.valid_datetime_min, "SHORT_DATETIME_FORMAT"),
|
||||
max=date_format(q.valid_datetime_max, "SHORT_DATETIME_FORMAT"),
|
||||
)
|
||||
elif q.valid_datetime_min:
|
||||
help_text = format_lazy(
|
||||
'Please enter a date and time no earlier than {min}.',
|
||||
_('Please enter a date and time no earlier than {min}.'),
|
||||
min=date_format(q.valid_datetime_min, "SHORT_DATETIME_FORMAT"),
|
||||
)
|
||||
elif q.valid_datetime_max:
|
||||
help_text = format_lazy(
|
||||
'Please enter a date and time no later than {max}.',
|
||||
_('Please enter a date and time no later than {max}.'),
|
||||
max=date_format(q.valid_datetime_max, "SHORT_DATETIME_FORMAT"),
|
||||
)
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ from pretix.base.invoicing.transmission import (
|
||||
transmission_types,
|
||||
)
|
||||
from pretix.base.models import Invoice, InvoiceAddress
|
||||
from pretix.base.services.mail import SendMailException, mail, render_mail
|
||||
from pretix.base.services.mail import mail, render_mail
|
||||
from pretix.helpers.format import format_map
|
||||
|
||||
|
||||
@@ -133,41 +133,37 @@ class EmailTransmissionProvider(TransmissionProvider):
|
||||
template = invoice.order.event.settings.get('mail_text_order_invoice', as_type=LazyI18nString)
|
||||
subject = invoice.order.event.settings.get('mail_subject_order_invoice', as_type=LazyI18nString)
|
||||
|
||||
try:
|
||||
# Do not set to completed because that is done by the email sending task
|
||||
subject = format_map(subject, context)
|
||||
email_content = render_mail(template, context)
|
||||
mail(
|
||||
[recipient],
|
||||
subject,
|
||||
template,
|
||||
context=context,
|
||||
event=invoice.order.event,
|
||||
locale=invoice.order.locale,
|
||||
order=invoice.order,
|
||||
invoices=[invoice],
|
||||
attach_tickets=False,
|
||||
auto_email=True,
|
||||
attach_ical=False,
|
||||
plain_text_only=True,
|
||||
no_order_links=True,
|
||||
)
|
||||
except SendMailException:
|
||||
raise
|
||||
else:
|
||||
invoice.order.log_action(
|
||||
'pretix.event.order.email.invoice',
|
||||
user=None,
|
||||
auth=None,
|
||||
data={
|
||||
'subject': subject,
|
||||
'message': email_content,
|
||||
'position': None,
|
||||
'recipient': recipient,
|
||||
'invoices': [invoice.pk],
|
||||
'attach_tickets': False,
|
||||
'attach_ical': False,
|
||||
'attach_other_files': [],
|
||||
'attach_cached_files': [],
|
||||
}
|
||||
)
|
||||
# Do not set to completed because that is done by the email sending task
|
||||
subject = format_map(subject, context)
|
||||
email_content = render_mail(template, context)
|
||||
mail(
|
||||
[recipient],
|
||||
subject,
|
||||
template,
|
||||
context=context,
|
||||
event=invoice.order.event,
|
||||
locale=invoice.order.locale,
|
||||
order=invoice.order,
|
||||
invoices=[invoice],
|
||||
attach_tickets=False,
|
||||
auto_email=True,
|
||||
attach_ical=False,
|
||||
plain_text_only=True,
|
||||
no_order_links=True,
|
||||
)
|
||||
invoice.order.log_action(
|
||||
'pretix.event.order.email.invoice',
|
||||
user=None,
|
||||
auth=None,
|
||||
data={
|
||||
'subject': subject,
|
||||
'message': email_content,
|
||||
'position': None,
|
||||
'recipient': recipient,
|
||||
'invoices': [invoice.pk],
|
||||
'attach_tickets': False,
|
||||
'attach_ical': False,
|
||||
'attach_other_files': [],
|
||||
'attach_cached_files': [],
|
||||
}
|
||||
)
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#
|
||||
from typing import Optional
|
||||
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django_countries.fields import Country
|
||||
|
||||
from pretix.base.models import Invoice, InvoiceAddress
|
||||
@@ -106,6 +107,22 @@ class TransmissionType:
|
||||
def transmission_info_to_form_data(self, transmission_info: dict) -> dict:
|
||||
return transmission_info
|
||||
|
||||
def describe_info(self, transmission_info: dict, country: Country, is_business: bool):
|
||||
form_data = self.transmission_info_to_form_data(transmission_info)
|
||||
data = []
|
||||
visible_field_keys = self.invoice_address_form_fields_visible(country, is_business)
|
||||
for k, f in self.invoice_address_form_fields.items():
|
||||
if k not in visible_field_keys:
|
||||
continue
|
||||
v = form_data.get(k)
|
||||
if v is True:
|
||||
v = _("Yes")
|
||||
elif v is False:
|
||||
v = _("No")
|
||||
if v:
|
||||
data.append((f.label, v))
|
||||
return data
|
||||
|
||||
def pdf_watermark(self) -> Optional[str]:
|
||||
"""
|
||||
Return a watermark that should be rendered across the PDF file.
|
||||
|
||||
@@ -294,14 +294,28 @@ def metric_values():
|
||||
channel = app.broker_connection().channel()
|
||||
if hasattr(channel, 'client') and channel.client is not None:
|
||||
client = channel.client
|
||||
priority_steps = settings.CELERY_BROKER_TRANSPORT_OPTIONS.get("priority_steps", [0])
|
||||
sep = settings.CELERY_BROKER_TRANSPORT_OPTIONS.get("sep", ":")
|
||||
|
||||
for q in settings.CELERY_TASK_QUEUES:
|
||||
llen = client.llen(q.name)
|
||||
lfirst = client.lindex(q.name, -1)
|
||||
metrics['pretix_celery_tasks_queued_count']['{queue="%s"}' % q.name] = llen
|
||||
if lfirst:
|
||||
ldata = json.loads(lfirst)
|
||||
dt = time.time() - ldata.get('created', 0)
|
||||
metrics['pretix_celery_tasks_queued_age_seconds']['{queue="%s"}' % q.name] = dt
|
||||
queue_lengths = []
|
||||
queue_delays = []
|
||||
for prio in priority_steps:
|
||||
if prio:
|
||||
qname = f"{q.name}{sep}{prio}"
|
||||
else:
|
||||
qname = q.name
|
||||
queue_length = client.llen(qname)
|
||||
queue_lengths.append(queue_length)
|
||||
oldest_queue_item = client.lindex(qname, -1)
|
||||
if oldest_queue_item:
|
||||
ldata = json.loads(oldest_queue_item)
|
||||
oldest_item_age = time.time() - ldata.get('created', 0)
|
||||
queue_delays.append(oldest_item_age)
|
||||
|
||||
metrics['pretix_celery_tasks_queued_count']['{queue="%s"}' % q.name] = sum(queue_lengths)
|
||||
if queue_delays:
|
||||
metrics['pretix_celery_tasks_queued_age_seconds']['{queue="%s"}' % q.name] = max(queue_delays)
|
||||
else:
|
||||
metrics['pretix_celery_tasks_queued_age_seconds']['{queue="%s"}' % q.name] = 0
|
||||
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
# Generated by Django 4.2.26 on 2026-01-22 13:44
|
||||
import uuid
|
||||
|
||||
import django.db.models.deletion
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
import pretix.base.models.mail
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("pretixbase", "0296_invoice_invoice_from_state"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="OutgoingMail",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.BigAutoField(
|
||||
auto_created=True, primary_key=True, serialize=False
|
||||
),
|
||||
),
|
||||
("guid", models.UUIDField(db_index=True, default=uuid.uuid4)),
|
||||
("status", models.CharField(default="queued", max_length=200)),
|
||||
("created", models.DateTimeField(auto_now_add=True)),
|
||||
("sent", models.DateTimeField(blank=True, null=True)),
|
||||
("inflight_since", models.DateTimeField(blank=True, null=True)),
|
||||
("retry_after", models.DateTimeField(blank=True, null=True)),
|
||||
("error", models.TextField(null=True)),
|
||||
("error_detail", models.TextField(null=True)),
|
||||
("sensitive", models.BooleanField(default=False)),
|
||||
("subject", models.TextField()),
|
||||
("body_plain", models.TextField()),
|
||||
("body_html", models.TextField(null=True)),
|
||||
("sender", models.CharField(max_length=500)),
|
||||
("headers", models.JSONField(default=dict)),
|
||||
("to", models.JSONField(default=list)),
|
||||
("cc", models.JSONField(default=list)),
|
||||
("bcc", models.JSONField(default=list)),
|
||||
("recipient_count", models.IntegerField()),
|
||||
("should_attach_tickets", models.BooleanField(default=False)),
|
||||
("should_attach_ical", models.BooleanField(default=False)),
|
||||
("should_attach_other_files", models.JSONField(default=list)),
|
||||
("actual_attachments", models.JSONField(default=list)),
|
||||
(
|
||||
"customer",
|
||||
models.ForeignKey(
|
||||
null=True,
|
||||
on_delete=pretix.base.models.mail.CASCADE_IF_QUEUED,
|
||||
related_name="outgoing_mails",
|
||||
to="pretixbase.customer",
|
||||
),
|
||||
),
|
||||
(
|
||||
"event",
|
||||
models.ForeignKey(
|
||||
null=True,
|
||||
on_delete=pretix.base.models.mail.CASCADE_IF_QUEUED,
|
||||
related_name="outgoing_mails",
|
||||
to="pretixbase.event",
|
||||
),
|
||||
),
|
||||
(
|
||||
"order",
|
||||
models.ForeignKey(
|
||||
null=True,
|
||||
on_delete=pretix.base.models.mail.CASCADE_IF_QUEUED,
|
||||
related_name="outgoing_mails",
|
||||
to="pretixbase.order",
|
||||
),
|
||||
),
|
||||
(
|
||||
"orderposition",
|
||||
models.ForeignKey(
|
||||
null=True,
|
||||
on_delete=pretix.base.models.mail.CASCADE_IF_QUEUED,
|
||||
related_name="outgoing_mails",
|
||||
to="pretixbase.orderposition",
|
||||
),
|
||||
),
|
||||
(
|
||||
"organizer",
|
||||
models.ForeignKey(
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="outgoing_mails",
|
||||
to="pretixbase.organizer",
|
||||
),
|
||||
),
|
||||
(
|
||||
"should_attach_cached_files",
|
||||
models.ManyToManyField(
|
||||
related_name="outgoing_mails", to="pretixbase.cachedfile"
|
||||
),
|
||||
),
|
||||
(
|
||||
"should_attach_invoices",
|
||||
models.ManyToManyField(
|
||||
related_name="outgoing_mails", to="pretixbase.invoice"
|
||||
),
|
||||
),
|
||||
(
|
||||
"user",
|
||||
models.ForeignKey(
|
||||
null=True,
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="outgoing_mails",
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"ordering": ("-created",),
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -41,6 +41,7 @@ from .items import (
|
||||
itempicture_upload_to,
|
||||
)
|
||||
from .log import LogEntry
|
||||
from .mail import OutgoingMail
|
||||
from .media import ReusableMedium
|
||||
from .memberships import Membership, MembershipType
|
||||
from .notifications import NotificationSetting
|
||||
|
||||
@@ -334,27 +334,24 @@ class User(AbstractBaseUser, PermissionsMixin, LoggingMixin):
|
||||
return self.email
|
||||
|
||||
def send_security_notice(self, messages, email=None):
|
||||
from pretix.base.services.mail import SendMailException, mail
|
||||
from pretix.base.services.mail import mail
|
||||
|
||||
try:
|
||||
with language(self.locale):
|
||||
msg = '- ' + '\n- '.join(str(m) for m in messages)
|
||||
with language(self.locale):
|
||||
msg = '- ' + '\n- '.join(str(m) for m in messages)
|
||||
|
||||
mail(
|
||||
email or self.email,
|
||||
_('Account information changed'),
|
||||
'pretixcontrol/email/security_notice.txt',
|
||||
{
|
||||
'user': self,
|
||||
'messages': msg,
|
||||
'url': build_absolute_uri('control:user.settings')
|
||||
},
|
||||
event=None,
|
||||
user=self,
|
||||
locale=self.locale
|
||||
)
|
||||
except SendMailException:
|
||||
pass # Already logged
|
||||
mail(
|
||||
email or self.email,
|
||||
_('Account information changed'),
|
||||
'pretixcontrol/email/security_notice.txt',
|
||||
{
|
||||
'user': self,
|
||||
'messages': msg,
|
||||
'url': build_absolute_uri('control:user.settings')
|
||||
},
|
||||
event=None,
|
||||
user=self,
|
||||
locale=self.locale
|
||||
)
|
||||
|
||||
def send_confirmation_code(self, session, reason, email=None, state=None):
|
||||
"""
|
||||
|
||||
@@ -130,6 +130,8 @@ class LoggingMixin:
|
||||
organizer_id = self.event.organizer_id
|
||||
elif hasattr(self, 'organizer_id'):
|
||||
organizer_id = self.organizer_id
|
||||
elif hasattr(self, 'issuer_id'):
|
||||
organizer_id = self.issuer_id
|
||||
|
||||
if user and not user.is_authenticated:
|
||||
user = None
|
||||
|
||||
@@ -40,6 +40,7 @@ from i18nfield.fields import I18nCharField
|
||||
from phonenumber_field.modelfields import PhoneNumberField
|
||||
|
||||
from pretix.base.banlist import banned
|
||||
from pretix.base.i18n import language
|
||||
from pretix.base.models.base import LoggedModel
|
||||
from pretix.base.models.fields import MultiStringField
|
||||
from pretix.base.models.giftcards import GiftCardTransaction
|
||||
@@ -164,6 +165,28 @@ class Customer(LoggedModel):
|
||||
self.attendee_profiles.all().delete()
|
||||
self.invoice_addresses.all().delete()
|
||||
|
||||
def send_security_notice(self, message, email=None):
|
||||
from pretix.base.services.mail import SendMailException, mail
|
||||
from pretix.multidomain.urlreverse import build_absolute_uri
|
||||
|
||||
try:
|
||||
with language(self.locale):
|
||||
mail(
|
||||
email or self.email,
|
||||
self.organizer.settings.mail_subject_customer_security_notice,
|
||||
self.organizer.settings.mail_text_customer_security_notice,
|
||||
{
|
||||
**self.get_email_context(),
|
||||
'message': str(message),
|
||||
'url': build_absolute_uri(self.organizer, 'presale:organizer.customer.index')
|
||||
},
|
||||
customer=self,
|
||||
organizer=self.organizer,
|
||||
locale=self.locale
|
||||
)
|
||||
except SendMailException:
|
||||
pass # Already logged
|
||||
|
||||
@scopes_disabled()
|
||||
def assign_identifier(self):
|
||||
charset = list('ABCDEFGHJKLMNPQRSTUVWXYZ23456789')
|
||||
@@ -293,6 +316,7 @@ class Customer(LoggedModel):
|
||||
locale=self.locale,
|
||||
customer=self,
|
||||
organizer=self.organizer,
|
||||
sensitive=True,
|
||||
)
|
||||
|
||||
def usable_gift_cards(self, used_cards=[]):
|
||||
|
||||
@@ -0,0 +1,222 @@
|
||||
#
|
||||
# This file is part of pretix (Community Edition).
|
||||
#
|
||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||
#
|
||||
# ADDITIONAL TERMS APPLY: Pursuant to Section 7 of the GNU Affero General Public License, additional terms are
|
||||
# applicable granting you additional permissions and placing additional restrictions on your usage of this software.
|
||||
# Please refer to the pretix LICENSE file to obtain the full terms applicable to this work. If you did not receive
|
||||
# this file, see <https://pretix.eu/about/en/license>.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
|
||||
# <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
import uuid
|
||||
|
||||
from django.core.mail import get_connection
|
||||
from django.db import models
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django_scopes import scope, scopes_disabled
|
||||
|
||||
|
||||
def CASCADE_IF_QUEUED(collector, field, sub_objs, using):
|
||||
# If the email is still queued and the thing it is related to vanishes, the email can vanish as well
|
||||
cascade_objs = [
|
||||
o for o in sub_objs if o.status == OutgoingMail.STATUS_QUEUED
|
||||
]
|
||||
if cascade_objs:
|
||||
models.CASCADE(collector, field, cascade_objs, using)
|
||||
|
||||
# In all other cases, set to NULL to keep the email on record
|
||||
models.SET_NULL(collector, field, [o for o in sub_objs if o not in cascade_objs], using)
|
||||
|
||||
|
||||
class OutgoingMail(models.Model):
|
||||
STATUS_QUEUED = "queued"
|
||||
STATUS_WITHHELD = "withheld"
|
||||
STATUS_INFLIGHT = "inflight"
|
||||
STATUS_AWAITING_RETRY = "awaiting_retry"
|
||||
STATUS_FAILED = "failed"
|
||||
STATUS_SENT = "sent"
|
||||
STATUS_BOUNCED = "bounced"
|
||||
STATUS_ABORTED = "aborted"
|
||||
STATUS_CHOICES = (
|
||||
(STATUS_QUEUED, _("queued")),
|
||||
(STATUS_INFLIGHT, _("being sent")),
|
||||
(STATUS_AWAITING_RETRY, _("awaiting retry")),
|
||||
(STATUS_WITHHELD, _("withheld")), # for plugin use
|
||||
(STATUS_FAILED, _("failed")),
|
||||
(STATUS_ABORTED, _("aborted")),
|
||||
(STATUS_SENT, _("sent")),
|
||||
(STATUS_BOUNCED, _("bounced")), # for plugin use
|
||||
)
|
||||
STATUS_LIST_ABORTABLE = {
|
||||
STATUS_QUEUED,
|
||||
STATUS_WITHHELD,
|
||||
STATUS_AWAITING_RETRY,
|
||||
}
|
||||
STATUS_LIST_RETRYABLE = {
|
||||
STATUS_FAILED,
|
||||
STATUS_WITHHELD,
|
||||
}
|
||||
|
||||
# The GUID is a globally unique ID for the email added to a header of the email for later tracing
|
||||
# in bug reports etc. We could theoretically also use this as a basis for the Message-ID header, but
|
||||
# we currently don't since we are unsure if some intermediary SMTP servers have opinions on setting
|
||||
# their own Message-ID headers.
|
||||
guid = models.UUIDField(db_index=True, default=uuid.uuid4)
|
||||
|
||||
status = models.CharField(max_length=200, choices=STATUS_CHOICES, default=STATUS_QUEUED)
|
||||
created = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
# sent will be the time the email was sent or the email failed
|
||||
sent = models.DateTimeField(null=True, blank=True)
|
||||
|
||||
inflight_since = models.DateTimeField(null=True, blank=True)
|
||||
retry_after = models.DateTimeField(null=True, blank=True)
|
||||
|
||||
error = models.TextField(null=True, blank=True)
|
||||
error_detail = models.TextField(null=True, blank=True)
|
||||
|
||||
# There is a conflict here between the different purposes of the model. As a system administrator,
|
||||
# one wants *all* emails to be persisted as long as possible to debug issues. This means that if
|
||||
# e.g. the event or order is deleted, we want SET_NULL behavior. However, in that case, the email
|
||||
# would be an "orphan" forever and there's no way to remove the personal information.
|
||||
# We try to find a middle-ground with the following behaviour:
|
||||
# - The email is always deleted if the entire organizer or user is deleted
|
||||
# - The email is always deleted if it has not yet been sent
|
||||
# - The email is kept in all other cases
|
||||
# This is only an acceptable trade-off since emails are stored for a short period only, and because
|
||||
# orders and customers are never deleted during normal operation. If we ever make this a long-term
|
||||
# storage / email archive, we'd need to find another way to make sure personal information is removed
|
||||
# if personal information of orders etc is removed.
|
||||
organizer = models.ForeignKey(
|
||||
'pretixbase.Organizer',
|
||||
on_delete=models.CASCADE,
|
||||
related_name='outgoing_mails',
|
||||
null=True, blank=True,
|
||||
)
|
||||
event = models.ForeignKey(
|
||||
'pretixbase.Event',
|
||||
on_delete=CASCADE_IF_QUEUED,
|
||||
related_name='outgoing_mails',
|
||||
null=True, blank=True,
|
||||
)
|
||||
order = models.ForeignKey(
|
||||
'pretixbase.Order',
|
||||
on_delete=CASCADE_IF_QUEUED,
|
||||
related_name='outgoing_mails',
|
||||
null=True, blank=True,
|
||||
)
|
||||
orderposition = models.ForeignKey(
|
||||
'pretixbase.OrderPosition',
|
||||
on_delete=CASCADE_IF_QUEUED,
|
||||
related_name='outgoing_mails',
|
||||
null=True, blank=True,
|
||||
)
|
||||
customer = models.ForeignKey(
|
||||
'pretixbase.Customer',
|
||||
on_delete=CASCADE_IF_QUEUED,
|
||||
related_name='outgoing_mails',
|
||||
null=True, blank=True,
|
||||
)
|
||||
user = models.ForeignKey(
|
||||
'pretixbase.User',
|
||||
on_delete=models.CASCADE,
|
||||
related_name='outgoing_mails',
|
||||
null=True, blank=True,
|
||||
)
|
||||
|
||||
sensitive = models.BooleanField(default=False)
|
||||
subject = models.TextField()
|
||||
body_plain = models.TextField()
|
||||
body_html = models.TextField(null=True)
|
||||
sender = models.CharField(max_length=500)
|
||||
headers = models.JSONField(default=dict)
|
||||
to = models.JSONField(default=list)
|
||||
cc = models.JSONField(default=list)
|
||||
bcc = models.JSONField(default=list)
|
||||
recipient_count = models.IntegerField()
|
||||
|
||||
# We don't store the actual invoices, tickets or calendar invites, so if the email is re-sent at a later time, a
|
||||
# newer version of the files might be used. We accept that risk to save on storage and also because the new
|
||||
# version might actually be more useful.
|
||||
should_attach_invoices = models.ManyToManyField(
|
||||
'pretixbase.Invoice',
|
||||
related_name='outgoing_mails'
|
||||
)
|
||||
should_attach_tickets = models.BooleanField(default=False)
|
||||
should_attach_ical = models.BooleanField(default=False)
|
||||
|
||||
# clean_cached_files makes sure not to delete these as long as the email is in a retryable state
|
||||
should_attach_cached_files = models.ManyToManyField(
|
||||
'pretixbase.CachedFile',
|
||||
related_name='outgoing_mails',
|
||||
)
|
||||
|
||||
# This is used to send files stored in settings. In most cases, these aren't short-lived and should still be there
|
||||
# if the email is sent. Otherwise, they will be skipped. We accept that risk.
|
||||
should_attach_other_files = models.JSONField(default=list)
|
||||
|
||||
# [{name, type size}] of the attachments we actually setn
|
||||
actual_attachments = models.JSONField(default=list)
|
||||
|
||||
class Meta:
|
||||
ordering = ('-created',)
|
||||
|
||||
def get_mail_backend(self):
|
||||
if self.event:
|
||||
return self.event.get_mail_backend()
|
||||
elif self.organizer:
|
||||
return self.organizer.get_mail_backend()
|
||||
else:
|
||||
return get_connection(fail_silently=False)
|
||||
|
||||
def scope_manager(self):
|
||||
if self.organizer:
|
||||
return scope(organizer=self.organizer) # noqa
|
||||
else:
|
||||
return scopes_disabled() # noqa
|
||||
|
||||
@property
|
||||
def is_failed(self):
|
||||
return self.status in (
|
||||
OutgoingMail.STATUS_FAILED,
|
||||
OutgoingMail.STATUS_AWAITING_RETRY,
|
||||
OutgoingMail.STATUS_BOUNCED,
|
||||
)
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if self.orderposition_id and not self.order_id:
|
||||
self.order = self.orderposition.order
|
||||
if self.order_id and not self.event_id:
|
||||
self.event = self.order.event
|
||||
if self.event_id and not self.organizer_id:
|
||||
self.organizer = self.event.organizer
|
||||
if self.customer_id and not self.organizer_id:
|
||||
self.organizer = self.customer.organizer
|
||||
self.recipient_count = len(self.to) + len(self.cc) + len(self.bcc)
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
def log_parameters(self):
|
||||
if self.order:
|
||||
error_log_action_type = 'pretix.event.order.email.error'
|
||||
log_target = self.order
|
||||
elif self.customer:
|
||||
error_log_action_type = 'pretix.customer.email.error'
|
||||
log_target = self.customer
|
||||
elif self.user:
|
||||
error_log_action_type = 'pretix.user.email.error'
|
||||
log_target = self.user
|
||||
else:
|
||||
error_log_action_type = 'pretix.email.error'
|
||||
log_target = None
|
||||
return log_target, error_log_action_type
|
||||
@@ -87,7 +87,7 @@ from pretix.base.timemachine import time_machine_now
|
||||
|
||||
from ...helpers import OF_SELF
|
||||
from ...helpers.countries import CachedCountries, FastCountryField
|
||||
from ...helpers.format import format_map
|
||||
from ...helpers.format import FormattedString, format_map
|
||||
from ...helpers.names import build_name
|
||||
from ...testutils.middleware import debugflags_var
|
||||
from ._transactions import (
|
||||
@@ -1167,9 +1167,7 @@ class Order(LockModel, LoggedModel):
|
||||
only be attached for this position and child positions, the link will only point to the
|
||||
position and the attendee email will be used if available.
|
||||
"""
|
||||
from pretix.base.services.mail import (
|
||||
SendMailException, mail, render_mail,
|
||||
)
|
||||
from pretix.base.services.mail import mail, render_mail
|
||||
|
||||
if not self.email and not (position and position.attendee_email):
|
||||
return
|
||||
@@ -1179,35 +1177,32 @@ class Order(LockModel, LoggedModel):
|
||||
if position and position.attendee_email:
|
||||
recipient = position.attendee_email
|
||||
|
||||
try:
|
||||
email_content = render_mail(template, context)
|
||||
email_content = render_mail(template, context)
|
||||
if not isinstance(subject, FormattedString):
|
||||
subject = format_map(subject, context)
|
||||
mail(
|
||||
recipient, subject, template, context,
|
||||
self.event, self.locale, self, headers=headers, sender=sender,
|
||||
invoices=invoices, attach_tickets=attach_tickets,
|
||||
position=position, auto_email=auto_email, attach_ical=attach_ical,
|
||||
attach_other_files=attach_other_files, attach_cached_files=attach_cached_files,
|
||||
)
|
||||
except SendMailException:
|
||||
raise
|
||||
else:
|
||||
self.log_action(
|
||||
log_entry_type,
|
||||
user=user,
|
||||
auth=auth,
|
||||
data={
|
||||
'subject': subject,
|
||||
'message': email_content,
|
||||
'position': position.positionid if position else None,
|
||||
'recipient': recipient,
|
||||
'invoices': [i.pk for i in invoices] if invoices else [],
|
||||
'attach_tickets': attach_tickets,
|
||||
'attach_ical': attach_ical,
|
||||
'attach_other_files': attach_other_files,
|
||||
'attach_cached_files': [cf.filename for cf in attach_cached_files] if attach_cached_files else [],
|
||||
}
|
||||
)
|
||||
mail(
|
||||
recipient, subject, template, context,
|
||||
self.event, self.locale, self, headers=headers, sender=sender,
|
||||
invoices=invoices, attach_tickets=attach_tickets,
|
||||
position=position, auto_email=auto_email, attach_ical=attach_ical,
|
||||
attach_other_files=attach_other_files, attach_cached_files=attach_cached_files,
|
||||
)
|
||||
self.log_action(
|
||||
log_entry_type,
|
||||
user=user,
|
||||
auth=auth,
|
||||
data={
|
||||
'subject': subject,
|
||||
'message': email_content,
|
||||
'position': position.positionid if position else None,
|
||||
'recipient': recipient,
|
||||
'invoices': [i.pk for i in invoices] if invoices else [],
|
||||
'attach_tickets': attach_tickets,
|
||||
'attach_ical': attach_ical,
|
||||
'attach_other_files': attach_other_files,
|
||||
'attach_cached_files': [cf.filename for cf in attach_cached_files] if attach_cached_files else [],
|
||||
}
|
||||
)
|
||||
|
||||
def resend_link(self, user=None, auth=None):
|
||||
with language(self.locale, self.event.settings.region):
|
||||
@@ -2024,40 +2019,30 @@ class OrderPayment(models.Model):
|
||||
transmit_invoice.apply_async(args=(self.order.event_id, invoice.pk, False))
|
||||
|
||||
def _send_paid_mail_attendee(self, position, user):
|
||||
from pretix.base.services.mail import SendMailException
|
||||
|
||||
with language(self.order.locale, self.order.event.settings.region):
|
||||
email_template = self.order.event.settings.mail_text_order_paid_attendee
|
||||
email_subject = self.order.event.settings.mail_subject_order_paid_attendee
|
||||
email_context = get_email_context(event=self.order.event, order=self.order, position=position)
|
||||
try:
|
||||
position.send_mail(
|
||||
email_subject, email_template, email_context,
|
||||
'pretix.event.order.email.order_paid', user,
|
||||
invoices=[],
|
||||
attach_tickets=True,
|
||||
attach_ical=self.order.event.settings.mail_attach_ical
|
||||
)
|
||||
except SendMailException:
|
||||
logger.exception('Order paid email could not be sent')
|
||||
position.send_mail(
|
||||
email_subject, email_template, email_context,
|
||||
'pretix.event.order.email.order_paid', user,
|
||||
invoices=[],
|
||||
attach_tickets=True,
|
||||
attach_ical=self.order.event.settings.mail_attach_ical
|
||||
)
|
||||
|
||||
def _send_paid_mail(self, invoice, user, mail_text):
|
||||
from pretix.base.services.mail import SendMailException
|
||||
|
||||
with language(self.order.locale, self.order.event.settings.region):
|
||||
email_template = self.order.event.settings.mail_text_order_paid
|
||||
email_subject = self.order.event.settings.mail_subject_order_paid
|
||||
email_context = get_email_context(event=self.order.event, order=self.order, payment_info=mail_text)
|
||||
try:
|
||||
self.order.send_mail(
|
||||
email_subject, email_template, email_context,
|
||||
'pretix.event.order.email.order_paid', user,
|
||||
invoices=[invoice] if invoice else [],
|
||||
attach_tickets=True,
|
||||
attach_ical=self.order.event.settings.mail_attach_ical
|
||||
)
|
||||
except SendMailException:
|
||||
logger.exception('Order paid email could not be sent')
|
||||
self.order.send_mail(
|
||||
email_subject, email_template, email_context,
|
||||
'pretix.event.order.email.order_paid', user,
|
||||
invoices=[invoice] if invoice else [],
|
||||
attach_tickets=True,
|
||||
attach_ical=self.order.event.settings.mail_attach_ical
|
||||
)
|
||||
|
||||
@property
|
||||
def refunded_amount(self):
|
||||
@@ -2915,45 +2900,40 @@ class OrderPosition(AbstractPosition):
|
||||
:param attach_tickets: Attach tickets of this order, if they are existing and ready to download
|
||||
:param attach_ical: Attach relevant ICS files
|
||||
"""
|
||||
from pretix.base.services.mail import (
|
||||
SendMailException, mail, render_mail,
|
||||
)
|
||||
from pretix.base.services.mail import mail, render_mail
|
||||
|
||||
if not self.attendee_email:
|
||||
return
|
||||
|
||||
with language(self.order.locale, self.order.event.settings.region):
|
||||
recipient = self.attendee_email
|
||||
try:
|
||||
email_content = render_mail(template, context)
|
||||
email_content = render_mail(template, context)
|
||||
if not isinstance(subject, FormattedString):
|
||||
subject = format_map(subject, context)
|
||||
mail(
|
||||
recipient, subject, template, context,
|
||||
self.event, self.order.locale, order=self.order, headers=headers, sender=sender,
|
||||
position=self,
|
||||
invoices=invoices,
|
||||
attach_tickets=attach_tickets,
|
||||
attach_ical=attach_ical,
|
||||
attach_other_files=attach_other_files,
|
||||
)
|
||||
except SendMailException:
|
||||
raise
|
||||
else:
|
||||
self.order.log_action(
|
||||
log_entry_type,
|
||||
user=user,
|
||||
auth=auth,
|
||||
data={
|
||||
'subject': subject,
|
||||
'message': email_content,
|
||||
'recipient': recipient,
|
||||
'invoices': [i.pk for i in invoices] if invoices else [],
|
||||
'attach_tickets': attach_tickets,
|
||||
'attach_ical': attach_ical,
|
||||
'attach_other_files': attach_other_files,
|
||||
'attach_cached_files': [],
|
||||
}
|
||||
)
|
||||
mail(
|
||||
recipient, subject, template, context,
|
||||
self.event, self.order.locale, order=self.order, headers=headers, sender=sender,
|
||||
position=self,
|
||||
invoices=invoices,
|
||||
attach_tickets=attach_tickets,
|
||||
attach_ical=attach_ical,
|
||||
attach_other_files=attach_other_files,
|
||||
)
|
||||
self.order.log_action(
|
||||
log_entry_type,
|
||||
user=user,
|
||||
auth=auth,
|
||||
data={
|
||||
'subject': subject,
|
||||
'message': email_content,
|
||||
'recipient': recipient,
|
||||
'invoices': [i.pk for i in invoices] if invoices else [],
|
||||
'attach_tickets': attach_tickets,
|
||||
'attach_ical': attach_ical,
|
||||
'attach_other_files': attach_other_files,
|
||||
'attach_cached_files': [],
|
||||
}
|
||||
)
|
||||
|
||||
def resend_link(self, user=None, auth=None):
|
||||
|
||||
@@ -3529,18 +3509,10 @@ class InvoiceAddress(models.Model):
|
||||
def describe_transmission(self):
|
||||
from pretix.base.invoicing.transmission import transmission_types
|
||||
data = []
|
||||
|
||||
t, __ = transmission_types.get(identifier=self.transmission_type)
|
||||
data.append((_("Transmission type"), t.public_name))
|
||||
form_data = t.transmission_info_to_form_data(self.transmission_info or {})
|
||||
for k, f in t.invoice_address_form_fields.items():
|
||||
v = form_data.get(k)
|
||||
if v is True:
|
||||
v = _("Yes")
|
||||
elif v is False:
|
||||
v = _("No")
|
||||
if v:
|
||||
data.append((f.label, v))
|
||||
if self.transmission_info:
|
||||
data += t.describe_info(self.transmission_info, self.country, self.is_business)
|
||||
return data
|
||||
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ from phonenumber_field.modelfields import PhoneNumberField
|
||||
from pretix.base.email import get_email_context
|
||||
from pretix.base.i18n import language
|
||||
from pretix.base.models import User, Voucher
|
||||
from pretix.base.services.mail import SendMailException, mail, render_mail
|
||||
from pretix.base.services.mail import mail, render_mail
|
||||
from pretix.helpers import OF_SELF
|
||||
|
||||
from ...helpers.format import format_map
|
||||
@@ -272,34 +272,30 @@ class WaitingListEntry(LoggedModel):
|
||||
with language(self.locale, self.event.settings.region):
|
||||
recipient = self.email
|
||||
|
||||
try:
|
||||
email_content = render_mail(template, context)
|
||||
subject = format_map(subject, context)
|
||||
mail(
|
||||
recipient, subject, template, context,
|
||||
self.event,
|
||||
self.locale,
|
||||
headers=headers,
|
||||
sender=sender,
|
||||
auto_email=auto_email,
|
||||
attach_other_files=attach_other_files,
|
||||
attach_cached_files=attach_cached_files,
|
||||
)
|
||||
except SendMailException:
|
||||
raise
|
||||
else:
|
||||
self.log_action(
|
||||
log_entry_type,
|
||||
user=user,
|
||||
auth=auth,
|
||||
data={
|
||||
'subject': subject,
|
||||
'message': email_content,
|
||||
'recipient': recipient,
|
||||
'attach_other_files': attach_other_files,
|
||||
'attach_cached_files': [cf.filename for cf in attach_cached_files] if attach_cached_files else [],
|
||||
}
|
||||
)
|
||||
email_content = render_mail(template, context)
|
||||
subject = format_map(subject, context)
|
||||
mail(
|
||||
recipient, subject, template, context,
|
||||
self.event,
|
||||
self.locale,
|
||||
headers=headers,
|
||||
sender=sender,
|
||||
auto_email=auto_email,
|
||||
attach_other_files=attach_other_files,
|
||||
attach_cached_files=attach_cached_files,
|
||||
)
|
||||
self.log_action(
|
||||
log_entry_type,
|
||||
user=user,
|
||||
auth=auth,
|
||||
data={
|
||||
'subject': subject,
|
||||
'message': email_content,
|
||||
'recipient': recipient,
|
||||
'attach_other_files': attach_other_files,
|
||||
'attach_cached_files': [cf.filename for cf in attach_cached_files] if attach_cached_files else [],
|
||||
}
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def clean_itemvar(event, item, variation):
|
||||
|
||||
@@ -1231,8 +1231,8 @@ class ManualPayment(BasePaymentProvider):
|
||||
def is_allowed(self, request: HttpRequest, total: Decimal=None):
|
||||
return 'pretix.plugins.manualpayment' in self.event.plugins and super().is_allowed(request, total)
|
||||
|
||||
def order_change_allowed(self, order: Order):
|
||||
return 'pretix.plugins.manualpayment' in self.event.plugins and super().order_change_allowed(order)
|
||||
def order_change_allowed(self, order: Order, request=None):
|
||||
return 'pretix.plugins.manualpayment' in self.event.plugins and super().order_change_allowed(order, request)
|
||||
|
||||
@property
|
||||
def public_name(self):
|
||||
@@ -1646,6 +1646,13 @@ class GiftCardPayment(BasePaymentProvider):
|
||||
'transaction_id': trans.pk,
|
||||
}
|
||||
payment.confirm(send_mail=not is_early_special_case, generate_invoice=not is_early_special_case)
|
||||
gc.log_action(
|
||||
action='pretix.giftcards.transaction.payment',
|
||||
data={
|
||||
'value': trans.value,
|
||||
'acceptor_id': self.event.organizer.id
|
||||
}
|
||||
)
|
||||
except PaymentException as e:
|
||||
payment.fail(info={'error': str(e)})
|
||||
raise e
|
||||
@@ -1670,6 +1677,14 @@ class GiftCardPayment(BasePaymentProvider):
|
||||
'transaction_id': trans.pk,
|
||||
}
|
||||
refund.done()
|
||||
gc.log_action(
|
||||
action='pretix.giftcards.transaction.refund',
|
||||
data={
|
||||
'value': refund.amount,
|
||||
'acceptor_id': self.event.organizer.id,
|
||||
'text': refund.comment,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@receiver(register_payment_providers, dispatch_uid="payment_free")
|
||||
|
||||
@@ -65,7 +65,7 @@ def get_all_plugins(*, event=None, organizer=None) -> List[type]:
|
||||
if app.name in settings.PRETIX_PLUGINS_EXCLUDE:
|
||||
continue
|
||||
|
||||
level = getattr(app, "level", PLUGIN_LEVEL_EVENT)
|
||||
level = getattr(meta, "level", PLUGIN_LEVEL_EVENT)
|
||||
if level == PLUGIN_LEVEL_EVENT:
|
||||
if event and hasattr(app, 'is_available'):
|
||||
if not app.is_available(event):
|
||||
|
||||
@@ -36,7 +36,7 @@ from pretix.base.models import (
|
||||
SubEvent, TaxRule, User, WaitingListEntry,
|
||||
)
|
||||
from pretix.base.services.locking import LockTimeoutException
|
||||
from pretix.base.services.mail import SendMailException, mail
|
||||
from pretix.base.services.mail import mail
|
||||
from pretix.base.services.orders import (
|
||||
OrderChangeManager, OrderError, _cancel_order, _try_auto_refund,
|
||||
)
|
||||
@@ -53,17 +53,14 @@ logger = logging.getLogger(__name__)
|
||||
def _send_wle_mail(wle: WaitingListEntry, subject: LazyI18nString, message: LazyI18nString, subevent: SubEvent):
|
||||
with language(wle.locale, wle.event.settings.region):
|
||||
email_context = get_email_context(event_or_subevent=subevent or wle.event, event=wle.event)
|
||||
try:
|
||||
mail(
|
||||
wle.email,
|
||||
format_map(subject, email_context),
|
||||
message,
|
||||
email_context,
|
||||
wle.event,
|
||||
locale=wle.locale
|
||||
)
|
||||
except SendMailException:
|
||||
logger.exception('Waiting list canceled email could not be sent')
|
||||
mail(
|
||||
wle.email,
|
||||
format_map(subject, email_context),
|
||||
message,
|
||||
email_context,
|
||||
wle.event,
|
||||
locale=wle.locale
|
||||
)
|
||||
|
||||
|
||||
def _send_mail(order: Order, subject: LazyI18nString, message: LazyI18nString, subevent: SubEvent,
|
||||
@@ -77,14 +74,11 @@ def _send_mail(order: Order, subject: LazyI18nString, message: LazyI18nString, s
|
||||
email_context = get_email_context(event_or_subevent=subevent or order.event, refund_amount=refund_amount,
|
||||
order=order, position_or_address=ia, event=order.event)
|
||||
real_subject = format_map(subject, email_context)
|
||||
try:
|
||||
order.send_mail(
|
||||
real_subject, message, email_context,
|
||||
'pretix.event.order.email.event_canceled',
|
||||
user,
|
||||
)
|
||||
except SendMailException:
|
||||
logger.exception('Order canceled email could not be sent')
|
||||
order.send_mail(
|
||||
real_subject, message, email_context,
|
||||
'pretix.event.order.email.event_canceled',
|
||||
user,
|
||||
)
|
||||
|
||||
for p in positions:
|
||||
if subevent and p.subevent_id != subevent.id:
|
||||
@@ -97,15 +91,12 @@ def _send_mail(order: Order, subject: LazyI18nString, message: LazyI18nString, s
|
||||
refund_amount=refund_amount,
|
||||
position_or_address=p,
|
||||
order=order, position=p)
|
||||
try:
|
||||
order.send_mail(
|
||||
real_subject, message, email_context,
|
||||
'pretix.event.order.email.event_canceled',
|
||||
position=p,
|
||||
user=user
|
||||
)
|
||||
except SendMailException:
|
||||
logger.exception('Order canceled email could not be sent to attendee')
|
||||
order.send_mail(
|
||||
real_subject, message, email_context,
|
||||
'pretix.event.order.email.event_canceled',
|
||||
position=p,
|
||||
user=user
|
||||
)
|
||||
|
||||
|
||||
@app.task(base=ProfiledEventTask, bind=True, max_retries=5, default_retry_delay=1, throws=(OrderError,))
|
||||
|
||||
@@ -1639,7 +1639,7 @@ def get_fees(event, request, _total_ignored_=None, invoice_address=None, payment
|
||||
if fee.tax_rule and not fee.tax_rule.pk:
|
||||
fee.tax_rule = None # TODO: deprecate
|
||||
|
||||
apply_rounding(event.settings.tax_rounding, event.currency, [*positions, *fees])
|
||||
apply_rounding(event.settings.tax_rounding, invoice_address, event.currency, [*positions, *fees])
|
||||
total = sum([c.price for c in positions]) + sum([f.value for f in fees])
|
||||
|
||||
if total != 0 and payments:
|
||||
@@ -1679,7 +1679,7 @@ def get_fees(event, request, _total_ignored_=None, invoice_address=None, payment
|
||||
fees.append(pf)
|
||||
|
||||
# Re-apply rounding as grand total has changed
|
||||
apply_rounding(event.settings.tax_rounding, event.currency, [*positions, *fees])
|
||||
apply_rounding(event.settings.tax_rounding, invoice_address, event.currency, [*positions, *fees])
|
||||
total = sum([c.price for c in positions]) + sum([f.value for f in fees])
|
||||
|
||||
# Re-calculate to_pay as grand total has changed
|
||||
|
||||
@@ -23,11 +23,12 @@ from datetime import timedelta
|
||||
|
||||
from django.conf import settings
|
||||
from django.core.management import call_command
|
||||
from django.db.models import Exists, OuterRef
|
||||
from django.dispatch import receiver
|
||||
from django.utils.timezone import now
|
||||
from django_scopes import scopes_disabled
|
||||
|
||||
from pretix.base.models import CachedCombinedTicket, CachedTicket
|
||||
from pretix.base.models import CachedCombinedTicket, CachedTicket, OutgoingMail
|
||||
from pretix.base.models.customers import CustomerSSOGrant
|
||||
|
||||
from ..models import CachedFile, CartPosition, InvoiceAddress
|
||||
@@ -49,7 +50,18 @@ def clean_cart_positions(sender, **kwargs):
|
||||
@receiver(signal=periodic_task)
|
||||
@scopes_disabled()
|
||||
def clean_cached_files(sender, **kwargs):
|
||||
for cf in CachedFile.objects.filter(expires__isnull=False, expires__lt=now()):
|
||||
has_queued_email = Exists(
|
||||
OutgoingMail.objects.filter(
|
||||
should_attach_cached_files__pk=OuterRef("pk"),
|
||||
status__in=(
|
||||
OutgoingMail.STATUS_QUEUED,
|
||||
OutgoingMail.STATUS_INFLIGHT,
|
||||
OutgoingMail.STATUS_AWAITING_RETRY,
|
||||
OutgoingMail.STATUS_FAILED,
|
||||
),
|
||||
)
|
||||
)
|
||||
for cf in CachedFile.objects.filter(expires__isnull=False, expires__lt=now()).exclude(has_queued_email):
|
||||
cf.delete()
|
||||
|
||||
|
||||
|
||||
+653
-408
File diff suppressed because it is too large
Load Diff
@@ -19,6 +19,8 @@
|
||||
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
|
||||
# <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
import uuid
|
||||
|
||||
import css_inline
|
||||
from django.conf import settings
|
||||
from django.template.loader import get_template
|
||||
@@ -26,7 +28,9 @@ from django.utils.timezone import override
|
||||
from django_scopes import scope, scopes_disabled
|
||||
|
||||
from pretix.base.i18n import language
|
||||
from pretix.base.models import LogEntry, NotificationSetting, User
|
||||
from pretix.base.models import (
|
||||
LogEntry, NotificationSetting, OutgoingMail, User,
|
||||
)
|
||||
from pretix.base.notifications import Notification, get_all_notification_types
|
||||
from pretix.base.services.mail import mail_send_task
|
||||
from pretix.base.services.tasks import ProfiledTask, TransactionAwareTask
|
||||
@@ -153,16 +157,26 @@ def send_notification_mail(notification: Notification, user: User):
|
||||
tpl_plain = get_template('pretixbase/email/notification.txt')
|
||||
body_plain = tpl_plain.render(ctx)
|
||||
|
||||
mail_send_task.apply_async(kwargs={
|
||||
'to': [user.email],
|
||||
'subject': '[{}] {}: {}'.format(
|
||||
guid = uuid.uuid4()
|
||||
m = OutgoingMail.objects.create(
|
||||
guid=guid,
|
||||
user=user,
|
||||
to=[user.email],
|
||||
subject='[{}] {}: {}'.format(
|
||||
settings.PRETIX_INSTANCE_NAME,
|
||||
notification.event.settings.mail_prefix or notification.event.slug.upper(),
|
||||
notification.title
|
||||
),
|
||||
'body': body_plain,
|
||||
'html': body_html,
|
||||
'sender': settings.MAIL_FROM_NOTIFICATIONS,
|
||||
'headers': {},
|
||||
'user': user.pk
|
||||
body_plain=body_plain,
|
||||
body_html=body_html,
|
||||
sender=settings.MAIL_FROM_NOTIFICATIONS,
|
||||
headers={
|
||||
'X-Auto-Response-Suppress': 'OOF, NRN, AutoReply, RN',
|
||||
'Auto-Submitted': 'auto-generated',
|
||||
'X-Mailer': 'pretix',
|
||||
'X-PX-Correlation': str(guid),
|
||||
},
|
||||
)
|
||||
mail_send_task.apply_async(kwargs={
|
||||
'outgoing_mail': m.pk,
|
||||
})
|
||||
|
||||
+186
-146
@@ -90,7 +90,6 @@ from pretix.base.services.invoices import (
|
||||
from pretix.base.services.locking import (
|
||||
LOCK_TRUST_WINDOW, LockTimeoutException, lock_objects,
|
||||
)
|
||||
from pretix.base.services.mail import SendMailException
|
||||
from pretix.base.services.memberships import (
|
||||
create_membership, validate_memberships_in_order,
|
||||
)
|
||||
@@ -248,6 +247,15 @@ def reactivate_order(order: Order, force: bool=False, user: User=None, auth=None
|
||||
for gc in position.issued_gift_cards.all():
|
||||
gc = GiftCard.objects.select_for_update(of=OF_SELF).get(pk=gc.pk)
|
||||
gc.transactions.create(value=position.price, order=order, acceptor=order.event.organizer)
|
||||
gc.log_action(
|
||||
action='pretix.giftcards.transaction.manual',
|
||||
user=user,
|
||||
auth=auth,
|
||||
data={
|
||||
'value': position.price,
|
||||
'acceptor_id': order.event.organizer.id
|
||||
}
|
||||
)
|
||||
break
|
||||
|
||||
for m in position.granted_memberships.all():
|
||||
@@ -438,33 +446,27 @@ def approve_order(order, user=None, send_mail: bool=True, auth=None, force=False
|
||||
email_attendee_subject = order.event.settings.mail_subject_order_approved_attendee
|
||||
|
||||
email_context = get_email_context(event=order.event, order=order)
|
||||
try:
|
||||
order.send_mail(
|
||||
email_subject, email_template, email_context,
|
||||
'pretix.event.order.email.order_approved', user,
|
||||
attach_tickets=True,
|
||||
attach_ical=order.event.settings.mail_attach_ical and (
|
||||
not order.event.settings.mail_attach_ical_paid_only or
|
||||
order.total == Decimal('0.00') or
|
||||
order.valid_if_pending
|
||||
),
|
||||
invoices=[invoice] if invoice and transmit_invoice_mail else []
|
||||
)
|
||||
except SendMailException:
|
||||
logger.exception('Order approved email could not be sent')
|
||||
order.send_mail(
|
||||
email_subject, email_template, email_context,
|
||||
'pretix.event.order.email.order_approved', user,
|
||||
attach_tickets=True,
|
||||
attach_ical=order.event.settings.mail_attach_ical and (
|
||||
not order.event.settings.mail_attach_ical_paid_only or
|
||||
order.total == Decimal('0.00') or
|
||||
order.valid_if_pending
|
||||
),
|
||||
invoices=[invoice] if invoice and transmit_invoice_mail else []
|
||||
)
|
||||
|
||||
if email_attendees:
|
||||
for p in order.positions.all():
|
||||
if p.addon_to_id is None and p.attendee_email and p.attendee_email != order.email:
|
||||
email_attendee_context = get_email_context(event=order.event, order=order, position=p)
|
||||
try:
|
||||
p.send_mail(
|
||||
email_attendee_subject, email_attendee_template, email_attendee_context,
|
||||
'pretix.event.order.email.order_approved', user,
|
||||
attach_tickets=True,
|
||||
)
|
||||
except SendMailException:
|
||||
logger.exception('Order approved email could not be sent to attendee')
|
||||
p.send_mail(
|
||||
email_attendee_subject, email_attendee_template, email_attendee_context,
|
||||
'pretix.event.order.email.order_approved', user,
|
||||
attach_tickets=True,
|
||||
)
|
||||
|
||||
return order.pk
|
||||
|
||||
@@ -501,13 +503,10 @@ def deny_order(order, comment='', user=None, send_mail: bool=True, auth=None):
|
||||
email_template = order.event.settings.mail_text_order_denied
|
||||
email_subject = order.event.settings.mail_subject_order_denied
|
||||
email_context = get_email_context(event=order.event, order=order, comment=comment)
|
||||
try:
|
||||
order.send_mail(
|
||||
email_subject, email_template, email_context,
|
||||
'pretix.event.order.email.order_denied', user
|
||||
)
|
||||
except SendMailException:
|
||||
logger.exception('Order denied email could not be sent')
|
||||
order.send_mail(
|
||||
email_subject, email_template, email_context,
|
||||
'pretix.event.order.email.order_denied', user
|
||||
)
|
||||
|
||||
return order.pk
|
||||
|
||||
@@ -558,6 +557,14 @@ def _cancel_order(order, user=None, send_mail: bool=True, api_token=None, device
|
||||
)
|
||||
else:
|
||||
gc.transactions.create(value=-position.price, order=order, acceptor=order.event.organizer)
|
||||
gc.log_action(
|
||||
action='pretix.giftcards.transaction.manual',
|
||||
user=user,
|
||||
data={
|
||||
'value': -position.price,
|
||||
'acceptor_id': order.event.organizer.id,
|
||||
}
|
||||
)
|
||||
|
||||
for m in position.granted_memberships.all():
|
||||
m.canceled = True
|
||||
@@ -660,14 +667,11 @@ def _cancel_order(order, user=None, send_mail: bool=True, api_token=None, device
|
||||
email_template = order.event.settings.mail_text_order_canceled
|
||||
email_subject = order.event.settings.mail_subject_order_canceled
|
||||
email_context = get_email_context(event=order.event, order=order, comment=comment or "")
|
||||
try:
|
||||
order.send_mail(
|
||||
email_subject, email_template, email_context,
|
||||
'pretix.event.order.email.order_canceled', user,
|
||||
invoices=transmit_invoices_mail,
|
||||
)
|
||||
except SendMailException:
|
||||
logger.exception('Order canceled email could not be sent')
|
||||
order.send_mail(
|
||||
email_subject, email_template, email_context,
|
||||
'pretix.event.order.email.order_canceled', user,
|
||||
invoices=transmit_invoices_mail,
|
||||
)
|
||||
|
||||
for p in order.payments.filter(state__in=(OrderPayment.PAYMENT_STATE_CREATED, OrderPayment.PAYMENT_STATE_PENDING)):
|
||||
try:
|
||||
@@ -968,7 +972,7 @@ def _apply_rounding_and_fees(positions: List[CartPosition], payment_requests: Li
|
||||
fee.tax_rule = None # TODO: deprecate
|
||||
|
||||
# Apply rounding to get final total in case no payment fees will be added
|
||||
apply_rounding(event.settings.tax_rounding, event.currency, [*positions, *fees])
|
||||
apply_rounding(event.settings.tax_rounding, address, event.currency, [*positions, *fees])
|
||||
total = sum([c.price for c in positions]) + sum([f.value for f in fees])
|
||||
|
||||
payments_assigned = Decimal("0.00")
|
||||
@@ -995,7 +999,7 @@ def _apply_rounding_and_fees(positions: List[CartPosition], payment_requests: Li
|
||||
p['fee'] = pf
|
||||
|
||||
# Re-apply rounding as grand total has changed
|
||||
apply_rounding(event.settings.tax_rounding, event.currency, [*positions, *fees])
|
||||
apply_rounding(event.settings.tax_rounding, address, event.currency, [*positions, *fees])
|
||||
total = sum([c.price for c in positions]) + sum([f.value for f in fees])
|
||||
|
||||
# Re-calculate to_pay as grand total has changed
|
||||
@@ -1108,46 +1112,40 @@ def _order_placed_email(event: Event, order: Order, email_template, subject_temp
|
||||
log_entry: str, invoice, payments: List[OrderPayment], is_free=False):
|
||||
email_context = get_email_context(event=event, order=order, payments=payments)
|
||||
|
||||
try:
|
||||
order.send_mail(
|
||||
subject_template, email_template, email_context,
|
||||
log_entry,
|
||||
invoices=[invoice] if invoice else [],
|
||||
attach_tickets=True,
|
||||
attach_ical=event.settings.mail_attach_ical and (
|
||||
not event.settings.mail_attach_ical_paid_only or
|
||||
is_free or
|
||||
order.valid_if_pending
|
||||
),
|
||||
attach_other_files=[a for a in [
|
||||
event.settings.get('mail_attachment_new_order', as_type=str, default='')[len('file://'):]
|
||||
] if a],
|
||||
)
|
||||
except SendMailException:
|
||||
logger.exception('Order received email could not be sent')
|
||||
order.send_mail(
|
||||
subject_template, email_template, email_context,
|
||||
log_entry,
|
||||
invoices=[invoice] if invoice else [],
|
||||
attach_tickets=True,
|
||||
attach_ical=event.settings.mail_attach_ical and (
|
||||
not event.settings.mail_attach_ical_paid_only or
|
||||
is_free or
|
||||
order.valid_if_pending
|
||||
),
|
||||
attach_other_files=[a for a in [
|
||||
event.settings.get('mail_attachment_new_order', as_type=str, default='')[len('file://'):]
|
||||
] if a],
|
||||
)
|
||||
|
||||
|
||||
def _order_placed_email_attendee(event: Event, order: Order, position: OrderPosition, email_template, subject_template,
|
||||
log_entry: str, is_free=False):
|
||||
email_context = get_email_context(event=event, order=order, position=position)
|
||||
|
||||
try:
|
||||
position.send_mail(
|
||||
subject_template, email_template, email_context,
|
||||
log_entry,
|
||||
invoices=[],
|
||||
attach_tickets=True,
|
||||
attach_ical=event.settings.mail_attach_ical and (
|
||||
not event.settings.mail_attach_ical_paid_only or
|
||||
is_free or
|
||||
order.valid_if_pending
|
||||
),
|
||||
attach_other_files=[a for a in [
|
||||
event.settings.get('mail_attachment_new_order', as_type=str, default='')[len('file://'):]
|
||||
] if a],
|
||||
)
|
||||
except SendMailException:
|
||||
logger.exception('Order received email could not be sent to attendee')
|
||||
position.send_mail(
|
||||
subject_template, email_template, email_context,
|
||||
log_entry,
|
||||
invoices=[],
|
||||
attach_tickets=True,
|
||||
attach_ical=event.settings.mail_attach_ical and (
|
||||
not event.settings.mail_attach_ical_paid_only or
|
||||
is_free or
|
||||
order.valid_if_pending
|
||||
),
|
||||
attach_other_files=[a for a in [
|
||||
event.settings.get('mail_attachment_new_order', as_type=str, default='')[len('file://'):]
|
||||
] if a],
|
||||
)
|
||||
|
||||
|
||||
def _perform_order(event: Event, payment_requests: List[dict], position_ids: List[str],
|
||||
@@ -1476,13 +1474,10 @@ def send_expiry_warnings(sender, **kwargs):
|
||||
email_template = settings.mail_text_order_pending_warning
|
||||
email_subject = settings.mail_subject_order_pending_warning
|
||||
|
||||
try:
|
||||
o.send_mail(
|
||||
email_subject, email_template, email_context,
|
||||
'pretix.event.order.email.expire_warning_sent'
|
||||
)
|
||||
except SendMailException:
|
||||
logger.exception('Reminder email could not be sent')
|
||||
o.send_mail(
|
||||
email_subject, email_template, email_context,
|
||||
'pretix.event.order.email.expire_warning_sent'
|
||||
)
|
||||
|
||||
|
||||
@receiver(signal=periodic_task)
|
||||
@@ -1543,14 +1538,11 @@ def send_download_reminders(sender, **kwargs):
|
||||
email_template = event.settings.mail_text_download_reminder
|
||||
email_subject = event.settings.mail_subject_download_reminder
|
||||
email_context = get_email_context(event=event, order=o)
|
||||
try:
|
||||
o.send_mail(
|
||||
email_subject, email_template, email_context,
|
||||
'pretix.event.order.email.download_reminder_sent',
|
||||
attach_tickets=True
|
||||
)
|
||||
except SendMailException:
|
||||
logger.exception('Reminder email could not be sent')
|
||||
o.send_mail(
|
||||
email_subject, email_template, email_context,
|
||||
'pretix.event.order.email.download_reminder_sent',
|
||||
attach_tickets=True
|
||||
)
|
||||
|
||||
if event.settings.mail_send_download_reminder_attendee:
|
||||
for p in positions:
|
||||
@@ -1564,14 +1556,11 @@ def send_download_reminders(sender, **kwargs):
|
||||
email_template = event.settings.mail_text_download_reminder_attendee
|
||||
email_subject = event.settings.mail_subject_download_reminder_attendee
|
||||
email_context = get_email_context(event=event, order=o, position=p)
|
||||
try:
|
||||
o.send_mail(
|
||||
email_subject, email_template, email_context,
|
||||
'pretix.event.order.email.download_reminder_sent',
|
||||
attach_tickets=True, position=p
|
||||
)
|
||||
except SendMailException:
|
||||
logger.exception('Reminder email could not be sent to attendee')
|
||||
o.send_mail(
|
||||
email_subject, email_template, email_context,
|
||||
'pretix.event.order.email.download_reminder_sent',
|
||||
attach_tickets=True, position=p
|
||||
)
|
||||
|
||||
|
||||
def notify_user_changed_order(order, user=None, auth=None, invoices=[]):
|
||||
@@ -1579,13 +1568,10 @@ def notify_user_changed_order(order, user=None, auth=None, invoices=[]):
|
||||
email_template = order.event.settings.mail_text_order_changed
|
||||
email_context = get_email_context(event=order.event, order=order)
|
||||
email_subject = order.event.settings.mail_subject_order_changed
|
||||
try:
|
||||
order.send_mail(
|
||||
email_subject, email_template, email_context,
|
||||
'pretix.event.order.email.order_changed', user, auth=auth, invoices=invoices, attach_tickets=True,
|
||||
)
|
||||
except SendMailException:
|
||||
logger.exception('Order changed email could not be sent')
|
||||
order.send_mail(
|
||||
email_subject, email_template, email_context,
|
||||
'pretix.event.order.email.order_changed', user, auth=auth, invoices=invoices, attach_tickets=True,
|
||||
)
|
||||
|
||||
|
||||
class OrderChangeManager:
|
||||
@@ -1641,6 +1627,7 @@ class OrderChangeManager:
|
||||
ChangeValidUntilOperation = namedtuple('ChangeValidUntilOperation', ('position', 'valid_until'))
|
||||
AddBlockOperation = namedtuple('AddBlockOperation', ('position', 'block_name', 'ignore_from_quota_while_blocked'))
|
||||
RemoveBlockOperation = namedtuple('RemoveBlockOperation', ('position', 'block_name', 'ignore_from_quota_while_blocked'))
|
||||
ForceRecomputeOperation = namedtuple('ForceRecomputeOperation', tuple())
|
||||
|
||||
class AddPositionResult:
|
||||
_position: Optional[OrderPosition]
|
||||
@@ -1804,6 +1791,7 @@ class OrderChangeManager:
|
||||
positions = self.order.positions.select_related('item', 'item__tax_rule')
|
||||
ia = self._invoice_address
|
||||
tax_rules = self._current_tax_rules()
|
||||
self._operations.append(self.ForceRecomputeOperation())
|
||||
|
||||
for pos in positions:
|
||||
tax_rule = tax_rules.get(pos.pk, pos.tax_rule)
|
||||
@@ -2094,6 +2082,43 @@ class OrderChangeManager:
|
||||
)
|
||||
item_counts[item] += 1
|
||||
|
||||
# Detect removed add-ons and create RemoveOperations
|
||||
for cp, al in list(current_addons.items()):
|
||||
for k, v in al.items():
|
||||
input_num = input_addons[cp.id].get(k, 0)
|
||||
current_num = len(current_addons[cp].get(k, []))
|
||||
if input_num < current_num:
|
||||
for a in current_addons[cp][k][:current_num - input_num]:
|
||||
if a.canceled:
|
||||
continue
|
||||
is_unavailable = (
|
||||
# If an item is no longer available due to time, it should usually also be no longer
|
||||
# user-removable, because e.g. the stock has already been ordered.
|
||||
# We always pass has_voucher=True because if a product now requires a voucher, it usually does
|
||||
# not mean it should be unremovable for others.
|
||||
# This also prevents accidental removal through the UI because a hidden product will no longer
|
||||
# be part of the input.
|
||||
(a.variation and a.variation.unavailability_reason(has_voucher=True, subevent=a.subevent))
|
||||
or (a.variation and not a.variation.all_sales_channels and not a.variation.limit_sales_channels.contains(self.order.sales_channel))
|
||||
or a.item.unavailability_reason(has_voucher=True, subevent=a.subevent)
|
||||
or (
|
||||
not a.item.all_sales_channels and
|
||||
not a.item.limit_sales_channels.contains(self.order.sales_channel)
|
||||
)
|
||||
)
|
||||
if is_unavailable:
|
||||
# "Re-select" add-on
|
||||
selected_addons[cp.id, a.item.category_id][a.item_id, a.variation_id] += 1
|
||||
continue
|
||||
if a.checkins.filter(list__consider_tickets_used=True).exists():
|
||||
raise OrderError(
|
||||
error_messages['addon_already_checked_in'] % {
|
||||
'addon': str(a.item.name),
|
||||
}
|
||||
)
|
||||
self.cancel(a)
|
||||
item_counts[a.item] -= 1
|
||||
|
||||
# Check constraints on the add-on combinations
|
||||
for op in toplevel_op:
|
||||
item = op.item
|
||||
@@ -2126,41 +2151,6 @@ class OrderChangeManager:
|
||||
}
|
||||
)
|
||||
|
||||
# Detect removed add-ons and create RemoveOperations
|
||||
for cp, al in list(current_addons.items()):
|
||||
for k, v in al.items():
|
||||
input_num = input_addons[cp.id].get(k, 0)
|
||||
current_num = len(current_addons[cp].get(k, []))
|
||||
if input_num < current_num:
|
||||
for a in current_addons[cp][k][:current_num - input_num]:
|
||||
if a.canceled:
|
||||
continue
|
||||
is_unavailable = (
|
||||
# If an item is no longer available due to time, it should usually also be no longer
|
||||
# user-removable, because e.g. the stock has already been ordered.
|
||||
# We always pass has_voucher=True because if a product now requires a voucher, it usually does
|
||||
# not mean it should be unremovable for others.
|
||||
# This also prevents accidental removal through the UI because a hidden product will no longer
|
||||
# be part of the input.
|
||||
(a.variation and a.variation.unavailability_reason(has_voucher=True, subevent=a.subevent))
|
||||
or (a.variation and not a.variation.all_sales_channels and not a.variation.limit_sales_channels.contains(self.order.sales_channel))
|
||||
or a.item.unavailability_reason(has_voucher=True, subevent=a.subevent)
|
||||
or (
|
||||
not item.all_sales_channels and
|
||||
not item.limit_sales_channels.contains(self.order.sales_channel)
|
||||
)
|
||||
)
|
||||
if is_unavailable:
|
||||
continue
|
||||
if a.checkins.filter(list__consider_tickets_used=True).exists():
|
||||
raise OrderError(
|
||||
error_messages['addon_already_checked_in'] % {
|
||||
'addon': str(a.item.name),
|
||||
}
|
||||
)
|
||||
self.cancel(a)
|
||||
item_counts[a.item] -= 1
|
||||
|
||||
for item, count in item_counts.items():
|
||||
if count == 0:
|
||||
continue
|
||||
@@ -2461,6 +2451,15 @@ class OrderChangeManager:
|
||||
))
|
||||
else:
|
||||
gc.transactions.create(value=-position.price, order=self.order, acceptor=self.order.event.organizer)
|
||||
gc.log_action(
|
||||
action='pretix.giftcards.transaction.manual',
|
||||
user=self.user,
|
||||
auth=self.auth,
|
||||
data={
|
||||
'value': -position.price,
|
||||
'acceptor_id': self.order.event.organizer.id
|
||||
}
|
||||
)
|
||||
|
||||
for m in position.granted_memberships.with_usages().all():
|
||||
m.canceled = True
|
||||
@@ -2478,6 +2477,15 @@ class OrderChangeManager:
|
||||
))
|
||||
else:
|
||||
gc.transactions.create(value=-opa.position.price, order=self.order, acceptor=self.order.event.organizer)
|
||||
gc.log_action(
|
||||
action='pretix.giftcards.transaction.manual',
|
||||
user=self.user,
|
||||
auth=self.auth,
|
||||
data={
|
||||
'value': -opa.position.price,
|
||||
'acceptor_id': self.order.event.organizer.id
|
||||
}
|
||||
)
|
||||
|
||||
for m in opa.granted_memberships.with_usages().all():
|
||||
m.canceled = True
|
||||
@@ -2640,6 +2648,10 @@ class OrderChangeManager:
|
||||
except BlockedTicketSecret.DoesNotExist:
|
||||
pass
|
||||
# todo: revoke list handling
|
||||
elif isinstance(op, self.ForceRecomputeOperation):
|
||||
self.order.log_action('pretix.event.order.changed.recomputed', user=self.user, auth=self.auth, data={})
|
||||
else:
|
||||
raise TypeError(f"Unknown operation {type(op)}")
|
||||
|
||||
for p in secret_dirty:
|
||||
assign_ticket_secret(
|
||||
@@ -2694,7 +2706,10 @@ class OrderChangeManager:
|
||||
fees.append(new_fee)
|
||||
|
||||
changed_by_rounding = set(apply_rounding(
|
||||
self.order.tax_rounding_mode, self.event.currency, [p for p in split_positions if not p.canceled] + fees
|
||||
self.order.tax_rounding_mode,
|
||||
self._invoice_address,
|
||||
self.event.currency,
|
||||
[p for p in split_positions if not p.canceled] + fees
|
||||
))
|
||||
split_order.total = sum([p.price for p in split_positions if not p.canceled])
|
||||
|
||||
@@ -2716,7 +2731,10 @@ class OrderChangeManager:
|
||||
fee.delete()
|
||||
|
||||
changed_by_rounding |= set(apply_rounding(
|
||||
self.order.tax_rounding_mode, self.event.currency, [p for p in split_positions if not p.canceled] + fees
|
||||
self.order.tax_rounding_mode,
|
||||
self._invoice_address,
|
||||
self.event.currency,
|
||||
[p for p in split_positions if not p.canceled] + fees
|
||||
))
|
||||
split_order.total = sum([p.price for p in split_positions if not p.canceled]) + sum([f.value for f in fees])
|
||||
|
||||
@@ -2833,7 +2851,12 @@ class OrderChangeManager:
|
||||
if fee_changed:
|
||||
fees = list(self.order.fees.all())
|
||||
|
||||
changed = apply_rounding(self.order.tax_rounding_mode, self.order.event.currency, [*positions, *fees])
|
||||
changed = apply_rounding(
|
||||
self.order.tax_rounding_mode,
|
||||
self._invoice_address,
|
||||
self.order.event.currency,
|
||||
[*positions, *fees]
|
||||
)
|
||||
for l in changed:
|
||||
if isinstance(l, OrderPosition):
|
||||
l.save(update_fields=[
|
||||
@@ -3131,7 +3154,10 @@ def _try_auto_refund(order, auto_refund=True, manual_refund=False, allow_partial
|
||||
customer=order.customer,
|
||||
testmode=order.testmode
|
||||
)
|
||||
giftcard.log_action('pretix.giftcards.created', data={})
|
||||
giftcard.log_action(
|
||||
action='pretix.giftcards.created',
|
||||
data={}
|
||||
)
|
||||
r = order.refunds.create(
|
||||
order=order,
|
||||
payment=None,
|
||||
@@ -3269,8 +3295,12 @@ def change_payment_provider(order: Order, payment_provider, amount=None, new_pay
|
||||
|
||||
positions = list(order.positions.all())
|
||||
fees = list(order.fees.all())
|
||||
try:
|
||||
ia = order.invoice_address
|
||||
except InvoiceAddress.DoesNotExist:
|
||||
ia = None
|
||||
rounding_changed = set(apply_rounding(
|
||||
order.tax_rounding_mode, order.event.currency, [*positions, *[f for f in fees if f.pk != fee.pk]]
|
||||
order.tax_rounding_mode, ia, order.event.currency, [*positions, *[f for f in fees if f.pk != fee.pk]]
|
||||
))
|
||||
total_without_fee = sum(c.price for c in positions) + sum(f.value for f in fees if f.pk != fee.pk)
|
||||
pending_sum_without_fee = max(Decimal("0.00"), total_without_fee - already_paid)
|
||||
@@ -3295,7 +3325,7 @@ def change_payment_provider(order: Order, payment_provider, amount=None, new_pay
|
||||
fee = None
|
||||
|
||||
rounding_changed |= set(apply_rounding(
|
||||
order.tax_rounding_mode, order.event.currency, [*positions, *fees]
|
||||
order.tax_rounding_mode, ia, order.event.currency, [*positions, *fees]
|
||||
))
|
||||
for l in rounding_changed:
|
||||
if isinstance(l, OrderPosition):
|
||||
@@ -3414,7 +3444,17 @@ def signal_listener_issue_giftcards(sender: Event, order: Order, **kwargs):
|
||||
currency=sender.currency, issued_in=p, testmode=order.testmode,
|
||||
expires=sender.organizer.default_gift_card_expiry,
|
||||
)
|
||||
gc.transactions.create(value=p.price - issued, order=order, acceptor=sender.organizer)
|
||||
gc.log_action(
|
||||
action='pretix.giftcards.created',
|
||||
)
|
||||
trans = gc.transactions.create(value=p.price - issued, order=order, acceptor=sender.organizer)
|
||||
gc.log_action(
|
||||
action='pretix.giftcards.transaction.manual',
|
||||
data={
|
||||
'value': trans.value,
|
||||
'acceptor_id': order.event.organizer.id,
|
||||
}
|
||||
)
|
||||
any_giftcards = True
|
||||
p.secret = gc.secret
|
||||
p.save(update_fields=['secret'])
|
||||
|
||||
@@ -211,7 +211,8 @@ def apply_discounts(event: Event, sales_channel: Union[str, SalesChannel],
|
||||
return [new_prices.get(idx, (p[3], None)) for idx, p in enumerate(positions)]
|
||||
|
||||
|
||||
def apply_rounding(rounding_mode: Literal["line", "sum_by_net", "sum_by_net_keep_gross"], currency: str,
|
||||
def apply_rounding(rounding_mode: Literal["line", "sum_by_net", "sum_by_net_only_business", "sum_by_net_keep_gross"],
|
||||
invoice_address: Optional[InvoiceAddress], currency: str,
|
||||
lines: List[Union[OrderPosition, CartPosition, OrderFee]]) -> list:
|
||||
"""
|
||||
Given a list of order positions / cart positions / order fees (may be mixed), applies the given rounding mode
|
||||
@@ -226,11 +227,17 @@ def apply_rounding(rounding_mode: Literal["line", "sum_by_net", "sum_by_net_keep
|
||||
When rounding mode is set to ``"sum_by_net"``, the gross prices and tax values of the individual lines will be
|
||||
adjusted such that the per-taxrate/taxcode subtotal is rounded correctly. The net prices will stay constant.
|
||||
|
||||
:param rounding_mode: One of ``"line"``, ``"sum_by_net"``, or ``"sum_by_net_keep_gross"``.
|
||||
:param rounding_mode: One of ``"line"``, ``"sum_by_net"``, ``"sum_by_net_only_business"``, or ``"sum_by_net_keep_gross"``.
|
||||
:param invoice_address: The invoice address, or ``None``
|
||||
:param currency: Currency that will be used to determine rounding precision
|
||||
:param lines: List of order/cart contents
|
||||
:return: Collection of ``lines`` members that have been changed and may need to be persisted to the database.
|
||||
"""
|
||||
if rounding_mode == "sum_by_net_only_business":
|
||||
if invoice_address and invoice_address.is_business:
|
||||
rounding_mode = "sum_by_net"
|
||||
else:
|
||||
rounding_mode = "line"
|
||||
|
||||
def _key(line):
|
||||
return (line.tax_rate, line.tax_code or "")
|
||||
|
||||
@@ -48,7 +48,7 @@ from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from pretix.base.i18n import language
|
||||
from pretix.base.models import CachedFile, Event, User, cachedfile_name
|
||||
from pretix.base.services.mail import SendMailException, mail
|
||||
from pretix.base.services.mail import mail
|
||||
from pretix.base.services.tasks import ProfiledEventTask
|
||||
from pretix.base.shredder import ShredError
|
||||
from pretix.celery_app import app
|
||||
@@ -171,21 +171,18 @@ def shred(self, event: Event, fileid: str, confirm_code: str, user: int=None, lo
|
||||
|
||||
if user:
|
||||
with language(user.locale):
|
||||
try:
|
||||
mail(
|
||||
user.email,
|
||||
_('Data shredding completed'),
|
||||
'pretixbase/email/shred_completed.txt',
|
||||
{
|
||||
'user': user,
|
||||
'organizer': event.organizer.name,
|
||||
'event': str(event.name),
|
||||
'start_time': date_format(parse(indexdata['time']).astimezone(event.timezone), 'SHORT_DATETIME_FORMAT'),
|
||||
'shredders': ', '.join([str(s.verbose_name) for s in shredders])
|
||||
},
|
||||
event=None,
|
||||
user=user,
|
||||
locale=user.locale,
|
||||
)
|
||||
except SendMailException:
|
||||
pass # Already logged
|
||||
mail(
|
||||
user.email,
|
||||
_('Data shredding completed'),
|
||||
'pretixbase/email/shred_completed.txt',
|
||||
{
|
||||
'user': user,
|
||||
'organizer': event.organizer.name,
|
||||
'event': str(event.name),
|
||||
'start_time': date_format(parse(indexdata['time']).astimezone(event.timezone), 'SHORT_DATETIME_FORMAT'),
|
||||
'shredders': ', '.join([str(s.verbose_name) for s in shredders])
|
||||
},
|
||||
event=None,
|
||||
user=user,
|
||||
locale=user.locale,
|
||||
)
|
||||
|
||||
@@ -81,6 +81,7 @@ from pretix.helpers.countries import CachedCountries, pycountry_add
|
||||
ROUNDING_MODES = (
|
||||
('line', _('Compute taxes for every line individually')),
|
||||
('sum_by_net', _('Compute taxes based on net total')),
|
||||
('sum_by_net_only_business', _('For business customers, compute taxes based on net total. For individuals, use line-based rounding')),
|
||||
('sum_by_net_keep_gross', _('Compute taxes based on net total with stable gross prices')),
|
||||
# We could also have sum_by_gross, but we're not aware of any use-cases for it
|
||||
)
|
||||
@@ -2947,6 +2948,28 @@ If you did not request a new password, please ignore this email.
|
||||
|
||||
Best regards,
|
||||
|
||||
Your {organizer} team""")) # noqa: W291
|
||||
},
|
||||
'mail_subject_customer_security_notice': {
|
||||
'type': LazyI18nString,
|
||||
'default': LazyI18nString.from_gettext(gettext_noop("Changes to your account at {organizer}")),
|
||||
},
|
||||
'mail_text_customer_security_notice': {
|
||||
'type': LazyI18nString,
|
||||
'default': LazyI18nString.from_gettext(gettext_noop("""Hello {name},
|
||||
|
||||
the following change has been made to your account at {organizer}:
|
||||
|
||||
{message}
|
||||
|
||||
You can review and change your account settings here:
|
||||
|
||||
{url}
|
||||
|
||||
If this change was not performed by you, please contact us immediately.
|
||||
|
||||
Best regards,
|
||||
|
||||
Your {organizer} team""")) # noqa: W291
|
||||
},
|
||||
'smtp_use_custom': {
|
||||
|
||||
@@ -51,7 +51,7 @@ from pretix.api.serializers.waitinglist import WaitingListSerializer
|
||||
from pretix.base.i18n import LazyLocaleException
|
||||
from pretix.base.models import (
|
||||
CachedCombinedTicket, CachedTicket, Event, InvoiceAddress, OrderPayment,
|
||||
OrderPosition, OrderRefund, QuestionAnswer,
|
||||
OrderPosition, OrderRefund, OutgoingMail, QuestionAnswer,
|
||||
)
|
||||
from pretix.base.services.invoices import invoice_pdf_task
|
||||
from pretix.base.signals import register_data_shredders
|
||||
@@ -329,6 +329,10 @@ class EmailAddressShredder(BaseDataShredder):
|
||||
sleep_time=2,
|
||||
)
|
||||
|
||||
slow_delete(
|
||||
OutgoingMail.objects.filter(event=self.event)
|
||||
)
|
||||
|
||||
for o in _progress_helper(qs_orders, progress_callback, qs_op_cnt, total):
|
||||
changed = bool(o.email) or bool(o.customer)
|
||||
o.email = None
|
||||
|
||||
@@ -944,32 +944,40 @@ As with all event-plugin signals, the ``sender`` keyword argument will contain t
|
||||
|
||||
email_filter = EventPluginSignal()
|
||||
"""
|
||||
Arguments: ``message``, ``order``, ``user``
|
||||
Arguments: ``message``, ``order``, ``user``, ``outgoing_mail``
|
||||
|
||||
This signal allows you to implement a middleware-style filter on all outgoing emails. You are expected to
|
||||
return a (possibly modified) copy of the message object passed to you.
|
||||
|
||||
As with all event-plugin signals, the ``sender`` keyword argument will contain the event.
|
||||
The ``message`` argument will contain an ``EmailMultiAlternatives`` object.
|
||||
The ``outgoing_mail`` argument will contain the ``OutgoingMail`` model instance. Note that the ``message`` object
|
||||
might have newer information if a previous plugin already modified the email.
|
||||
If the email is associated with a specific order, the ``order`` argument will be passed as well, otherwise
|
||||
it will be ``None``.
|
||||
If the email is associated with a specific user, e.g. a notification email, the ``user`` argument will be passed as
|
||||
well, otherwise it will be ``None``.
|
||||
|
||||
You can raise ``WithholdMailException`` to prevent the email from being sent, e.g. when implementing rate limiting.
|
||||
"""
|
||||
|
||||
global_email_filter = GlobalSignal()
|
||||
"""
|
||||
Arguments: ``message``, ``order``, ``user``, ``customer``, ``organizer``
|
||||
Arguments: ``message``, ``order``, ``user``, ``customer``, ``organizer``, ``outgoing_mail``
|
||||
|
||||
This signal allows you to implement a middleware-style filter on all outgoing emails. You are expected to
|
||||
return a (possibly modified) copy of the message object passed to you.
|
||||
|
||||
This signal is called on all events and even if there is no known event. ``sender`` is an event or None.
|
||||
The ``message`` argument will contain an ``EmailMultiAlternatives`` object.
|
||||
The ``outgoing_mail`` argument will contain the ``OutgoingMail`` model instance. Note that the ``message`` object
|
||||
might have newer information if a previous plugin already modified the email.
|
||||
If the email is associated with a specific order, the ``order`` argument will be passed as well, otherwise
|
||||
it will be ``None``.
|
||||
If the email is associated with a specific user, e.g. a notification email, the ``user`` argument will be passed as
|
||||
well, otherwise it will be ``None``.
|
||||
|
||||
You can raise ``WithholdMailException`` to prevent the email from being sent, e.g. when implementing rate limiting.
|
||||
"""
|
||||
|
||||
|
||||
|
||||
@@ -8,9 +8,6 @@
|
||||
<h1>{% trans "Not found" %}</h1>
|
||||
<p>{% trans "I'm afraid we could not find the the resource you requested." %}</p>
|
||||
<p>{{ exception }}</p>
|
||||
<p class="links">
|
||||
<a id='goback' href='#'>{% trans "Take a step back" %}</a>
|
||||
</p>
|
||||
{% if request.user.is_staff and not staff_session %}
|
||||
<form action="{% url 'control:user.sudo' %}?next={{ request.path|add:"?"|add:request.GET.urlencode|urlencode }}" method="post">
|
||||
<p>
|
||||
|
||||
@@ -156,7 +156,7 @@ def safelink_callback(attrs, new=False):
|
||||
Makes sure that all links to a different domain are passed through a redirection handler
|
||||
to ensure there's no passing of referers with secrets inside them.
|
||||
"""
|
||||
url = attrs.get((None, 'href'), '/')
|
||||
url = html.unescape(attrs.get((None, 'href'), '/'))
|
||||
if not url_has_allowed_host_and_scheme(url, allowed_hosts=None) and not url.startswith('mailto:') and not url.startswith('tel:'):
|
||||
signer = signing.Signer(salt='safe-redirect')
|
||||
attrs[None, 'href'] = reverse('redirect') + '?url=' + urllib.parse.quote(signer.sign(url))
|
||||
|
||||
@@ -95,6 +95,7 @@ class OrganizerSlugBanlistValidator(BanlistValidator):
|
||||
'csp_report',
|
||||
'widget',
|
||||
'lead',
|
||||
'scheduling',
|
||||
]
|
||||
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
# <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
import pycountry
|
||||
from django.conf import settings
|
||||
from django.http import JsonResponse
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.utils.translation import gettext, pgettext, pgettext_lazy
|
||||
@@ -29,6 +30,7 @@ from django_scopes import scope
|
||||
from pretix.base.addressvalidation import (
|
||||
COUNTRIES_WITH_STREET_ZIPCODE_AND_CITY_REQUIRED,
|
||||
)
|
||||
from pretix.base.i18n import language
|
||||
from pretix.base.invoicing.transmission import get_transmission_types
|
||||
from pretix.base.models import Organizer
|
||||
from pretix.base.models.tax import VAT_ID_COUNTRIES
|
||||
@@ -89,7 +91,7 @@ def _info(cc):
|
||||
}
|
||||
|
||||
|
||||
def address_form(request):
|
||||
def _address_form(request):
|
||||
cc = request.GET.get("country", "DE")
|
||||
info = _info(cc)
|
||||
|
||||
@@ -157,4 +159,15 @@ def address_form(request):
|
||||
# The help text explains that it is optional, so we want to hide that if it is required
|
||||
info["vat_id"]["helptext_visible"] = False
|
||||
|
||||
return info
|
||||
|
||||
|
||||
def address_form(request):
|
||||
locale = request.GET.get('locale')
|
||||
if locale in dict(settings.LANGUAGES):
|
||||
with language(locale):
|
||||
info = _address_form(request)
|
||||
else:
|
||||
info = _address_form(request)
|
||||
|
||||
return JsonResponse(info)
|
||||
|
||||
@@ -867,6 +867,11 @@ class TaxSettingsForm(EventSettingsValidationMixin, SettingsForm):
|
||||
"The gross price of some products may be changed to ensure correct rounding, while the net "
|
||||
"prices will be kept as configured. This may cause the actual payment amount to differ."
|
||||
),
|
||||
"sum_by_net_only_business": _(
|
||||
"Same as above, but only applied to business customers. Line-based rounding will be used for consumers. "
|
||||
"Recommended when e-invoicing is only used for business customers and consumers do not receive "
|
||||
"invoices. This can cause the payment amount to change when the invoice address is changed."
|
||||
),
|
||||
"sum_by_net_keep_gross": _(
|
||||
"Recommended for e-invoicing when you primarily sell to consumers. "
|
||||
"The gross or net price of some products may be changed automatically to ensure correct "
|
||||
|
||||
@@ -57,8 +57,9 @@ from pretix.base.forms.widgets import (
|
||||
from pretix.base.models import (
|
||||
Checkin, CheckinList, Device, Event, EventMetaProperty, EventMetaValue,
|
||||
Gate, Invoice, InvoiceAddress, Item, Order, OrderPayment, OrderPosition,
|
||||
OrderRefund, Organizer, Question, QuestionAnswer, Quota, SalesChannel,
|
||||
SubEvent, SubEventMetaValue, Team, TeamAPIToken, TeamInvite, Voucher,
|
||||
OrderRefund, Organizer, OutgoingMail, Question, QuestionAnswer, Quota,
|
||||
SalesChannel, SubEvent, SubEventMetaValue, Team, TeamAPIToken, TeamInvite,
|
||||
Voucher,
|
||||
)
|
||||
from pretix.base.signals import register_payment_providers
|
||||
from pretix.base.timeframes import (
|
||||
@@ -2815,3 +2816,61 @@ class DeviceFilterForm(FilterForm):
|
||||
qs = qs.order_by('-device_id')
|
||||
|
||||
return qs
|
||||
|
||||
|
||||
class OutgoingMailFilterForm(FilterForm):
|
||||
orders = {
|
||||
'date': 'created',
|
||||
'-date': '-created',
|
||||
}
|
||||
query = forms.CharField(
|
||||
label=_('Search email address or subject'),
|
||||
widget=forms.TextInput(attrs={
|
||||
'placeholder': _('Search email address or subject'),
|
||||
}),
|
||||
required=False
|
||||
)
|
||||
event = forms.ModelChoiceField(
|
||||
queryset=Event.objects.none(),
|
||||
label=_('Event'),
|
||||
empty_label=_('All events'),
|
||||
required=False,
|
||||
)
|
||||
status = forms.ChoiceField(
|
||||
label=_('Status'),
|
||||
choices=[
|
||||
('', _('All')),
|
||||
*OutgoingMail.STATUS_CHOICES,
|
||||
],
|
||||
required=False
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
request = kwargs.pop('request')
|
||||
super().__init__(*args, **kwargs)
|
||||
self.fields['event'].queryset = request.organizer.events.all()
|
||||
|
||||
def filter_qs(self, qs):
|
||||
fdata = self.cleaned_data
|
||||
|
||||
if fdata.get('query'):
|
||||
query = fdata.get('query')
|
||||
qs = qs.filter(
|
||||
Q(to__containsstring=query.lower())
|
||||
| Q(cc__containsstring=query.lower())
|
||||
| Q(bcc__containsstring=query.lower())
|
||||
| Q(subject__icontains=query)
|
||||
)
|
||||
|
||||
if fdata.get('event'):
|
||||
qs = qs.filter(event=fdata['event'])
|
||||
|
||||
if fdata.get('status'):
|
||||
qs = qs.filter(status=fdata['status'])
|
||||
|
||||
if fdata.get('ordering'):
|
||||
qs = qs.order_by(self.get_order_by())
|
||||
else:
|
||||
qs = qs.order_by("-created", "-pk")
|
||||
|
||||
return qs
|
||||
|
||||
@@ -585,6 +585,7 @@ class MailSettingsForm(SettingsForm):
|
||||
help_text=''.join([
|
||||
str(_("All emails will be sent to this address as a Bcc copy.")),
|
||||
str(_("You can specify multiple recipients separated by commas.")),
|
||||
str(_("Sensitive emails like password resets will not be sent in Bcc.")),
|
||||
]),
|
||||
validators=[multimail_validate],
|
||||
required=False,
|
||||
@@ -634,6 +635,16 @@ class MailSettingsForm(SettingsForm):
|
||||
required=False,
|
||||
widget=I18nMarkdownTextarea,
|
||||
)
|
||||
mail_subject_customer_security_notice = I18nFormField(
|
||||
label=_("Subject"),
|
||||
required=False,
|
||||
widget=I18nTextInput,
|
||||
)
|
||||
mail_text_customer_security_notice = I18nFormField(
|
||||
label=_("Text"),
|
||||
required=False,
|
||||
widget=I18nMarkdownTextarea,
|
||||
)
|
||||
|
||||
base_context = {
|
||||
'mail_text_customer_registration': ['customer', 'url'],
|
||||
@@ -642,6 +653,8 @@ class MailSettingsForm(SettingsForm):
|
||||
'mail_subject_customer_email_change': ['customer', 'url'],
|
||||
'mail_text_customer_reset': ['customer', 'url'],
|
||||
'mail_subject_customer_reset': ['customer', 'url'],
|
||||
'mail_text_customer_security_notice': ['customer', 'url', 'message'],
|
||||
'mail_subject_customer_security_notice': ['customer', 'url', 'message'],
|
||||
}
|
||||
|
||||
def _get_sample_context(self, base_parameters):
|
||||
@@ -655,6 +668,9 @@ class MailSettingsForm(SettingsForm):
|
||||
'presale:organizer.customer.activate'
|
||||
) + '?token=' + get_random_string(30)
|
||||
|
||||
if 'message' in base_parameters:
|
||||
placeholders['message'] = _('Your password has been changed.')
|
||||
|
||||
if 'customer' in base_parameters:
|
||||
placeholders['name'] = pgettext_lazy('person_name_sample', 'John Doe')
|
||||
name_scheme = PERSON_NAME_SCHEMES[self.organizer.settings.name_scheme]
|
||||
|
||||
@@ -170,6 +170,12 @@ class OrderFeeAdded(OrderChangeLogEntryType):
|
||||
plain = _('A fee has been added')
|
||||
|
||||
|
||||
@log_entry_types.new()
|
||||
class OrderRecomputed(OrderChangeLogEntryType):
|
||||
action_type = 'pretix.event.order.changed.recomputed'
|
||||
plain = _('Taxes and rounding have been recomputed')
|
||||
|
||||
|
||||
@log_entry_types.new()
|
||||
class OrderFeeChanged(OrderChangeLogEntryType):
|
||||
action_type = 'pretix.event.order.changed.feevalue'
|
||||
@@ -699,6 +705,8 @@ class CoreUserImpersonatedLogEntryType(UserImpersonatedLogEntryType):
|
||||
'pretix.organizer.export.schedule.deleted': _('A scheduled export has been deleted.'),
|
||||
'pretix.organizer.export.schedule.executed': _('A scheduled export has been executed.'),
|
||||
'pretix.organizer.export.schedule.failed': _('A scheduled export has failed: {reason}.'),
|
||||
'pretix.organizer.outgoingmails.retried': _('Failed emails have been scheduled to be retried.'),
|
||||
'pretix.organizer.outgoingmails.aborted': _('Queued emails have been aborted.'),
|
||||
'pretix.giftcards.acceptance.added': _('Gift card acceptance for another organizer has been added.'),
|
||||
'pretix.giftcards.acceptance.removed': _('Gift card acceptance for another organizer has been removed.'),
|
||||
'pretix.giftcards.acceptance.acceptor.invited': _('A new gift card acceptor has been invited.'),
|
||||
@@ -793,6 +801,8 @@ class CoreUserImpersonatedLogEntryType(UserImpersonatedLogEntryType):
|
||||
'pretix.giftcards.created': _('The gift card has been created.'),
|
||||
'pretix.giftcards.modified': _('The gift card has been changed.'),
|
||||
'pretix.giftcards.transaction.manual': _('A manual transaction has been performed.'),
|
||||
'pretix.giftcards.transaction.payment': _('A payment has been performed.'),
|
||||
'pretix.giftcards.transaction.refund': _('A refund has been performed. '),
|
||||
'pretix.team.token.created': _('The token "{name}" has been created.'),
|
||||
'pretix.team.token.deleted': _('The token "{name}" has been revoked.'),
|
||||
'pretix.event.checkin.reset': _('The check-in and print log state has been reset.')
|
||||
|
||||
@@ -679,6 +679,15 @@ def get_organizer_navigation(request):
|
||||
'active': (url.url_name == 'organizer.datasync.failedjobs'),
|
||||
}])
|
||||
|
||||
nav.append({
|
||||
'label': _('Outgoing emails'),
|
||||
'url': reverse('control:organizer.outgoingmails', kwargs={
|
||||
'organizer': request.organizer.slug,
|
||||
}),
|
||||
'active': 'organizer.outgoingmail' in url.url_name,
|
||||
'icon': 'send',
|
||||
})
|
||||
|
||||
merge_in(nav, sorted(
|
||||
sum((list(a[1]) for a in nav_organizer.send(request.organizer, request=request, organizer=request.organizer)),
|
||||
[]),
|
||||
|
||||
@@ -65,6 +65,9 @@
|
||||
|
||||
{% blocktrans asvar title_reset %}Customer account password reset{% endblocktrans %}
|
||||
{% include "pretixcontrol/event/mail_settings_fragment.html" with pid="reset" title=title_reset items="mail_subject_customer_reset,mail_text_customer_reset" %}
|
||||
|
||||
{% blocktrans asvar title_security_notice %}Customer account security notification{% endblocktrans %}
|
||||
{% include "pretixcontrol/event/mail_settings_fragment.html" with pid="security_notice" title=title_security_notice items="mail_subject_customer_security_notice,mail_text_customer_security_notice" %}
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,222 @@
|
||||
{% extends "pretixcontrol/organizers/base.html" %}
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 %}
|
||||
{% load urlreplace %}
|
||||
{% load icon %}
|
||||
{% load compress %}
|
||||
{% load static %}
|
||||
{% block inner %}
|
||||
<h1>
|
||||
{% trans "Outgoing email" %}
|
||||
</h1>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">{% trans "Email details" %}</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div class="row">
|
||||
<div class="col-lg-7 col-md-12">
|
||||
|
||||
<dl class="dl-horizontal">
|
||||
<dt>{% trans "From" context "email" %}</dt>
|
||||
<dd>{{ sender }}</dd>
|
||||
<dt>{% trans "To" context "email" %}</dt>
|
||||
<dd>{{ mail.to|join:", " }}</dd>
|
||||
{% if mail.cc %}
|
||||
<dt>{% trans "Cc" context "email" %}</dt>
|
||||
<dd>{{ mail.cc|join:", " }}</dd>
|
||||
{% endif %}
|
||||
{% if mail.bcc %}
|
||||
<dt>{% trans "Bcc" context "email" %}</dt>
|
||||
<dd>{{ mail.bcc|join:", " }}</dd>
|
||||
{% endif %}
|
||||
<dt>{% trans "Subject" %}</dt>
|
||||
<dd>{{ mail.subject }}</dd>
|
||||
<dt>{% trans "Status" %}</dt>
|
||||
<dd>
|
||||
{% if mail.status == "queued" %}
|
||||
<span class="label label-info">{% icon "clock-o" %} {% trans "queued" %}</span>
|
||||
{% elif mail.status == "inflight" %}
|
||||
<span class="label label-info">{% icon "send" %} {% trans "being sent" %}</span>
|
||||
{% elif mail.status == "awaiting_retry" %}
|
||||
<span class="label label-warning">{% icon "repeat" %} {% trans "will be retried" %}</span>
|
||||
{% elif mail.status == "failed" %}
|
||||
<span class="label label-danger">{% icon "warning" %} {% trans "failed" %}</span>
|
||||
{% elif mail.status == "bounced" %}
|
||||
<span class="label label-danger">{% icon "exclamation-circle" %} {% trans "bounced" %}</span>
|
||||
{% elif mail.status == "withheld" %}
|
||||
<span class="label label-warning">{% icon "ban" %} {% trans "withheld" %}</span>
|
||||
{% elif mail.status == "aborted" %}
|
||||
<span class="label label-danger">{% icon "ban" %} {% trans "aborted" %}</span>
|
||||
{% elif mail.status == "sent" %}
|
||||
<span class="label label-success">{% icon "check" %} {% trans "sent" %}</span>
|
||||
{% endif %}
|
||||
</dd>
|
||||
<dt>{% trans "Creation" %}</dt>
|
||||
<dd>{{ mail.created|date:"SHORT_DATETIME_FORMAT" }}</dd>
|
||||
{% if mail.sent %}
|
||||
<dt>{% trans "Sent" %}</dt>
|
||||
<dd>{{ mail.sent|date:"SHORT_DATETIME_FORMAT" }}</dd>
|
||||
{% endif %}
|
||||
{% if mail.retry_after and mail.status == "awaiting_retry" %}
|
||||
<dt>{% trans "Next attempt (estimate)" %}</dt>
|
||||
<dd>{{ mail.retry_after|date:"SHORT_DATETIME_FORMAT" }}</dd>
|
||||
{% endif %}
|
||||
{% if mail.event %}
|
||||
<dt>{% trans "Event" %}</dt>
|
||||
<dd>
|
||||
<a href="{% url "control:event.index" organizer=request.organizer.slug event=mail.event.slug %}">
|
||||
{{ mail.event }}
|
||||
</a>
|
||||
</dd>
|
||||
{% endif %}
|
||||
{% if mail.order %}
|
||||
<dt>{% trans "Order" %}</dt>
|
||||
<dd>
|
||||
<a href="{% url "control:event.order" organizer=request.organizer.slug event=mail.event.slug code=mail.order.code %}">
|
||||
{{ mail.order.code }}</a>{% if mail.orderposition %}-
|
||||
{{ mail.orderposition.positionid }}{% endif %}
|
||||
</dd>
|
||||
{% endif %}
|
||||
{% if mail.customer %}
|
||||
<dt>{% trans "Customer" %}</dt>
|
||||
<dd>
|
||||
{% icon "user fa-fw" %}
|
||||
<a href="{% url "control:organizer.customer" organizer=request.organizer.slug customer=mail.customer.identifier %}">
|
||||
{{ mail.customer }}
|
||||
</a>
|
||||
</dd>
|
||||
{% endif %}
|
||||
</dl>
|
||||
</div>
|
||||
{% if mail.actual_attachments %}
|
||||
<div class="col-lg-5 col-md-12">
|
||||
<strong>{% trans "Attachments" %}</strong><br>
|
||||
<ul class="list-unstyled">
|
||||
{% for a in mail.actual_attachments %}
|
||||
<li>
|
||||
{% if a.type == "text/calendar" %}
|
||||
{% icon "calendar-plus-o fa-fw" %}
|
||||
{% elif a.type == "application/pdf" %}
|
||||
{% icon "file-pdf-o fa-fw" %}
|
||||
{% elif "image/" in a.type %}
|
||||
{% icon "file-image-o fa-fw" %}
|
||||
{% elif "msword" in a.type or "document" in a.type %}
|
||||
{% icon "file-word-o fa-fw" %}
|
||||
{% elif "excel" in a.type or "spreadsheet" in a.type %}
|
||||
{% icon "file-excel-o fa-fw" %}
|
||||
{% elif "powerpoint" in a.type or "presentation" in a.type %}
|
||||
{% icon "file-powerpoint-o fa-fw" %}
|
||||
{% elif "pkpass" in a.type %}
|
||||
{% icon "qrcode fa-fw" %}
|
||||
{% else %}
|
||||
{% icon "file-o fa-fw" %}
|
||||
{% endif %}
|
||||
{{ a.name }}
|
||||
<span class="text-muted">
|
||||
({{ a.size|filesizeformat }})
|
||||
</span>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<ul class="nav nav-tabs" role="tablist">
|
||||
{% if mail.is_failed %}
|
||||
<li role="presentation" class="active">
|
||||
<a href="#tab-error" role="tab" data-toggle="tab">
|
||||
<span class="fa fa-warning"></span>
|
||||
{% trans "Error" %}
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if mail.body_html %}
|
||||
<li role="presentation"
|
||||
{% if not mail.is_failed %}class="active"{% endif %}>
|
||||
<a href="#tab-html" role="tab" data-toggle="tab">
|
||||
<span class="fa fa-eye"></span>
|
||||
{% trans "HTML content" %}
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
<li role="presentation"
|
||||
{% if not mail.is_failed and not mail.body_html %}class="active"{% endif %}>
|
||||
<a href="#tab-text" role="tab" data-toggle="tab">
|
||||
<span class="fa fa-file-text-o"></span>
|
||||
{% trans "Text content" %}
|
||||
</a>
|
||||
</li>
|
||||
<li role="presentation">
|
||||
<a href="#tab-headers" role="tab" data-toggle="tab">
|
||||
<span class="fa fa-code"></span>
|
||||
{% trans "Headers" %}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="tab-content">
|
||||
{% if mail.is_failed %}
|
||||
<div role="tabpanel" class="tab-pane active" id="tab-error">
|
||||
<strong>
|
||||
{{ mail.error }}
|
||||
</strong>
|
||||
<pre>{{ mail.error_detail }}</pre>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if mail.body_html %}
|
||||
<div role="tabpanel"
|
||||
class="tab-pane {% if not mail.is_failed %}active{% endif %}"
|
||||
id="tab-html">
|
||||
{% if mail.sensitive %}
|
||||
<div class="empty-collection">
|
||||
<p>
|
||||
{% icon "eye-slash fa-4x" %}
|
||||
</p>
|
||||
<p>
|
||||
{% blocktrans trimmed %}
|
||||
Sensitive content not shown for security reasons
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
</div>
|
||||
{% else %}
|
||||
{{ data_url|json_script:"mail_body_html" }}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
<div role="tabpanel"
|
||||
class="tab-pane {% if not mail.is_failed and not mail.body_html %}active{% endif %}"
|
||||
id="tab-text">
|
||||
{% if mail.sensitive %}
|
||||
<div class="empty-collection">
|
||||
<p>
|
||||
{% icon "eye-slash fa-4x" %}
|
||||
</p>
|
||||
<p>
|
||||
{% blocktrans trimmed %}
|
||||
Sensitive content not shown for security reasons
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
</div>
|
||||
{% else %}
|
||||
<pre><code>{{ mail.body_plain }}</code></pre>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div role="tabpanel"
|
||||
class="tab-pane"
|
||||
id="tab-headers">
|
||||
<pre><code>{% for k, v in mail.headers.items %}{{ k }}: {{ v }}<br>{% endfor %}</code></pre>
|
||||
<p class="text-muted">
|
||||
{% trans "Additional headers will be added by the mail server and are not visible here." %}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{% compress js %}
|
||||
<script type="text/javascript" src="{% static "pretixcontrol/js/ui/outgoingmail.js" %}"></script>
|
||||
{% endcompress %}
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,185 @@
|
||||
{% extends "pretixcontrol/organizers/base.html" %}
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 %}
|
||||
{% load urlreplace %}
|
||||
{% load icon %}
|
||||
{% block inner %}
|
||||
<h1>
|
||||
{% trans "Outgoing emails" %}
|
||||
</h1>
|
||||
<p>
|
||||
{% blocktrans trimmed with days=days %}
|
||||
This is an overview of all emails sent by your organizer account in the last {{ days }} days.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
{% if mails|length == 0 and not filter_form.filtered %}
|
||||
<div class="empty-collection">
|
||||
<p>
|
||||
{% blocktrans trimmed %}
|
||||
You haven't sent any emails recently.
|
||||
{% endblocktrans %}
|
||||
</p>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">{% trans "Filter" %}</h3>
|
||||
</div>
|
||||
<form class="panel-body filter-form" action="" method="get">
|
||||
<div class="row">
|
||||
<div class="col-md-4 col-sm-6 col-xs-12">
|
||||
{% bootstrap_field filter_form.query %}
|
||||
</div>
|
||||
<div class="col-md-3 col-sm-6 col-xs-12">
|
||||
{% bootstrap_field filter_form.status %}
|
||||
</div>
|
||||
<div class="col-md-5 col-sm-6 col-xs-12">
|
||||
{% bootstrap_field filter_form.event %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-right">
|
||||
<button class="btn btn-primary btn-lg" type="submit">
|
||||
<span class="fa fa-filter"></span>
|
||||
{% trans "Filter" %}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<form action="{% url "control:organizer.outgoingmails.bulk_action" organizer=request.organizer.slug %}" method="post">
|
||||
{% csrf_token %}
|
||||
{% for field in filter_form %}
|
||||
{{ field.as_hidden }}
|
||||
{% endfor %}
|
||||
<div class="table-responsive">
|
||||
<table class="table table-condensed table-hover table-quotas">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
<label aria-label="{% trans "select all rows for batch-operation" %}"
|
||||
class="batch-select-label"><input type="checkbox" data-toggle-table/></label>
|
||||
</th>
|
||||
<th>{% trans "Subject" %}</th>
|
||||
<th>{% trans "Recipients" %}</th>
|
||||
<th>{% trans "Context" %}</th>
|
||||
<th>{% trans "Status" %}</th>
|
||||
<th>{% trans "Date" %}
|
||||
<a href="?{% url_replace request 'ordering' '-date' %}"><i
|
||||
class="fa fa-caret-down"></i></a>
|
||||
<a href="?{% url_replace request 'ordering' 'date' %}"><i class="fa fa-caret-up"></i></a>
|
||||
</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
{% if page_obj.paginator.num_pages > 1 %}
|
||||
<tr class="table-select-all warning hidden">
|
||||
<td>
|
||||
<input type="checkbox" name="__ALL" id="__all"
|
||||
data-results-total="{{ page_obj.paginator.count }}">
|
||||
</td>
|
||||
<td colspan="7">
|
||||
<label for="__all">
|
||||
{% trans "Select all results on other pages as well" %}
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
{% endif %}
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for m in mails %}
|
||||
<tr>
|
||||
<td>
|
||||
<label aria-label="{% trans "select row for batch-operation" %}"
|
||||
class="batch-select-label"><input type="checkbox" name="outgoingmail"
|
||||
class="batch-select-checkbox"
|
||||
value="{{ m.pk }}"/></label>
|
||||
</td>
|
||||
<td>
|
||||
<a href="{% url "control:organizer.outgoingmail" organizer=request.organizer.slug mail=m.id %}">
|
||||
{{ m.subject }}
|
||||
</a>
|
||||
{% if m.sensitive %}
|
||||
<span class="text-muted">{% icon "eye-slash" %}</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{{ m.to|join:", " }}
|
||||
{% if m.cc %}
|
||||
<br><small class="text-muted">{% trans "Cc" context "email" %}: {{ m.cc|join:", " }}</small>
|
||||
{% endif %}
|
||||
{% if m.bcc %}
|
||||
<br><small class="text-muted">{% trans "Bcc" context "email" %}: {{ m.bcc|join:", " }}</small>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if m.event %}
|
||||
<div>
|
||||
{% icon "calendar fa-fw" %}
|
||||
<a href="{% url "control:event.index" organizer=request.organizer.slug event=m.event.slug %}">
|
||||
{{ m.event }}
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if m.order %}
|
||||
<div>
|
||||
{% icon "shopping-cart fa-fw" %}
|
||||
<a href="{% url "control:event.order" organizer=request.organizer.slug event=m.event.slug code=m.order.code %}">
|
||||
{{ m.order.code }}</a>{% if m.orderposition %}-{{ m.orderposition.positionid }}{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if m.customer %}
|
||||
<div>
|
||||
{% icon "user fa-fw" %}
|
||||
<a href="{% url "control:organizer.customer" organizer=request.organizer.slug customer=m.customer.identifier %}">
|
||||
{{ m.customer }}
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{% if m.status == "queued" %}
|
||||
<span class="label label-info">{% icon "clock-o" %} {% trans "queued" %}</span>
|
||||
{% elif m.status == "inflight" %}
|
||||
<span class="label label-info">{% icon "send" %} {% trans "being sent" %}</span>
|
||||
{% elif m.status == "awaiting_retry" %}
|
||||
<span class="label label-warning">{% icon "repeat" %} {% trans "will be retried" %}</span>
|
||||
{% elif m.status == "failed" %}
|
||||
<span class="label label-danger">{% icon "warning" %} {% trans "failed" %}</span>
|
||||
{% elif m.status == "bounced" %}
|
||||
<span class="label label-danger">{% icon "exclamation-circle" %} {% trans "bounced" %}</span>
|
||||
{% elif m.status == "withheld" %}
|
||||
<span class="label label-warning">{% icon "ban" %} {% trans "withheld" %}</span>
|
||||
{% elif m.status == "aborted" %}
|
||||
<span class="label label-danger">{% icon "ban" %} {% trans "aborted" %}</span>
|
||||
{% elif m.status == "sent" %}
|
||||
<span class="label label-success">{% icon "check" %} {% trans "sent" %}</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
{{ m.created|date:"SHORT_DATETIME_FORMAT" }}
|
||||
{% if m.sent %}
|
||||
<br>
|
||||
<small class="text-muted">{% trans "Sent:" %} {{ m.sent|date:"SHORT_DATETIME_FORMAT" }}</small>
|
||||
{% endif %}
|
||||
</td>
|
||||
<td class="text-right flip">
|
||||
<a href="{% url "control:organizer.outgoingmail" organizer=request.organizer.slug mail=m.id %}"
|
||||
class="btn btn-default btn-sm">{% icon "eye" %}</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="batch-select-actions">
|
||||
<button type="submit" class="btn btn-primary btn-save" name="action" value="retry">
|
||||
{% icon "repeat" %}
|
||||
{% trans "Retry (if failed or withheld)" %}
|
||||
</button>
|
||||
<button type="submit" class="btn btn-danger btn-save" name="action" value="abort">
|
||||
{% icon "ban" %}
|
||||
{% trans "Abort (if queued, awaiting retry or withheld)" %}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
{% include "pretixcontrol/pagination.html" %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
@@ -38,8 +38,9 @@ from django.views.generic.base import RedirectView
|
||||
|
||||
from pretix.control.views import (
|
||||
auth, checkin, dashboards, datasync, discounts, event, geo,
|
||||
global_settings, item, main, modelimport, oauth, orders, organizer, pdf,
|
||||
search, shredder, subevents, typeahead, user, users, vouchers, waitinglist,
|
||||
global_settings, item, mail, main, modelimport, oauth, orders, organizer,
|
||||
pdf, search, shredder, subevents, typeahead, user, users, vouchers,
|
||||
waitinglist,
|
||||
)
|
||||
|
||||
urlpatterns = [
|
||||
@@ -240,6 +241,9 @@ urlpatterns = [
|
||||
name='organizer.gate.edit'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/gate/(?P<gate>[^/]+)/delete$', organizer.GateDeleteView.as_view(),
|
||||
name='organizer.gate.delete'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/outgoingmails$', mail.OutgoingMailListView.as_view(), name='organizer.outgoingmails'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/outgoingmail/bulk_action$', mail.OutgoingMailBulkAction.as_view(), name='organizer.outgoingmails.bulk_action'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/outgoingmail/(?P<mail>[0-9]+)/$', mail.OutgoingMailDetailView.as_view(), name='organizer.outgoingmail'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/teams$', organizer.TeamListView.as_view(), name='organizer.teams'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/team/add$', organizer.TeamCreateView.as_view(), name='organizer.team.add'),
|
||||
re_path(r'^organizer/(?P<organizer>[^/]+)/team/(?P<team>[^/]+)/$', organizer.TeamMemberView.as_view(),
|
||||
|
||||
@@ -66,7 +66,6 @@ from pretix.base.forms.auth import (
|
||||
)
|
||||
from pretix.base.metrics import pretix_failed_logins, pretix_successful_logins
|
||||
from pretix.base.models import TeamInvite, U2FDevice, User, WebAuthnDevice
|
||||
from pretix.base.services.mail import SendMailException
|
||||
from pretix.helpers.http import get_client_ip, redirect_to_url
|
||||
from pretix.helpers.security import handle_login_source
|
||||
|
||||
@@ -347,9 +346,6 @@ class Forgot(TemplateView):
|
||||
except User.DoesNotExist:
|
||||
logger.warning('Backend password reset for unregistered e-mail \"' + email + '\" requested.')
|
||||
|
||||
except SendMailException:
|
||||
logger.exception('Sending password reset email to \"' + email + '\" failed.')
|
||||
|
||||
except RepeatedResetDenied:
|
||||
pass
|
||||
|
||||
|
||||
@@ -0,0 +1,194 @@
|
||||
#
|
||||
# This file is part of pretix (Community Edition).
|
||||
#
|
||||
# Copyright (C) 2014-2020 Raphael Michel and contributors
|
||||
# Copyright (C) 2020-today pretix GmbH and contributors
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
|
||||
# Public License as published by the Free Software Foundation in version 3 of the License.
|
||||
#
|
||||
# ADDITIONAL TERMS APPLY: Pursuant to Section 7 of the GNU Affero General Public License, additional terms are
|
||||
# applicable granting you additional permissions and placing additional restrictions on your usage of this software.
|
||||
# Please refer to the pretix LICENSE file to obtain the full terms applicable to this work. If you did not receive
|
||||
# this file, see <https://pretix.eu/about/en/license>.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
|
||||
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
|
||||
# <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
import base64
|
||||
import logging
|
||||
from email.header import decode_header, make_header
|
||||
from email.utils import parseaddr
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib import messages
|
||||
from django.core.exceptions import BadRequest
|
||||
from django.db import transaction
|
||||
from django.shortcuts import get_object_or_404, redirect
|
||||
from django.urls import reverse
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.translation import ngettext
|
||||
from django.views import View
|
||||
from django.views.generic import DetailView, ListView
|
||||
|
||||
from pretix.base.middleware import _merge_csp, _parse_csp, _render_csp
|
||||
from pretix.base.models import OutgoingMail
|
||||
from pretix.base.services.mail import mail_send_task
|
||||
from pretix.control.forms.filter import OutgoingMailFilterForm
|
||||
from pretix.control.permissions import OrganizerPermissionRequiredMixin
|
||||
from pretix.control.views.organizer import OrganizerDetailViewMixin
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class OutgoingMailQueryMixin:
|
||||
|
||||
@cached_property
|
||||
def request_data(self):
|
||||
if self.request.method == "POST":
|
||||
d = self.request.POST
|
||||
else:
|
||||
d = self.request.GET
|
||||
d = d.copy()
|
||||
return d
|
||||
|
||||
@cached_property
|
||||
def filter_form(self):
|
||||
return OutgoingMailFilterForm(
|
||||
data=self.request_data,
|
||||
request=self.request,
|
||||
)
|
||||
|
||||
def get_queryset(self):
|
||||
qs = self.request.organizer.outgoing_mails.select_related(
|
||||
'event', 'order', 'orderposition', 'customer'
|
||||
)
|
||||
|
||||
if 'outgoingmail' in self.request_data and '__ALL' not in self.request_data:
|
||||
qs = qs.filter(
|
||||
id__in=self.request_data.getlist('outgoingmail')
|
||||
)
|
||||
elif self.request.method == 'GET' or '__ALL' in self.request_data:
|
||||
if self.filter_form.is_valid():
|
||||
qs = self.filter_form.filter_qs(qs)
|
||||
else:
|
||||
raise BadRequest("No mails selected")
|
||||
|
||||
return qs
|
||||
|
||||
|
||||
class OutgoingMailListView(OutgoingMailQueryMixin, OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, ListView):
|
||||
model = OutgoingMail
|
||||
template_name = 'pretixcontrol/organizers/outgoing_mails.html'
|
||||
# Assume "the highest" permission level for now because emails could belog to any event, order, or customer.
|
||||
# We plan to add a special permissoin in the future
|
||||
permission = 'can_change_organizer_settings'
|
||||
context_object_name = 'mails'
|
||||
paginate_by = 100
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
ctx = super().get_context_data(**kwargs)
|
||||
ctx['filter_form'] = self.filter_form
|
||||
ctx['days'] = int(settings.OUTGOING_MAIL_RETENTION / (24 * 3600))
|
||||
return ctx
|
||||
|
||||
|
||||
class OutgoingMailDetailView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, DetailView):
|
||||
model = OutgoingMail
|
||||
template_name = 'pretixcontrol/organizers/outgoing_mail.html'
|
||||
permission = 'can_change_organizer_settings'
|
||||
context_object_name = 'mail'
|
||||
|
||||
def get_object(self, queryset=None):
|
||||
return get_object_or_404(OutgoingMail, organizer=self.request.organizer, pk=self.kwargs.get('mail'))
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
response = super().dispatch(request, *args, **kwargs)
|
||||
if 'Content-Security-Policy' in response:
|
||||
h = _parse_csp(response['Content-Security-Policy'])
|
||||
else:
|
||||
h = {}
|
||||
csps = {
|
||||
'frame-src': ['data:'],
|
||||
# Unfortuantely, we can't avoid unsafe-inline for style here.
|
||||
# See outgoingmail.js for the protection measures we take.
|
||||
'style-src': ["'unsafe-inline'"],
|
||||
}
|
||||
_merge_csp(h, csps)
|
||||
response['Content-Security-Policy'] = _render_csp(h)
|
||||
return response
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
ctx = super().get_context_data(**kwargs)
|
||||
if self.object.body_html:
|
||||
ctx['data_url'] = "data:text/html;charset=utf-8;base64," + base64.b64encode(self.object.body_html.encode()).decode()
|
||||
|
||||
from_name, from_email = parseaddr(self.object.sender)
|
||||
if from_name:
|
||||
from_name = make_header(decode_header(from_name))
|
||||
ctx['sender'] = "{} <{}>".format(from_name, from_email) if from_name else from_email
|
||||
|
||||
return ctx
|
||||
|
||||
|
||||
class OutgoingMailBulkAction(OutgoingMailQueryMixin, OrganizerPermissionRequiredMixin, OrganizerDetailViewMixin, View):
|
||||
permission = 'can_change_organizer_settings'
|
||||
|
||||
@transaction.atomic
|
||||
def post(self, request, *args, **kwargs):
|
||||
if request.POST.get('action') == 'retry':
|
||||
ids = set(
|
||||
self.get_queryset().filter(status__in=OutgoingMail.STATUS_LIST_RETRYABLE).values_list("pk", flat=True)
|
||||
)
|
||||
with transaction.atomic():
|
||||
OutgoingMail.objects.filter(pk__in=ids).update(
|
||||
status=OutgoingMail.STATUS_QUEUED,
|
||||
sent=None,
|
||||
)
|
||||
self.request.organizer.log_action(
|
||||
'pretix.organizer.outgoingmails.retried', user=self.request.user, data={
|
||||
'mails': list(ids)
|
||||
}, save=False
|
||||
)
|
||||
for i in ids:
|
||||
mail_send_task.apply_async(kwargs={"outgoing_mail": i})
|
||||
|
||||
messages.success(request, ngettext(
|
||||
"A retry of one email was scheduled.",
|
||||
"A retry of {num} emails was scheduled.",
|
||||
len(ids),
|
||||
).format(num=len(ids)))
|
||||
elif request.POST.get('action') == 'abort':
|
||||
ids = set(
|
||||
self.get_queryset().filter(
|
||||
status__in=(OutgoingMail.STATUS_QUEUED, OutgoingMail.STATUS_AWAITING_RETRY)
|
||||
).values_list("pk", flat=True)
|
||||
)
|
||||
with transaction.atomic():
|
||||
OutgoingMail.objects.filter(pk__in=ids).update(
|
||||
status=OutgoingMail.STATUS_ABORTED,
|
||||
sent=None,
|
||||
)
|
||||
self.request.organizer.log_action(
|
||||
'pretix.organizer.outgoingmails.aborted', user=self.request.user, data={
|
||||
'mails': list(ids)
|
||||
}, save=False
|
||||
)
|
||||
for i in ids:
|
||||
mail_send_task.apply_async(kwargs={"outgoing_mail": i})
|
||||
|
||||
messages.success(request, ngettext(
|
||||
"One email was aborted and will not be sent.",
|
||||
"{num} emails were aborted and will not be sent.",
|
||||
len(ids),
|
||||
).format(num=len(ids)))
|
||||
return redirect(self.get_success_url())
|
||||
|
||||
def get_success_url(self) -> str:
|
||||
return reverse('control:organizer.outgoingmails', kwargs={
|
||||
'organizer': self.request.organizer.slug,
|
||||
})
|
||||
@@ -98,9 +98,7 @@ from pretix.base.services.invoices import (
|
||||
invoice_qualified, regenerate_invoice, transmit_invoice,
|
||||
)
|
||||
from pretix.base.services.locking import LockTimeoutException
|
||||
from pretix.base.services.mail import (
|
||||
SendMailException, prefix_subject, render_mail,
|
||||
)
|
||||
from pretix.base.services.mail import prefix_subject, render_mail
|
||||
from pretix.base.services.orders import (
|
||||
OrderChangeManager, OrderError, approve_order, cancel_order, deny_order,
|
||||
extend_order, mark_order_expired, mark_order_refunded,
|
||||
@@ -1066,10 +1064,6 @@ class OrderPaymentConfirm(OrderView):
|
||||
messages.error(self.request, str(e))
|
||||
except PaymentException as e:
|
||||
messages.error(self.request, str(e))
|
||||
except SendMailException:
|
||||
messages.warning(self.request,
|
||||
_('The payment has been marked as complete, but we were unable to send a '
|
||||
'confirmation mail.'))
|
||||
else:
|
||||
messages.success(self.request, _('The payment has been marked as complete.'))
|
||||
else:
|
||||
@@ -1232,7 +1226,11 @@ class OrderRefundView(OrderView):
|
||||
customer=order.customer,
|
||||
testmode=order.testmode
|
||||
)
|
||||
giftcard.log_action('pretix.giftcards.created', user=self.request.user, data={})
|
||||
giftcard.log_action(
|
||||
action='pretix.giftcards.created',
|
||||
user=self.request.user,
|
||||
data={}
|
||||
)
|
||||
refunds.append(OrderRefund(
|
||||
order=order,
|
||||
payment=None,
|
||||
@@ -1540,9 +1538,6 @@ class OrderTransition(OrderView):
|
||||
'message': str(e)
|
||||
})
|
||||
messages.error(self.request, str(e))
|
||||
except SendMailException:
|
||||
messages.warning(self.request, _('The order has been marked as paid, but we were unable to send a '
|
||||
'confirmation mail.'))
|
||||
else:
|
||||
messages.success(self.request, _('The payment has been created successfully.'))
|
||||
elif self.order.cancel_allowed() and to == 'c':
|
||||
@@ -1781,15 +1776,11 @@ class OrderResendLink(OrderView):
|
||||
permission = 'can_change_orders'
|
||||
|
||||
def post(self, *args, **kwargs):
|
||||
try:
|
||||
if 'position' in kwargs:
|
||||
p = get_object_or_404(self.order.positions, pk=kwargs['position'])
|
||||
p.resend_link(user=self.request.user)
|
||||
else:
|
||||
self.order.resend_link(user=self.request.user)
|
||||
except SendMailException:
|
||||
messages.error(self.request, _('There was an error sending the mail. Please try again later.'))
|
||||
return redirect(self.get_order_url())
|
||||
if 'position' in kwargs:
|
||||
p = get_object_or_404(self.order.positions, pk=kwargs['position'])
|
||||
p.resend_link(user=self.request.user)
|
||||
else:
|
||||
self.order.resend_link(user=self.request.user)
|
||||
|
||||
messages.success(self.request, _('The email has been queued to be sent.'))
|
||||
return redirect(self.get_order_url())
|
||||
@@ -2433,24 +2424,18 @@ class OrderSendMail(EventPermissionRequiredMixin, OrderViewMixin, FormView):
|
||||
}
|
||||
return self.get(self.request, *self.args, **self.kwargs)
|
||||
else:
|
||||
try:
|
||||
order.send_mail(
|
||||
form.cleaned_data['subject'], email_template,
|
||||
email_context, 'pretix.event.order.email.custom_sent',
|
||||
self.request.user, auto_email=False,
|
||||
attach_tickets=form.cleaned_data.get('attach_tickets', False),
|
||||
invoices=form.cleaned_data.get('attach_invoices', []),
|
||||
attach_other_files=[a for a in [
|
||||
self.request.event.settings.get('mail_attachment_new_order', as_type=str, default='')[len('file://'):]
|
||||
] if a] if form.cleaned_data.get('attach_new_order', False) else [],
|
||||
)
|
||||
messages.success(self.request,
|
||||
_('Your message has been queued and will be sent to {}.'.format(order.email)))
|
||||
except SendMailException:
|
||||
messages.error(
|
||||
self.request,
|
||||
_('Failed to send mail to the following user: {}'.format(order.email))
|
||||
)
|
||||
order.send_mail(
|
||||
form.cleaned_data['subject'], email_template,
|
||||
email_context, 'pretix.event.order.email.custom_sent',
|
||||
self.request.user, auto_email=False,
|
||||
attach_tickets=form.cleaned_data.get('attach_tickets', False),
|
||||
invoices=form.cleaned_data.get('attach_invoices', []),
|
||||
attach_other_files=[a for a in [
|
||||
self.request.event.settings.get('mail_attachment_new_order', as_type=str, default='')[len('file://'):]
|
||||
] if a] if form.cleaned_data.get('attach_new_order', False) else [],
|
||||
)
|
||||
messages.success(self.request,
|
||||
_('Your message has been queued and will be sent to {}.'.format(order.email)))
|
||||
return super(OrderSendMail, self).form_valid(form)
|
||||
|
||||
def get_success_url(self):
|
||||
@@ -2503,23 +2488,19 @@ class OrderPositionSendMail(OrderSendMail):
|
||||
}
|
||||
return self.get(self.request, *self.args, **self.kwargs)
|
||||
else:
|
||||
try:
|
||||
position.send_mail(
|
||||
form.cleaned_data['subject'],
|
||||
email_template,
|
||||
email_context,
|
||||
'pretix.event.order.position.email.custom_sent',
|
||||
self.request.user,
|
||||
attach_tickets=form.cleaned_data.get('attach_tickets', False),
|
||||
attach_other_files=[a for a in [
|
||||
self.request.event.settings.get('mail_attachment_new_order', as_type=str, default='')[len('file://'):]
|
||||
] if a] if form.cleaned_data.get('attach_new_order', False) else [],
|
||||
)
|
||||
messages.success(self.request,
|
||||
_('Your message has been queued and will be sent to {}.'.format(position.attendee_email)))
|
||||
except SendMailException:
|
||||
messages.error(self.request,
|
||||
_('Failed to send mail to the following user: {}'.format(position.attendee_email)))
|
||||
position.send_mail(
|
||||
form.cleaned_data['subject'],
|
||||
email_template,
|
||||
email_context,
|
||||
'pretix.event.order.position.email.custom_sent',
|
||||
self.request.user,
|
||||
attach_tickets=form.cleaned_data.get('attach_tickets', False),
|
||||
attach_other_files=[a for a in [
|
||||
self.request.event.settings.get('mail_attachment_new_order', as_type=str, default='')[len('file://'):]
|
||||
] if a] if form.cleaned_data.get('attach_new_order', False) else [],
|
||||
)
|
||||
messages.success(self.request,
|
||||
_('Your message has been queued and will be sent to {}.'.format(position.attendee_email)))
|
||||
return super(OrderSendMail, self).form_valid(form)
|
||||
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ from pretix.base.plugins import (
|
||||
PLUGIN_LEVEL_ORGANIZER,
|
||||
)
|
||||
from pretix.base.services.export import multiexport, scheduled_organizer_export
|
||||
from pretix.base.services.mail import SendMailException, mail, prefix_subject
|
||||
from pretix.base.services.mail import mail, prefix_subject
|
||||
from pretix.base.signals import register_multievent_data_exporters
|
||||
from pretix.base.templatetags.rich_text import markdown_compile_email
|
||||
from pretix.base.views.tasks import AsyncAction
|
||||
@@ -1037,24 +1037,21 @@ class TeamMemberView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin,
|
||||
return ctx
|
||||
|
||||
def _send_invite(self, instance):
|
||||
try:
|
||||
mail(
|
||||
instance.email,
|
||||
_('pretix account invitation'),
|
||||
'pretixcontrol/email/invitation.txt',
|
||||
{
|
||||
'user': self,
|
||||
'organizer': self.request.organizer.name,
|
||||
'team': instance.team.name,
|
||||
'url': build_global_uri('control:auth.invite', kwargs={
|
||||
'token': instance.token
|
||||
})
|
||||
},
|
||||
event=None,
|
||||
locale=self.request.LANGUAGE_CODE
|
||||
)
|
||||
except SendMailException:
|
||||
pass # Already logged
|
||||
mail(
|
||||
instance.email,
|
||||
_('pretix account invitation'),
|
||||
'pretixcontrol/email/invitation.txt',
|
||||
{
|
||||
'user': self,
|
||||
'organizer': self.request.organizer.name,
|
||||
'team': instance.team.name,
|
||||
'url': build_global_uri('control:auth.invite', kwargs={
|
||||
'token': instance.token
|
||||
})
|
||||
},
|
||||
event=None,
|
||||
locale=self.request.LANGUAGE_CODE
|
||||
)
|
||||
|
||||
@transaction.atomic
|
||||
def post(self, request, *args, **kwargs):
|
||||
@@ -1670,9 +1667,12 @@ class GiftCardAcceptanceInviteView(OrganizerDetailViewMixin, OrganizerPermission
|
||||
active=False,
|
||||
)
|
||||
self.request.organizer.log_action(
|
||||
'pretix.giftcards.acceptance.acceptor.invited',
|
||||
data={'acceptor': form.cleaned_data['acceptor'].slug,
|
||||
'reusable_media': form.cleaned_data['reusable_media']},
|
||||
action='pretix.giftcards.acceptance.acceptor.invited',
|
||||
data={
|
||||
'acceptor': form.cleaned_data['acceptor'].slug,
|
||||
'issuer': self.request.organizer.slug,
|
||||
'reusable_media': form.cleaned_data['reusable_media']
|
||||
},
|
||||
user=self.request.user
|
||||
)
|
||||
messages.success(self.request, _('The selected organizer has been invited.'))
|
||||
@@ -1708,8 +1708,11 @@ class GiftCardAcceptanceListView(OrganizerDetailViewMixin, OrganizerPermissionRe
|
||||
).delete()
|
||||
if done:
|
||||
self.request.organizer.log_action(
|
||||
'pretix.giftcards.acceptance.acceptor.removed',
|
||||
data={'acceptor': request.POST.get("delete_acceptor")},
|
||||
action='pretix.giftcards.acceptance.acceptor.removed',
|
||||
data={
|
||||
'acceptor': request.POST.get("delete_acceptor"),
|
||||
'issuer': self.request.organizer.slug
|
||||
},
|
||||
user=request.user
|
||||
)
|
||||
messages.success(self.request, _('The selected connection has been removed.'))
|
||||
@@ -1719,8 +1722,11 @@ class GiftCardAcceptanceListView(OrganizerDetailViewMixin, OrganizerPermissionRe
|
||||
).delete()
|
||||
if done:
|
||||
self.request.organizer.log_action(
|
||||
'pretix.giftcards.acceptance.issuer.removed',
|
||||
data={'issuer': request.POST.get("delete_acceptor")},
|
||||
action='pretix.giftcards.acceptance.issuer.removed',
|
||||
data={
|
||||
'issuer': request.POST.get("delete_acceptor"),
|
||||
'acceptor': self.request.organizer.slug
|
||||
},
|
||||
user=request.user
|
||||
)
|
||||
messages.success(self.request, _('The selected connection has been removed.'))
|
||||
@@ -1730,8 +1736,11 @@ class GiftCardAcceptanceListView(OrganizerDetailViewMixin, OrganizerPermissionRe
|
||||
).update(active=True)
|
||||
if done:
|
||||
self.request.organizer.log_action(
|
||||
'pretix.giftcards.acceptance.issuer.accepted',
|
||||
data={'issuer': request.POST.get("accept_issuer")},
|
||||
action='pretix.giftcards.acceptance.issuer.accepted',
|
||||
data={
|
||||
'issuer': request.POST.get("accept_issuer"),
|
||||
'acceptor': self.request.organizer.slug
|
||||
},
|
||||
user=request.user
|
||||
)
|
||||
messages.success(self.request, _('The selected connection has been accepted.'))
|
||||
@@ -1837,10 +1846,11 @@ class GiftCardDetailView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMi
|
||||
acceptor=request.organizer,
|
||||
)
|
||||
self.object.log_action(
|
||||
'pretix.giftcards.transaction.manual',
|
||||
action='pretix.giftcards.transaction.manual',
|
||||
data={
|
||||
'value': value,
|
||||
'text': request.POST.get('text')
|
||||
'text': request.POST.get('text'),
|
||||
'acceptor_id': self.request.organizer.id
|
||||
},
|
||||
user=self.request.user,
|
||||
)
|
||||
@@ -1889,15 +1899,23 @@ class GiftCardCreateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMi
|
||||
messages.success(self.request, _('The gift card has been created and can now be used.'))
|
||||
form.instance.issuer = self.request.organizer
|
||||
super().form_valid(form)
|
||||
form.instance.transactions.create(
|
||||
acceptor=self.request.organizer,
|
||||
value=form.cleaned_data['value']
|
||||
form.instance.log_action(
|
||||
action='pretix.giftcards.created',
|
||||
user=self.request.user,
|
||||
)
|
||||
form.instance.log_action('pretix.giftcards.created', user=self.request.user, data={})
|
||||
if form.cleaned_data['value']:
|
||||
form.instance.log_action('pretix.giftcards.transaction.manual', user=self.request.user, data={
|
||||
'value': form.cleaned_data['value']
|
||||
})
|
||||
form.instance.transactions.create(
|
||||
acceptor=self.request.organizer,
|
||||
value=form.cleaned_data['value']
|
||||
)
|
||||
form.instance.log_action(
|
||||
action='pretix.giftcards.transaction.manual',
|
||||
user=self.request.user,
|
||||
data={
|
||||
'value': form.cleaned_data['value'],
|
||||
'acceptor_id': self.request.organizer.id
|
||||
}
|
||||
)
|
||||
return redirect(reverse(
|
||||
'control:organizer.giftcard',
|
||||
kwargs={
|
||||
@@ -1925,7 +1943,11 @@ class GiftCardUpdateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMi
|
||||
def form_valid(self, form):
|
||||
messages.success(self.request, _('The gift card has been changed.'))
|
||||
super().form_valid(form)
|
||||
form.instance.log_action('pretix.giftcards.modified', user=self.request.user, data=dict(form.cleaned_data))
|
||||
form.instance.log_action(
|
||||
action='pretix.giftcards.modified',
|
||||
user=self.request.user,
|
||||
data=dict(form.cleaned_data)
|
||||
)
|
||||
return redirect(reverse(
|
||||
'control:organizer.giftcard',
|
||||
kwargs={
|
||||
@@ -3027,6 +3049,7 @@ class CustomerDetailView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMi
|
||||
locale=self.customer.locale,
|
||||
customer=self.customer,
|
||||
organizer=self.request.organizer,
|
||||
sensitive=True,
|
||||
)
|
||||
messages.success(
|
||||
self.request,
|
||||
|
||||
@@ -41,7 +41,6 @@ from hijack import signals
|
||||
|
||||
from pretix.base.auth import get_auth_backends
|
||||
from pretix.base.models import User
|
||||
from pretix.base.services.mail import SendMailException
|
||||
from pretix.control.forms.filter import UserFilterForm
|
||||
from pretix.control.forms.users import UserEditForm
|
||||
from pretix.control.permissions import AdministratorPermissionRequiredMixin
|
||||
@@ -139,11 +138,7 @@ class UserResetView(AdministratorPermissionRequiredMixin, RecentAuthenticationRe
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
self.object = get_object_or_404(User, pk=self.kwargs.get("id"))
|
||||
try:
|
||||
self.object.send_password_reset()
|
||||
except SendMailException:
|
||||
messages.error(request, _('There was an error sending the mail. Please try again later.'))
|
||||
return redirect(self.get_success_url())
|
||||
self.object.send_password_reset()
|
||||
|
||||
self.object.log_action('pretix.control.auth.user.forgot_password.mail_sent',
|
||||
user=request.user)
|
||||
|
||||
@@ -148,4 +148,7 @@ def pycountry_add(db, **kw):
|
||||
continue
|
||||
value = value.lower()
|
||||
index = db.indices.setdefault(key, {})
|
||||
index.setdefault(value, set()).add(obj)
|
||||
if key in ["country_code"]:
|
||||
index.setdefault(value, set()).add(obj)
|
||||
else:
|
||||
index[value] = obj
|
||||
|
||||
@@ -25,7 +25,7 @@ from django.conf import settings
|
||||
from django.core.exceptions import FieldDoesNotExist, ImproperlyConfigured
|
||||
from django.db import connection, transaction
|
||||
from django.db.models import (
|
||||
Aggregate, Expression, F, Field, Lookup, OrderBy, Value,
|
||||
Aggregate, Expression, F, Field, JSONField, Lookup, OrderBy, Value,
|
||||
)
|
||||
from django.utils.functional import lazy
|
||||
|
||||
@@ -154,6 +154,19 @@ class NotEqual(Lookup):
|
||||
return '%s <> %s' % (lhs, rhs), params
|
||||
|
||||
|
||||
@JSONField.register_lookup
|
||||
class ContainsString(Lookup):
|
||||
lookup_name = 'containsstring'
|
||||
|
||||
def as_sql(self, compiler, connection):
|
||||
if connection.vendor != "postgresql":
|
||||
raise NotImplementedError("Lookup in JSON Array not supported on this database")
|
||||
lhs, lhs_params = self.process_lhs(compiler, connection)
|
||||
rhs, rhs_params = self.process_rhs(compiler, connection)
|
||||
params = lhs_params + rhs_params
|
||||
return '%s ? %s' % (lhs, rhs), params
|
||||
|
||||
|
||||
class PostgresWindowFrame(Expression):
|
||||
template = "%(frame_type)s BETWEEN %(start)s AND %(end)s"
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
import logging
|
||||
from string import Formatter
|
||||
|
||||
from django.core.exceptions import SuspiciousOperation
|
||||
from django.utils.html import conditional_escape
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -37,6 +38,17 @@ class PlainHtmlAlternativeString:
|
||||
return f"PlainHtmlAlternativeString('{self.plain}', '{self.html}')"
|
||||
|
||||
|
||||
class FormattedString(str):
|
||||
"""
|
||||
A str subclass that has been specifically marked as "already formatted" for email rendering
|
||||
purposes to avoid duplicate formatting.
|
||||
"""
|
||||
__slots__ = ()
|
||||
|
||||
def __str__(self):
|
||||
return self
|
||||
|
||||
|
||||
class SafeFormatter(Formatter):
|
||||
"""
|
||||
Customized version of ``str.format`` that (a) behaves just like ``str.format_map`` and
|
||||
@@ -77,8 +89,19 @@ class SafeFormatter(Formatter):
|
||||
# Ignore format_spec
|
||||
return super().format_field(self._prepare_value(value), '')
|
||||
|
||||
def convert_field(self, value, conversion):
|
||||
# Ignore any conversions
|
||||
if conversion is None:
|
||||
return value
|
||||
else:
|
||||
return str(value)
|
||||
|
||||
def format_map(template, context, raise_on_missing=False, mode=SafeFormatter.MODE_RICH_TO_PLAIN, linkifier=None):
|
||||
|
||||
def format_map(template, context, raise_on_missing=False, mode=SafeFormatter.MODE_RICH_TO_PLAIN, linkifier=None) -> FormattedString:
|
||||
if isinstance(template, FormattedString):
|
||||
raise SuspiciousOperation("Calling format_map() on an already formatted string is likely unsafe.")
|
||||
if not isinstance(template, str):
|
||||
template = str(template)
|
||||
return SafeFormatter(context, raise_on_missing, mode=mode, linkifier=linkifier).format(template)
|
||||
return FormattedString(
|
||||
SafeFormatter(context, raise_on_missing, mode=mode, linkifier=linkifier).format(template)
|
||||
)
|
||||
|
||||
@@ -32,7 +32,7 @@ from django_countries.fields import Country
|
||||
from geoip2.errors import AddressNotFoundError
|
||||
|
||||
from pretix.base.i18n import language
|
||||
from pretix.base.services.mail import SendMailException, mail
|
||||
from pretix.base.services.mail import mail
|
||||
from pretix.helpers.http import get_client_ip
|
||||
from pretix.helpers.urls import build_absolute_uri
|
||||
|
||||
@@ -159,21 +159,18 @@ def handle_login_source(user, request):
|
||||
})
|
||||
if user.known_login_sources.count() > 1:
|
||||
# Do not send on first login or first login after introduction of this feature:
|
||||
try:
|
||||
with language(user.locale):
|
||||
mail(
|
||||
user.email,
|
||||
_('Login from new source detected'),
|
||||
'pretixcontrol/email/login_notice.txt',
|
||||
{
|
||||
'source': src,
|
||||
'country': Country(str(country)).name if country else _('Unknown country'),
|
||||
'instance': settings.PRETIX_INSTANCE_NAME,
|
||||
'url': build_absolute_uri('control:user.settings')
|
||||
},
|
||||
event=None,
|
||||
user=user,
|
||||
locale=user.locale
|
||||
)
|
||||
except SendMailException:
|
||||
pass # Not much we can do
|
||||
with language(user.locale):
|
||||
mail(
|
||||
user.email,
|
||||
_('Login from new source detected'),
|
||||
'pretixcontrol/email/login_notice.txt',
|
||||
{
|
||||
'source': src,
|
||||
'country': Country(str(country)).name if country else _('Unknown country'),
|
||||
'instance': settings.PRETIX_INSTANCE_NAME,
|
||||
'url': build_absolute_uri('control:user.settings')
|
||||
},
|
||||
event=None,
|
||||
user=user,
|
||||
locale=user.locale
|
||||
)
|
||||
|
||||
@@ -8,10 +8,10 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-01-26 13:19+0000\n"
|
||||
"PO-Revision-Date: 2026-01-21 21:00+0000\n"
|
||||
"PO-Revision-Date: 2026-01-29 19:42+0000\n"
|
||||
"Last-Translator: Jiří Pastrňák <jiri@pastrnak.email>\n"
|
||||
"Language-Team: Czech <https://translate.pretix.eu/projects/pretix/pretix/cs/"
|
||||
">\n"
|
||||
"Language-Team: Czech <https://translate.pretix.eu/projects/pretix/pretix/cs/>"
|
||||
"\n"
|
||||
"Language: cs\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@@ -2848,7 +2848,7 @@ msgstr "Stavy platby"
|
||||
|
||||
#: pretix/base/exporters/orderlist.py:1089
|
||||
msgid "Refund states"
|
||||
msgstr "Stav vrácení peněz"
|
||||
msgstr "Stavy vrácení peněz"
|
||||
|
||||
#: pretix/base/exporters/orderlist.py:1132
|
||||
#: pretix/base/exporters/orderlist.py:1274
|
||||
@@ -13119,13 +13119,13 @@ msgid "Contact:"
|
||||
msgstr "Kontakt:"
|
||||
|
||||
#: pretix/base/templates/pretixbase/email/order_details.html:54
|
||||
#, fuzzy, python-format
|
||||
#| msgid ""
|
||||
#| "You are receiving this email because you placed an order for {event}."
|
||||
#, python-format
|
||||
msgid ""
|
||||
"You are receiving this email because you placed an order for "
|
||||
"<strong>%(event)s</strong>."
|
||||
msgstr "Tento e-mail jste obdrželi, protože jste zadali objednávku na {event}."
|
||||
msgstr ""
|
||||
"Tento e-mail jste obdrželi, protože jste zadali objednávku na <strong>%"
|
||||
"(event)s</strong>."
|
||||
|
||||
#: pretix/base/templates/pretixbase/email/order_details.html:93
|
||||
#: pretix/control/templates/pretixcontrol/organizers/customer.html:23
|
||||
@@ -14841,7 +14841,7 @@ msgstr "Jakýkoli produkt v kvótě \"{quota}\""
|
||||
|
||||
#: pretix/control/forms/filter.py:2439
|
||||
msgid "Refund status"
|
||||
msgstr "Stav náhrady"
|
||||
msgstr "Stav vrácení peněz"
|
||||
|
||||
#: pretix/control/forms/filter.py:2441
|
||||
msgid "All open refunds"
|
||||
|
||||
@@ -4,16 +4,16 @@ msgstr ""
|
||||
"Project-Id-Version: 1\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-01-26 13:19+0000\n"
|
||||
"PO-Revision-Date: 2025-08-27 22:00+0000\n"
|
||||
"PO-Revision-Date: 2026-02-03 17:12+0000\n"
|
||||
"Last-Translator: Mie Frydensbjerg <mif@aarhus.dk>\n"
|
||||
"Language-Team: Danish <https://translate.pretix.eu/projects/pretix/pretix/da/"
|
||||
">\n"
|
||||
"Language-Team: Danish <https://translate.pretix.eu/projects/pretix/pretix/"
|
||||
"da/>\n"
|
||||
"Language: da\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 5.13\n"
|
||||
"X-Generator: Weblate 5.15.2\n"
|
||||
|
||||
#: pretix/_base_settings.py:87
|
||||
msgid "English"
|
||||
@@ -35175,30 +35175,31 @@ msgid "Yes, request cancellation"
|
||||
msgstr "Generér afbestilling"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/order_change_confirm.html:19
|
||||
#, fuzzy
|
||||
msgid "Please confirm the following changes to your order."
|
||||
msgstr "Kontroller venligst detaljerne nedenfor og bekræft din bestilling."
|
||||
msgstr "Bekræft venligst følgende ændringer i din ordre."
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/order_giftcard.html:10
|
||||
#: pretix/presale/templates/pretixpresale/event/position_giftcard.html:10
|
||||
#, fuzzy, python-format
|
||||
#, python-format
|
||||
msgid "Gift card: %(code)s"
|
||||
msgstr "Gavekort"
|
||||
msgstr "Gavekort: %(code)s"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/order_modify.html:5
|
||||
msgid "Modify order"
|
||||
msgstr "Rediger bestilling"
|
||||
msgstr "Redigér ordre"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/order_modify.html:8
|
||||
#, python-format
|
||||
msgid "Modify order: %(code)s"
|
||||
msgstr ""
|
||||
msgstr "Rediger ordre: %(code)s"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/order_modify.html:18
|
||||
msgid ""
|
||||
"Modifying your invoice address will not automatically generate a new "
|
||||
"invoice. Please contact us if you need a new invoice."
|
||||
msgstr ""
|
||||
"Ændring af din fakturaadresse vil ikke automatisk generere en ny faktura. "
|
||||
"Kontakt os venligst, hvis du har brug for en ny faktura."
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/order_modify.html:88
|
||||
#: pretix/presale/templates/pretixpresale/event/position_modify.html:49
|
||||
@@ -35210,19 +35211,22 @@ msgid "Change payment method"
|
||||
msgstr "Skift betalingsmetode"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/order_pay_change.html:13
|
||||
#, fuzzy, python-format
|
||||
#, python-format
|
||||
msgid "Choose payment method: %(code)s"
|
||||
msgstr "Skift betalingsmetode: %(code)s"
|
||||
msgstr "Vælg betalingsmetode: %(code)s"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/order_pay_change.html:19
|
||||
msgid ""
|
||||
"Please note: If you change your payment method, your order total will change "
|
||||
"by the amount displayed to the right of each method."
|
||||
msgstr ""
|
||||
"Bemærk: Hvis du ændrer din betalingsmetode, ændres din ordres samlede beløb "
|
||||
"med det beløb, der vises til højre for hver metode."
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/order_pay_change.html:61
|
||||
msgid "There are no alternative payment providers available for this order."
|
||||
msgstr ""
|
||||
"Der er ingen alternative betalingsudbydere tilgængelige for denne ordre."
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/order_pay_confirm.html:16
|
||||
msgid "Please confirm the following payment details."
|
||||
@@ -35231,7 +35235,7 @@ msgstr "Bekræft venligst følgende betalingsoplysninger."
|
||||
#: pretix/presale/templates/pretixpresale/event/order_pay_confirm.html:22
|
||||
#, python-format
|
||||
msgid "Total: %(total)s"
|
||||
msgstr ""
|
||||
msgstr "Total: %(total)s"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/payment_qr_codes.html:17
|
||||
msgid ""
|
||||
@@ -35270,10 +35274,9 @@ msgid ""
|
||||
msgstr ""
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/position.html:63
|
||||
#, fuzzy
|
||||
msgctxt "action"
|
||||
msgid "Change your ticket"
|
||||
msgstr "Ændr pris til"
|
||||
msgstr "Ændr din billet"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/position.html:68
|
||||
msgid ""
|
||||
@@ -35356,30 +35359,36 @@ msgstr "Aktiver betalingsmetode"
|
||||
#: pretix/presale/templates/pretixpresale/event/voucher.html:36
|
||||
#: pretix/presale/templates/pretixpresale/event/voucher_form.html:9
|
||||
msgid "Voucher redemption"
|
||||
msgstr ""
|
||||
msgstr "Indløsning af rabatkode"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/voucher.html:20
|
||||
#, fuzzy
|
||||
msgid "This voucher is valid only for the following specific date and time."
|
||||
msgstr "Voucheren er ikke gyldig for denne dato."
|
||||
msgstr "Rabatkoden er ikke gyldig for denne dato."
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/voucher.html:43
|
||||
msgid ""
|
||||
"For the selected date, there are currently no products available that can be "
|
||||
"bought with this voucher. Please try a different date or a different voucher."
|
||||
msgstr ""
|
||||
"Der er i øjeblikket ingen produkter tilgængelige for den valgte dato, som "
|
||||
"kan købes med denne rabatkode. Prøv venligst en anden dato eller en anden "
|
||||
"rabatkode."
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/voucher.html:47
|
||||
msgid ""
|
||||
"There are currently no products available that can be bought with this "
|
||||
"voucher."
|
||||
msgstr ""
|
||||
"Der er i øjeblikket ingen produkter tilgængelige, der kan købes med denne "
|
||||
"rabatkode."
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/voucher.html:52
|
||||
msgid ""
|
||||
"You entered a voucher code that allows you to buy one of the following "
|
||||
"products at the specified price:"
|
||||
msgstr ""
|
||||
"Du har indtastet en rabatkode, der giver dig mulighed for at købe et af "
|
||||
"følgende produkter til den angivne pris:"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/voucher.html:112
|
||||
#, python-format
|
||||
|
||||
@@ -8,8 +8,8 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-01-26 13:19+0000\n"
|
||||
"PO-Revision-Date: 2026-01-14 00:00+0000\n"
|
||||
"Last-Translator: Mario Montes <mario@t3chfest.es>\n"
|
||||
"PO-Revision-Date: 2026-01-27 14:51+0000\n"
|
||||
"Last-Translator: CVZ-es <damien.bremont@casadevelazquez.org>\n"
|
||||
"Language-Team: Spanish <https://translate.pretix.eu/projects/pretix/pretix/"
|
||||
"es/>\n"
|
||||
"Language: es\n"
|
||||
@@ -17,7 +17,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 5.15.1\n"
|
||||
"X-Generator: Weblate 5.15.2\n"
|
||||
|
||||
#: pretix/_base_settings.py:87
|
||||
msgid "English"
|
||||
@@ -2309,6 +2309,10 @@ msgid ""
|
||||
"contain at least one position of this product. The order totals etc. still "
|
||||
"include all products contained in the order."
|
||||
msgstr ""
|
||||
"Si no se selecciona ninguno, se incluyen todos los productos. Se incluyen "
|
||||
"los pedidos que contengan al menos una posición de este producto. Los "
|
||||
"totales del pedido, etc., siguen incluyendo todos los productos contenidos "
|
||||
"en el pedido."
|
||||
|
||||
#: pretix/base/exporters/orderlist.py:283
|
||||
#: pretix/base/exporters/orderlist.py:478
|
||||
@@ -2572,10 +2576,8 @@ msgid "Voucher"
|
||||
msgstr "Vale de compra"
|
||||
|
||||
#: pretix/base/exporters/orderlist.py:653
|
||||
#, fuzzy
|
||||
#| msgid "Voucher code used:"
|
||||
msgid "Voucher budget usage"
|
||||
msgstr "Código de vale de compra utilizado:"
|
||||
msgstr "Uso del presupuesto del vale"
|
||||
|
||||
#: pretix/base/exporters/orderlist.py:654
|
||||
msgid "Pseudonymization ID"
|
||||
@@ -5540,14 +5542,6 @@ msgid "Only show after sellout of"
|
||||
msgstr "Mostrar sólo tras la venta completa de"
|
||||
|
||||
#: pretix/base/models/items.py:596
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "If you select a product here, this product will only be shown when that "
|
||||
#| "product is sold out. If combined with the option to hide sold-out "
|
||||
#| "products, this allows you to swap out products for more expensive ones "
|
||||
#| "once the cheaper option is sold out. There might be a short period in "
|
||||
#| "which both products are visible while all tickets of the referenced "
|
||||
#| "product are reserved, but not yet sold."
|
||||
msgid ""
|
||||
"If you select a product here, this product will only be shown when that "
|
||||
"product is no longer available. This will happen either because the other "
|
||||
@@ -5558,12 +5552,14 @@ msgid ""
|
||||
"products are visible while all tickets of the referenced product are "
|
||||
"reserved, but not yet sold."
|
||||
msgstr ""
|
||||
"Si selecciona un producto aquí, este producto solo se mostrará cuando esté "
|
||||
"agotado. Si se combina con la opción de ocultar productos agotados, esto le "
|
||||
"permite cambiar productos por otros más caros una vez que la opción más "
|
||||
"barata se agote. Puede haber un breve período en el que ambos productos "
|
||||
"estén visibles mientras todas las entradas del producto al que se hace "
|
||||
"referencia están reservadas, pero aún no vendidas."
|
||||
"Si selecciona un producto aquí, este solo se mostrará cuando ya no esté "
|
||||
"disponible. Esto sucederá porque el otro producto se haya agotado o porque "
|
||||
"el tiempo esté fuera del plazo de venta del otro producto. Si se combina con "
|
||||
"la opción de ocultar los productos agotados, esto le permite cambiar los "
|
||||
"productos por otros más caros una vez que se haya agotado la opción más "
|
||||
"barata. Puede haber un breve periodo en el que ambos productos estén "
|
||||
"visibles mientras todas las entradas del producto de referencia están "
|
||||
"reservadas, pero aún no vendidas."
|
||||
|
||||
#: pretix/base/models/items.py:611
|
||||
msgid ""
|
||||
@@ -9797,6 +9793,8 @@ msgstr ""
|
||||
#: pretix/base/settings.py:189
|
||||
msgid "Require login to access order confirmation pages"
|
||||
msgstr ""
|
||||
"Es necesario iniciar sesión para acceder a las páginas de confirmación de "
|
||||
"pedidos"
|
||||
|
||||
#: pretix/base/settings.py:190
|
||||
msgid ""
|
||||
@@ -9805,6 +9803,11 @@ msgid ""
|
||||
"placing an order, the restriction only becomes active after the customer "
|
||||
"account is activated."
|
||||
msgstr ""
|
||||
"Si está habilitada, los usuarios que hayan iniciado sesión en el momento de "
|
||||
"la compra también deberán iniciar sesión para acceder a la información de su "
|
||||
"pedido. Si se crea una cuenta de cliente al realizar un pedido, la "
|
||||
"restricción solo se activará después de que se haya activado la cuenta de "
|
||||
"cliente."
|
||||
|
||||
#: pretix/base/settings.py:202
|
||||
msgid "Match orders based on email address"
|
||||
@@ -10603,10 +10606,8 @@ msgstr ""
|
||||
"algún cambio."
|
||||
|
||||
#: pretix/base/settings.py:1234
|
||||
#, fuzzy
|
||||
#| msgid "Restrict to business customers"
|
||||
msgid "Only issue invoices to business customers"
|
||||
msgstr "Restringir a clientes empresariales"
|
||||
msgstr "Emitir facturas únicamente a clientes empresariales"
|
||||
|
||||
#: pretix/base/settings.py:1243
|
||||
msgid "Address line"
|
||||
@@ -24650,10 +24651,8 @@ msgstr ""
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/orders/export_form.html:46
|
||||
#: pretix/control/templates/pretixcontrol/organizers/export_form.html:47
|
||||
#, fuzzy
|
||||
#| msgid "Sample company"
|
||||
msgid "Save copy"
|
||||
msgstr "Compañía de ejemplo"
|
||||
msgstr "Guardar copia"
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/orders/export_form.html:56
|
||||
#: pretix/control/templates/pretixcontrol/organizers/export_form.html:57
|
||||
@@ -28139,10 +28138,10 @@ msgid "Please try again."
|
||||
msgstr "Por favor, inténtalo de nuevo."
|
||||
|
||||
#: pretix/control/views/auth.py:544
|
||||
#, fuzzy
|
||||
#| msgid "Two-factor authentication is required to log in"
|
||||
msgid "A recovery code for two-factor authentification was used to log in."
|
||||
msgstr "Autenticación de 2 pasos es necesaria para iniciar sesión"
|
||||
msgstr ""
|
||||
"Se utilizó un código de recuperación para la autenticación de dos factores "
|
||||
"para iniciar sesión."
|
||||
|
||||
#: pretix/control/views/auth.py:560
|
||||
msgid "Invalid code, please try again."
|
||||
@@ -28200,11 +28199,11 @@ msgstr "Se ha borrado la lista seleccionada."
|
||||
|
||||
#: pretix/control/views/dashboards.py:114
|
||||
msgid "Attendees (ordered)"
|
||||
msgstr "Asistentes (pedidos)"
|
||||
msgstr "Asistentes (por orden alfabético)"
|
||||
|
||||
#: pretix/control/views/dashboards.py:124
|
||||
msgid "Attendees (paid)"
|
||||
msgstr "Asistentes (pagados)"
|
||||
msgstr "Asistentes (de pago)"
|
||||
|
||||
#: pretix/control/views/dashboards.py:136
|
||||
#, python-brace-format
|
||||
@@ -29164,10 +29163,8 @@ msgid "The invoice has been scheduled for retransmission."
|
||||
msgstr "La factura se ha programado para su reenvío."
|
||||
|
||||
#: pretix/control/views/orders.py:1751
|
||||
#, fuzzy
|
||||
#| msgid "The invoice has already been canceled."
|
||||
msgid "The invoice has been canceled."
|
||||
msgstr "La factura ya se ha anulado."
|
||||
msgstr "La factura ha sido cancelada."
|
||||
|
||||
#: pretix/control/views/orders.py:1794
|
||||
msgid "The email has been queued to be sent."
|
||||
@@ -29877,6 +29874,9 @@ msgid ""
|
||||
"This will usually happen if you lost access to your two-factor credentials "
|
||||
"and requested a reset of the credentials."
|
||||
msgstr ""
|
||||
"El administrador del sistema ha generado un código de emergencia de dos "
|
||||
"factores. Esto suele ocurrir si ha perdido el acceso a sus credenciales de "
|
||||
"dos factores y ha solicitado un restablecimiento de las mismas."
|
||||
|
||||
#: pretix/control/views/users.py:174
|
||||
#, python-brace-format
|
||||
@@ -30783,14 +30783,8 @@ msgid "Reference code (important):"
|
||||
msgstr "Código de referencia (importante):"
|
||||
|
||||
#: pretix/plugins/banktransfer/templates/pretixplugins/banktransfer/checkout_payment_form.html:30
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "We will assign you a personal reference code to use after you completed "
|
||||
#| "the order."
|
||||
msgid "We will assign you a personal reference code in the next step."
|
||||
msgstr ""
|
||||
"Le asignaremos un código de referencia personal para que lo utilice después "
|
||||
"de completar el pedido."
|
||||
msgstr "En el siguiente paso le asignaremos un código de referencia personal."
|
||||
|
||||
#: pretix/plugins/banktransfer/templates/pretixplugins/banktransfer/checkout_payment_form.html:36
|
||||
msgid ""
|
||||
@@ -32126,11 +32120,8 @@ msgid "#"
|
||||
msgstr "#"
|
||||
|
||||
#: pretix/plugins/reports/exporters.py:483
|
||||
#, fuzzy
|
||||
#| msgctxt "skip-to-main-nav"
|
||||
#| msgid "Skip link"
|
||||
msgid "Skip empty lines"
|
||||
msgstr "Saltar enlace"
|
||||
msgstr "Omitir líneas vacías"
|
||||
|
||||
#: pretix/plugins/reports/exporters.py:492
|
||||
msgid "Tax split list (PDF)"
|
||||
@@ -32760,24 +32751,20 @@ msgid "Orders by day"
|
||||
msgstr "Pedidos por día"
|
||||
|
||||
#: pretix/plugins/statistics/templates/pretixplugins/statistics/index.html:25
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Only fully paid orders are counted. Orders paid in multiple payments are "
|
||||
#| "shown with the date of their last payment."
|
||||
msgid ""
|
||||
"Orders paid in multiple payments are shown with the date of their last "
|
||||
"payment. Placed orders include all orders (pending, paid, canceled, and "
|
||||
"expired); paid orders include only paid orders and exclude all canceled "
|
||||
"orders."
|
||||
msgstr ""
|
||||
"Sólo se cuentan los pedidos pagados en su totalidad. Los pedidos pagados en "
|
||||
"múltiples pagos se muestran con la fecha de su último pago."
|
||||
"Los pedidos pagados en varios plazos se muestran con la fecha de su último "
|
||||
"pago. Los pedidos realizados incluyen todos los pedidos (pendientes, "
|
||||
"pagados, cancelados y caducados); los pedidos pagados incluyen solo los "
|
||||
"pedidos pagados y excluyen todos los pedidos cancelados."
|
||||
|
||||
#: pretix/plugins/statistics/templates/pretixplugins/statistics/index.html:36
|
||||
#, fuzzy
|
||||
#| msgid "Attendee badges"
|
||||
msgid "Attendees by day"
|
||||
msgstr "Insignias de participante"
|
||||
msgstr "Asistentes por día"
|
||||
|
||||
#: pretix/plugins/statistics/templates/pretixplugins/statistics/index.html:42
|
||||
#: pretix/plugins/statistics/templates/pretixplugins/statistics/index.html:62
|
||||
@@ -32789,12 +32776,18 @@ msgid ""
|
||||
"(pending, paid, canceled, and expired); attendees in paid orders include "
|
||||
"only those from paid orders and exclude those from canceled orders."
|
||||
msgstr ""
|
||||
"Los asistentes en pedidos pagados en varios plazos se muestran utilizando la "
|
||||
"fecha del último pago. Las fechas de los pedidos reflejan cuándo se realizó "
|
||||
"el pedido por primera vez; los asistentes añadidos posteriormente a través "
|
||||
"de posiciones de pedido adicionales siguen utilizando la fecha del pedido "
|
||||
"original. Los asistentes en pedidos realizados incluyen los de todos los "
|
||||
"estados de los pedidos (pendientes, pagados, cancelados y caducados); los "
|
||||
"asistentes en pedidos pagados incluyen solo los de pedidos pagados y "
|
||||
"excluyen los de pedidos cancelados."
|
||||
|
||||
#: pretix/plugins/statistics/templates/pretixplugins/statistics/index.html:56
|
||||
#, fuzzy
|
||||
#| msgid "Attendee name"
|
||||
msgid "Attendees by time"
|
||||
msgstr "Nombre del asistente"
|
||||
msgstr "Asistentes por hora"
|
||||
|
||||
#: pretix/plugins/statistics/templates/pretixplugins/statistics/index.html:76
|
||||
msgid "Revenue over time"
|
||||
@@ -32810,36 +32803,34 @@ msgstr ""
|
||||
"mostrarán aquí, ya que es posible que no esté claro a qué fecha pertenecen."
|
||||
|
||||
#: pretix/plugins/statistics/templates/pretixplugins/statistics/index.html:91
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Only fully paid orders are counted. Orders paid in multiple payments are "
|
||||
#| "shown with the date of their last payment."
|
||||
msgid ""
|
||||
"Only fully paid orders are counted. Orders paid in multiple payments are "
|
||||
"shown with the date of their last payment. Revenue excludes all fees, "
|
||||
"including cancellation fees."
|
||||
msgstr ""
|
||||
"Sólo se cuentan los pedidos pagados en su totalidad. Los pedidos pagados en "
|
||||
"múltiples pagos se muestran con la fecha de su último pago."
|
||||
"Solo se contabilizan los pedidos pagados en su totalidad. Los pedidos "
|
||||
"pagados en varios plazos se muestran con la fecha del último pago. Los "
|
||||
"ingresos excluyen todas las tasas, incluidas las tasas de cancelación."
|
||||
|
||||
#: pretix/plugins/statistics/templates/pretixplugins/statistics/index.html:97
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Only fully paid orders are counted. Orders paid in multiple payments are "
|
||||
#| "shown with the date of their last payment."
|
||||
msgid ""
|
||||
"Only fully paid orders are counted. Orders paid in multiple payments are "
|
||||
"shown with the date of their last payment. Revenue includes all fees, "
|
||||
"including cancellation fees from canceled orders."
|
||||
msgstr ""
|
||||
"Sólo se cuentan los pedidos pagados en su totalidad. Los pedidos pagados en "
|
||||
"múltiples pagos se muestran con la fecha de su último pago."
|
||||
"Solo se contabilizan los pedidos pagados en su totalidad. Los pedidos "
|
||||
"pagados en varios plazos se muestran con la fecha del último pago. Los "
|
||||
"ingresos incluyen todas las tarifas, incluidas las tarifas de cancelación de "
|
||||
"los pedidos cancelados."
|
||||
|
||||
#: pretix/plugins/statistics/templates/pretixplugins/statistics/index.html:115
|
||||
msgid ""
|
||||
"Placed orders include all orders (pending, paid, canceled, and expired); "
|
||||
"paid orders include only paid orders and exclude all canceled orders."
|
||||
msgstr ""
|
||||
"Los pedidos realizados incluyen todos los pedidos (pendientes, pagados, "
|
||||
"cancelados y caducados); los pedidos pagados incluyen solo los pedidos "
|
||||
"pagados y excluyen todos los pedidos cancelados."
|
||||
|
||||
#: pretix/plugins/statistics/templates/pretixplugins/statistics/index.html:126
|
||||
msgid "Seating Overview"
|
||||
|
||||
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-01-26 09:10+0000\n"
|
||||
"PO-Revision-Date: 2026-01-14 00:00+0000\n"
|
||||
"PO-Revision-Date: 2026-01-27 14:51+0000\n"
|
||||
"Last-Translator: CVZ-es <damien.bremont@casadevelazquez.org>\n"
|
||||
"Language-Team: Spanish <https://translate.pretix.eu/projects/pretix/pretix-"
|
||||
"js/es/>\n"
|
||||
@@ -17,7 +17,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 5.15.1\n"
|
||||
"X-Generator: Weblate 5.15.2\n"
|
||||
|
||||
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:56
|
||||
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:62
|
||||
@@ -162,12 +162,12 @@ msgstr "Órdenes pagadas"
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:27
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:39
|
||||
msgid "Attendees (ordered)"
|
||||
msgstr ""
|
||||
msgstr "Asistentes (por orden alfabético)"
|
||||
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:27
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:39
|
||||
msgid "Attendees (paid)"
|
||||
msgstr ""
|
||||
msgstr "Asistentes (de pago)"
|
||||
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:51
|
||||
msgid "Total revenue"
|
||||
|
||||
@@ -4,16 +4,16 @@ msgstr ""
|
||||
"Project-Id-Version: 1\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-01-26 13:19+0000\n"
|
||||
"PO-Revision-Date: 2026-01-06 23:00+0000\n"
|
||||
"PO-Revision-Date: 2026-01-27 14:51+0000\n"
|
||||
"Last-Translator: CVZ-es <damien.bremont@casadevelazquez.org>\n"
|
||||
"Language-Team: French <https://translate.pretix.eu/projects/pretix/pretix/fr/"
|
||||
">\n"
|
||||
"Language-Team: French <https://translate.pretix.eu/projects/pretix/pretix/"
|
||||
"fr/>\n"
|
||||
"Language: fr\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n > 1;\n"
|
||||
"X-Generator: Weblate 5.15.1\n"
|
||||
"X-Generator: Weblate 5.15.2\n"
|
||||
|
||||
#: pretix/_base_settings.py:87
|
||||
msgid "English"
|
||||
@@ -2310,6 +2310,10 @@ msgid ""
|
||||
"contain at least one position of this product. The order totals etc. still "
|
||||
"include all products contained in the order."
|
||||
msgstr ""
|
||||
"Si aucun n'est sélectionné, tous les produits sont inclus. Les commandes "
|
||||
"sont incluses si elles contiennent au moins un article de ce produit. Les "
|
||||
"totaux des commandes, etc. incluent toujours tous les produits contenus dans "
|
||||
"la commande."
|
||||
|
||||
#: pretix/base/exporters/orderlist.py:283
|
||||
#: pretix/base/exporters/orderlist.py:478
|
||||
@@ -2573,10 +2577,8 @@ msgid "Voucher"
|
||||
msgstr "Bon"
|
||||
|
||||
#: pretix/base/exporters/orderlist.py:653
|
||||
#, fuzzy
|
||||
#| msgid "Voucher code used:"
|
||||
msgid "Voucher budget usage"
|
||||
msgstr "Code de réduction utilisé :"
|
||||
msgstr "Utilisation du budget des bons"
|
||||
|
||||
#: pretix/base/exporters/orderlist.py:654
|
||||
msgid "Pseudonymization ID"
|
||||
@@ -5560,14 +5562,6 @@ msgid "Only show after sellout of"
|
||||
msgstr "Afficher uniquement après la vente de"
|
||||
|
||||
#: pretix/base/models/items.py:596
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "If you select a product here, this product will only be shown when that "
|
||||
#| "product is sold out. If combined with the option to hide sold-out "
|
||||
#| "products, this allows you to swap out products for more expensive ones "
|
||||
#| "once the cheaper option is sold out. There might be a short period in "
|
||||
#| "which both products are visible while all tickets of the referenced "
|
||||
#| "product are reserved, but not yet sold."
|
||||
msgid ""
|
||||
"If you select a product here, this product will only be shown when that "
|
||||
"product is no longer available. This will happen either because the other "
|
||||
@@ -5578,12 +5572,14 @@ msgid ""
|
||||
"products are visible while all tickets of the referenced product are "
|
||||
"reserved, but not yet sold."
|
||||
msgstr ""
|
||||
"Si vous sélectionnez un produit ici, celui-ci ne sera affiché que lorsqu'il "
|
||||
"sera épuisé. Combinée à l'option permettant de masquer les produits épuisés, "
|
||||
"cette option vous permet de remplacer des produits par des produits plus "
|
||||
"chers lorsque l'option la moins chère est épuisée. Il peut y avoir une "
|
||||
"courte période pendant laquelle les deux produits sont visibles alors que "
|
||||
"tous les billets du produit référencé sont réservés, mais pas encore vendus."
|
||||
"Si vous sélectionnez un produit ici, celui-ci ne s'affichera que lorsqu'il "
|
||||
"ne sera plus disponible. Cela se produira soit parce que l'autre produit est "
|
||||
"épuisé, soit parce que la période de vente de l'autre produit est terminée. "
|
||||
"Si vous combinez cette option avec celle permettant de masquer les produits "
|
||||
"épuisés, vous pourrez remplacer les produits par des produits plus chers une "
|
||||
"fois que les moins chers seront épuisés. Il peut y avoir une courte période "
|
||||
"pendant laquelle les deux produits sont visibles alors que tous les billets "
|
||||
"du produit référencé sont réservés, mais pas encore vendus."
|
||||
|
||||
#: pretix/base/models/items.py:611
|
||||
msgid ""
|
||||
@@ -9862,7 +9858,7 @@ msgstr ""
|
||||
|
||||
#: pretix/base/settings.py:189
|
||||
msgid "Require login to access order confirmation pages"
|
||||
msgstr ""
|
||||
msgstr "Connexion requise pour accéder aux pages de confirmation de commande"
|
||||
|
||||
#: pretix/base/settings.py:190
|
||||
msgid ""
|
||||
@@ -9871,6 +9867,11 @@ msgid ""
|
||||
"placing an order, the restriction only becomes active after the customer "
|
||||
"account is activated."
|
||||
msgstr ""
|
||||
"Si cette option est activée, les utilisateurs qui étaient connectés au "
|
||||
"moment de l'achat doivent également se connecter pour accéder aux "
|
||||
"informations relatives à leur commande. Si un compte client est créé lors de "
|
||||
"la passation d'une commande, la restriction ne devient active qu'après "
|
||||
"l'activation du compte client."
|
||||
|
||||
#: pretix/base/settings.py:202
|
||||
msgid "Match orders based on email address"
|
||||
@@ -10679,10 +10680,8 @@ msgstr ""
|
||||
"si un changement doit être apporté."
|
||||
|
||||
#: pretix/base/settings.py:1234
|
||||
#, fuzzy
|
||||
#| msgid "Restrict to business customers"
|
||||
msgid "Only issue invoices to business customers"
|
||||
msgstr "Restreindre aux clients professionnels"
|
||||
msgstr "N'émettez des factures qu'aux clients professionnels"
|
||||
|
||||
#: pretix/base/settings.py:1243
|
||||
msgid "Address line"
|
||||
@@ -24835,10 +24834,8 @@ msgstr ""
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/orders/export_form.html:46
|
||||
#: pretix/control/templates/pretixcontrol/organizers/export_form.html:47
|
||||
#, fuzzy
|
||||
#| msgid "Sample company"
|
||||
msgid "Save copy"
|
||||
msgstr "Exemple de société"
|
||||
msgstr "Enregistrer une copie"
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/orders/export_form.html:56
|
||||
#: pretix/control/templates/pretixcontrol/organizers/export_form.html:57
|
||||
@@ -28351,10 +28348,10 @@ msgid "Please try again."
|
||||
msgstr "Veuillez réessayer."
|
||||
|
||||
#: pretix/control/views/auth.py:544
|
||||
#, fuzzy
|
||||
#| msgid "Two-factor authentication is required to log in"
|
||||
msgid "A recovery code for two-factor authentification was used to log in."
|
||||
msgstr "L'authentification à deux facteurs est actuellement activée"
|
||||
msgstr ""
|
||||
"Un code de récupération pour l'authentification à deux facteurs a été "
|
||||
"utilisé pour se connecter."
|
||||
|
||||
#: pretix/control/views/auth.py:560
|
||||
msgid "Invalid code, please try again."
|
||||
@@ -28413,11 +28410,11 @@ msgstr "La liste sélectionnée a été supprimée."
|
||||
|
||||
#: pretix/control/views/dashboards.py:114
|
||||
msgid "Attendees (ordered)"
|
||||
msgstr "Participants (commandés)"
|
||||
msgstr "Participants (par ordre alphabétique)"
|
||||
|
||||
#: pretix/control/views/dashboards.py:124
|
||||
msgid "Attendees (paid)"
|
||||
msgstr "Participants (payés)"
|
||||
msgstr "Participants (payants)"
|
||||
|
||||
#: pretix/control/views/dashboards.py:136
|
||||
#, python-brace-format
|
||||
@@ -29388,10 +29385,8 @@ msgid "The invoice has been scheduled for retransmission."
|
||||
msgstr "La facture a été programmée pour être renvoyée."
|
||||
|
||||
#: pretix/control/views/orders.py:1751
|
||||
#, fuzzy
|
||||
#| msgid "The invoice has already been canceled."
|
||||
msgid "The invoice has been canceled."
|
||||
msgstr "La facture a déjà été annulée."
|
||||
msgstr "La facture a été annulée."
|
||||
|
||||
#: pretix/control/views/orders.py:1794
|
||||
msgid "The email has been queued to be sent."
|
||||
@@ -30110,6 +30105,9 @@ msgid ""
|
||||
"This will usually happen if you lost access to your two-factor credentials "
|
||||
"and requested a reset of the credentials."
|
||||
msgstr ""
|
||||
"Un code d'urgence à deux facteurs a été généré par un administrateur "
|
||||
"système. Cela se produit généralement si vous avez perdu l'accès à vos "
|
||||
"identifiants à deux facteurs et demandé leur réinitialisation."
|
||||
|
||||
#: pretix/control/views/users.py:174
|
||||
#, python-brace-format
|
||||
@@ -31022,14 +31020,9 @@ msgid "Reference code (important):"
|
||||
msgstr "Code de référence (important) :"
|
||||
|
||||
#: pretix/plugins/banktransfer/templates/pretixplugins/banktransfer/checkout_payment_form.html:30
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "We will assign you a personal reference code to use after you completed "
|
||||
#| "the order."
|
||||
msgid "We will assign you a personal reference code in the next step."
|
||||
msgstr ""
|
||||
"Nous vous assignerons un code de référence personnel à utiliser après avoir "
|
||||
"complété la commande."
|
||||
"Nous vous attribuerons un code de référence personnel à l'étape suivante."
|
||||
|
||||
#: pretix/plugins/banktransfer/templates/pretixplugins/banktransfer/checkout_payment_form.html:36
|
||||
msgid ""
|
||||
@@ -32385,11 +32378,8 @@ msgid "#"
|
||||
msgstr "#"
|
||||
|
||||
#: pretix/plugins/reports/exporters.py:483
|
||||
#, fuzzy
|
||||
#| msgctxt "skip-to-main-nav"
|
||||
#| msgid "Skip link"
|
||||
msgid "Skip empty lines"
|
||||
msgstr "Passer le lien"
|
||||
msgstr "Ignorer les lignes vides"
|
||||
|
||||
#: pretix/plugins/reports/exporters.py:492
|
||||
msgid "Tax split list (PDF)"
|
||||
@@ -33018,25 +33008,21 @@ msgid "Orders by day"
|
||||
msgstr "Commandes par jour"
|
||||
|
||||
#: pretix/plugins/statistics/templates/pretixplugins/statistics/index.html:25
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Only fully paid orders are counted. Orders paid in multiple payments are "
|
||||
#| "shown with the date of their last payment."
|
||||
msgid ""
|
||||
"Orders paid in multiple payments are shown with the date of their last "
|
||||
"payment. Placed orders include all orders (pending, paid, canceled, and "
|
||||
"expired); paid orders include only paid orders and exclude all canceled "
|
||||
"orders."
|
||||
msgstr ""
|
||||
"Seules les commandes entièrement payées sont comptabilisées. Les commandes "
|
||||
"payées en paiements multiples sont indiquées avec la date de leur dernier "
|
||||
"paiement."
|
||||
"Les commandes réglées en plusieurs versements sont indiquées avec la date de "
|
||||
"leur dernier paiement. Les commandes passées comprennent toutes les "
|
||||
"commandes (en attente, payées, annulées et expirées) ; les commandes payées "
|
||||
"comprennent uniquement les commandes payées et excluent toutes les commandes "
|
||||
"annulées."
|
||||
|
||||
#: pretix/plugins/statistics/templates/pretixplugins/statistics/index.html:36
|
||||
#, fuzzy
|
||||
#| msgid "Attendee badges"
|
||||
msgid "Attendees by day"
|
||||
msgstr "Badges de participant"
|
||||
msgstr "Participants par jour"
|
||||
|
||||
#: pretix/plugins/statistics/templates/pretixplugins/statistics/index.html:42
|
||||
#: pretix/plugins/statistics/templates/pretixplugins/statistics/index.html:62
|
||||
@@ -33048,12 +33034,19 @@ msgid ""
|
||||
"(pending, paid, canceled, and expired); attendees in paid orders include "
|
||||
"only those from paid orders and exclude those from canceled orders."
|
||||
msgstr ""
|
||||
"Les participants dont les commandes ont été réglées en plusieurs versements "
|
||||
"sont affichés en fonction de la date du dernier paiement. Les dates de "
|
||||
"commande correspondent à la date à laquelle la commande a été passée pour la "
|
||||
"première fois ; les participants ajoutés ultérieurement via des positions de "
|
||||
"commande supplémentaires utilisent toujours la date de commande d'origine. "
|
||||
"Les participants figurant dans les commandes passées comprennent ceux de "
|
||||
"tous les statuts de commande (en attente, payée, annulée et expirée) ; les "
|
||||
"participants figurant dans les commandes payées comprennent uniquement ceux "
|
||||
"des commandes payées et excluent ceux des commandes annulées."
|
||||
|
||||
#: pretix/plugins/statistics/templates/pretixplugins/statistics/index.html:56
|
||||
#, fuzzy
|
||||
#| msgid "Attendee name"
|
||||
msgid "Attendees by time"
|
||||
msgstr "Nom du participant"
|
||||
msgstr "Participants par heure"
|
||||
|
||||
#: pretix/plugins/statistics/templates/pretixplugins/statistics/index.html:76
|
||||
msgid "Revenue over time"
|
||||
@@ -33069,38 +33062,35 @@ msgstr ""
|
||||
"listés ici car il se peut que la date correspondante ne soit pas claire."
|
||||
|
||||
#: pretix/plugins/statistics/templates/pretixplugins/statistics/index.html:91
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Only fully paid orders are counted. Orders paid in multiple payments are "
|
||||
#| "shown with the date of their last payment."
|
||||
msgid ""
|
||||
"Only fully paid orders are counted. Orders paid in multiple payments are "
|
||||
"shown with the date of their last payment. Revenue excludes all fees, "
|
||||
"including cancellation fees."
|
||||
msgstr ""
|
||||
"Seules les commandes entièrement payées sont comptabilisées. Les commandes "
|
||||
"payées en paiements multiples sont indiquées avec la date de leur dernier "
|
||||
"paiement."
|
||||
"Seules les commandes entièrement payées sont prises en compte. Les commandes "
|
||||
"payées en plusieurs fois sont indiquées avec la date de leur dernier "
|
||||
"paiement. Le chiffre d'affaires exclut tous les frais, y compris les frais "
|
||||
"d'annulation."
|
||||
|
||||
#: pretix/plugins/statistics/templates/pretixplugins/statistics/index.html:97
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Only fully paid orders are counted. Orders paid in multiple payments are "
|
||||
#| "shown with the date of their last payment."
|
||||
msgid ""
|
||||
"Only fully paid orders are counted. Orders paid in multiple payments are "
|
||||
"shown with the date of their last payment. Revenue includes all fees, "
|
||||
"including cancellation fees from canceled orders."
|
||||
msgstr ""
|
||||
"Seules les commandes entièrement payées sont comptabilisées. Les commandes "
|
||||
"payées en paiements multiples sont indiquées avec la date de leur dernier "
|
||||
"paiement."
|
||||
"Seules les commandes entièrement payées sont prises en compte. Les commandes "
|
||||
"payées en plusieurs fois sont indiquées avec la date de leur dernier "
|
||||
"paiement. Les revenus comprennent tous les frais, y compris les frais "
|
||||
"d'annulation des commandes annulées."
|
||||
|
||||
#: pretix/plugins/statistics/templates/pretixplugins/statistics/index.html:115
|
||||
msgid ""
|
||||
"Placed orders include all orders (pending, paid, canceled, and expired); "
|
||||
"paid orders include only paid orders and exclude all canceled orders."
|
||||
msgstr ""
|
||||
"Les commandes passées comprennent toutes les commandes (en attente, payées, "
|
||||
"annulées et expirées) ; les commandes payées comprennent uniquement les "
|
||||
"commandes payées et excluent toutes les commandes annulées."
|
||||
|
||||
#: pretix/plugins/statistics/templates/pretixplugins/statistics/index.html:126
|
||||
msgid "Seating Overview"
|
||||
|
||||
@@ -7,7 +7,7 @@ msgstr ""
|
||||
"Project-Id-Version: French\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-01-26 09:10+0000\n"
|
||||
"PO-Revision-Date: 2025-10-22 16:00+0000\n"
|
||||
"PO-Revision-Date: 2026-01-27 14:51+0000\n"
|
||||
"Last-Translator: CVZ-es <damien.bremont@casadevelazquez.org>\n"
|
||||
"Language-Team: French <https://translate.pretix.eu/projects/pretix/pretix-js/"
|
||||
"fr/>\n"
|
||||
@@ -16,7 +16,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n > 1;\n"
|
||||
"X-Generator: Weblate 5.13.3\n"
|
||||
"X-Generator: Weblate 5.15.2\n"
|
||||
|
||||
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:56
|
||||
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:62
|
||||
@@ -161,12 +161,12 @@ msgstr "Commandes payées"
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:27
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:39
|
||||
msgid "Attendees (ordered)"
|
||||
msgstr ""
|
||||
msgstr "Participants (par ordre alphabétique)"
|
||||
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:27
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:39
|
||||
msgid "Attendees (paid)"
|
||||
msgstr ""
|
||||
msgstr "Participants (payants)"
|
||||
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:51
|
||||
msgid "Total revenue"
|
||||
|
||||
@@ -3,16 +3,16 @@ msgstr ""
|
||||
"Project-Id-Version: HE PRETIX\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-01-26 13:19+0000\n"
|
||||
"PO-Revision-Date: 2025-05-21 10:46+0000\n"
|
||||
"Last-Translator: Raphael Michel <michel@rami.io>\n"
|
||||
"Language-Team: Hebrew <https://translate.pretix.eu/projects/pretix/pretix/he/"
|
||||
">\n"
|
||||
"PO-Revision-Date: 2026-02-09 21:00+0000\n"
|
||||
"Last-Translator: roi belotsercovsky <rbelotsercovsky@gmail.com>\n"
|
||||
"Language-Team: Hebrew <https://translate.pretix.eu/projects/pretix/pretix/"
|
||||
"he/>\n"
|
||||
"Language: he\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: Weblate 5.11.4\n"
|
||||
"X-Generator: Weblate 5.15.2\n"
|
||||
|
||||
#: pretix/_base_settings.py:87
|
||||
msgid "English"
|
||||
@@ -84,7 +84,7 @@ msgstr "יוונית"
|
||||
|
||||
#: pretix/_base_settings.py:104
|
||||
msgid "Hebrew"
|
||||
msgstr ""
|
||||
msgstr "עברית"
|
||||
|
||||
#: pretix/_base_settings.py:105
|
||||
msgid "Indonesian"
|
||||
@@ -140,7 +140,7 @@ msgstr "ספרדית"
|
||||
|
||||
#: pretix/_base_settings.py:118
|
||||
msgid "Spanish (Latin America)"
|
||||
msgstr ""
|
||||
msgstr "ספרדית (אמריקה הלטינית)"
|
||||
|
||||
#: pretix/_base_settings.py:119
|
||||
msgid "Turkish"
|
||||
@@ -285,28 +285,20 @@ msgid "The bundled item must not have bundles on its own."
|
||||
msgstr "הפריט המצורף לא יכול להחזיק חבילות בעצמו."
|
||||
|
||||
#: pretix/api/serializers/item.py:235
|
||||
#, fuzzy
|
||||
#| msgid "The payment is too late to be accepted."
|
||||
msgid "The program start must not be empty."
|
||||
msgstr "התשלום התקבל מאוחר מדי."
|
||||
msgstr "תחילת התוכנית לא יכולה להיות ריקה."
|
||||
|
||||
#: pretix/api/serializers/item.py:239
|
||||
#, fuzzy
|
||||
#| msgid "The payment is too late to be accepted."
|
||||
msgid "The program end must not be empty."
|
||||
msgstr "התשלום התקבל מאוחר מדי."
|
||||
msgstr "סוף התוכנית לא יכול להיות ריק."
|
||||
|
||||
#: pretix/api/serializers/item.py:242 pretix/base/models/items.py:2322
|
||||
#, fuzzy
|
||||
#| msgid "The maximum date must not be before the minimum value."
|
||||
msgid "The program end must not be before the program start."
|
||||
msgstr "התאריך המרבי לא יכול להיות לפני הערך המינימלי."
|
||||
msgstr "סוף התוכנית לא יכול להיות לפני תחילת התוכנית."
|
||||
|
||||
#: pretix/api/serializers/item.py:247 pretix/base/models/items.py:2316
|
||||
#, fuzzy
|
||||
#| msgid "You can not select a subevent if your event is not an event series."
|
||||
msgid "You cannot use program times on an event series."
|
||||
msgstr "לא ניתן לבחור תת-אירוע אם האירוע שלך אינו סדרת אירועים."
|
||||
msgstr "לא ניתן לבחור שעות תוכניות בסדרת אירועים."
|
||||
|
||||
#: pretix/api/serializers/item.py:337
|
||||
#, fuzzy
|
||||
@@ -569,22 +561,15 @@ msgid "Event series date deleted"
|
||||
msgstr "תאריך סדרת אירועים נמחק"
|
||||
|
||||
#: pretix/api/webhooks.py:375
|
||||
#, fuzzy
|
||||
#| msgid "Product name"
|
||||
msgid "Product changed"
|
||||
msgstr "שם המוצר"
|
||||
msgstr "המוצר השתנה"
|
||||
|
||||
#: pretix/api/webhooks.py:376
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Product changed (including product added or deleted and including changes "
|
||||
#| "to nested objects like variations or bundles)"
|
||||
msgid ""
|
||||
"This includes product added or deleted and changes to nested objects like "
|
||||
"variations or bundles."
|
||||
msgstr ""
|
||||
"המוצר שונה (כולל הוספה או מחיקה של מוצר ושינויים לאובייקטים מקוננים כמו "
|
||||
"וריאציות או חבילות)"
|
||||
"זה כולל מוצר שהוסף או נמחק ושונה לאובייקטים מקוננים כמו וריאציות או באנדלים"
|
||||
|
||||
#: pretix/api/webhooks.py:381
|
||||
msgid "Shop taken live"
|
||||
@@ -619,28 +604,22 @@ msgid "Waiting list entry received voucher"
|
||||
msgstr "רשומת רשימת המתנה קיבלה שובר"
|
||||
|
||||
#: pretix/api/webhooks.py:413
|
||||
#, fuzzy
|
||||
#| msgid "Voucher code"
|
||||
msgid "Voucher added"
|
||||
msgstr "קוד שובר"
|
||||
msgstr "קוד שובר הוסף"
|
||||
|
||||
#: pretix/api/webhooks.py:417
|
||||
#, fuzzy
|
||||
#| msgid "Voucher assigned"
|
||||
msgid "Voucher changed"
|
||||
msgstr "שובר הוקצה"
|
||||
msgstr "שובר שונה"
|
||||
|
||||
#: pretix/api/webhooks.py:418
|
||||
msgid ""
|
||||
"Only includes explicit changes to the voucher, not e.g. an increase of the "
|
||||
"number of redemptions."
|
||||
msgstr ""
|
||||
msgstr "כולל רק שינויים מפורשים לשובר, לא למשל העלאת מספר המימושים."
|
||||
|
||||
#: pretix/api/webhooks.py:422
|
||||
#, fuzzy
|
||||
#| msgid "Voucher redeemed"
|
||||
msgid "Voucher deleted"
|
||||
msgstr "שובר מומש"
|
||||
msgstr "שובר נמחק"
|
||||
|
||||
#: pretix/api/webhooks.py:426
|
||||
msgid "Customer account created"
|
||||
@@ -811,7 +790,7 @@ msgstr ""
|
||||
msgid ""
|
||||
"Field \"{field_name}\" does not exist. Please check your {provider_name} "
|
||||
"settings."
|
||||
msgstr ""
|
||||
msgstr "שדה \"{field_name}\" לא קיים. נא לבדוק את הגדרות {provider_name}."
|
||||
|
||||
#: pretix/base/datasync/datasync.py:271
|
||||
#, python-brace-format
|
||||
@@ -819,25 +798,23 @@ msgid ""
|
||||
"Field \"{field_name}\" requires {required_input}, but only got "
|
||||
"{available_inputs}. Please check your {provider_name} settings."
|
||||
msgstr ""
|
||||
"שדה \"{field_name}\" דורש {required_input}, אבל קיבל רק {available_inputs}"
|
||||
". נא לבדוק הגדרות {provider_name}."
|
||||
|
||||
#: pretix/base/datasync/datasync.py:282
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"Please update value mapping for field \"{field_name}\" - option \"{val}\" "
|
||||
"not assigned"
|
||||
msgstr ""
|
||||
msgstr "נא לעדכן מיפוי ערכים לשדה \"{field_name}\" - אפשרות \"{val}\" לא מוקצה"
|
||||
|
||||
#: pretix/base/datasync/sourcefields.py:128
|
||||
#, fuzzy
|
||||
#| msgid "Order positions"
|
||||
msgid "Order position details"
|
||||
msgstr "פריטי הזמנה"
|
||||
msgstr "פרטי מצב הזמנה"
|
||||
|
||||
#: pretix/base/datasync/sourcefields.py:129
|
||||
#, fuzzy
|
||||
#| msgid "Attendee email"
|
||||
msgid "Attendee details"
|
||||
msgstr "דוא\"ל משתתף"
|
||||
msgstr "פרטי משתתף"
|
||||
|
||||
#: pretix/base/datasync/sourcefields.py:130 pretix/base/exporters/answers.py:66
|
||||
#: pretix/base/models/items.py:1767 pretix/control/navigation.py:172
|
||||
@@ -847,10 +824,8 @@ msgid "Questions"
|
||||
msgstr "שאלות"
|
||||
|
||||
#: pretix/base/datasync/sourcefields.py:131
|
||||
#, fuzzy
|
||||
#| msgid "Product data"
|
||||
msgid "Product details"
|
||||
msgstr "נתוני מוצר"
|
||||
msgstr "פרטי מוצר"
|
||||
|
||||
#: pretix/base/datasync/sourcefields.py:132
|
||||
#: pretix/control/templates/pretixcontrol/event/settings.html:279
|
||||
@@ -875,17 +850,13 @@ msgid "Invoice address"
|
||||
msgstr "כתובת לחשבונית"
|
||||
|
||||
#: pretix/base/datasync/sourcefields.py:134
|
||||
#, fuzzy
|
||||
#| msgid "Meta information"
|
||||
msgid "Event information"
|
||||
msgstr "מידע מטא"
|
||||
msgstr "מידע על האירוע"
|
||||
|
||||
#: pretix/base/datasync/sourcefields.py:135
|
||||
#, fuzzy
|
||||
#| msgid "Send recovery information"
|
||||
msgctxt "subevent"
|
||||
msgid "Event or date information"
|
||||
msgstr "שלח פרטי שחזור"
|
||||
msgstr "מידע על האירוע או התאריך"
|
||||
|
||||
#: pretix/base/datasync/sourcefields.py:175
|
||||
#: pretix/base/exporters/orderlist.py:638
|
||||
@@ -910,10 +881,8 @@ msgstr "שם משתתף"
|
||||
#: pretix/base/datasync/sourcefields.py:187
|
||||
#: pretix/base/datasync/sourcefields.py:604
|
||||
#: pretix/base/datasync/sourcefields.py:628
|
||||
#, fuzzy
|
||||
#| msgid "Attendee name"
|
||||
msgid "Attendee"
|
||||
msgstr "שם משתתף"
|
||||
msgstr "משתתף"
|
||||
|
||||
#: pretix/base/datasync/sourcefields.py:207
|
||||
#: pretix/base/exporters/orderlist.py:645 pretix/base/forms/questions.py:693
|
||||
@@ -927,10 +896,8 @@ msgid "Attendee email"
|
||||
msgstr "דוא\"ל משתתף"
|
||||
|
||||
#: pretix/base/datasync/sourcefields.py:219
|
||||
#, fuzzy
|
||||
#| msgid "Attendee email"
|
||||
msgid "Attendee or order email"
|
||||
msgstr "דוא\"ל משתתף"
|
||||
msgstr "דוא\"ל משתתף או הזמנה"
|
||||
|
||||
#: pretix/base/datasync/sourcefields.py:232
|
||||
#: pretix/base/exporters/orderlist.py:646 pretix/base/pdf.py:188
|
||||
@@ -943,10 +910,8 @@ msgid "Attendee company"
|
||||
msgstr "חברת המשתתף"
|
||||
|
||||
#: pretix/base/datasync/sourcefields.py:241
|
||||
#, fuzzy
|
||||
#| msgid "Attendee address"
|
||||
msgid "Attendee address street"
|
||||
msgstr "כתובת המשתתף"
|
||||
msgstr "רחוב המשתתף"
|
||||
|
||||
#: pretix/base/datasync/sourcefields.py:250
|
||||
#, fuzzy
|
||||
@@ -955,16 +920,12 @@ msgid "Attendee address ZIP code"
|
||||
msgstr "מיקוד המשתתף"
|
||||
|
||||
#: pretix/base/datasync/sourcefields.py:259
|
||||
#, fuzzy
|
||||
#| msgid "Attendee address"
|
||||
msgid "Attendee address city"
|
||||
msgstr "כתובת המשתתף"
|
||||
msgstr "עיר המשתתף"
|
||||
|
||||
#: pretix/base/datasync/sourcefields.py:268
|
||||
#, fuzzy
|
||||
#| msgid "Attendee address"
|
||||
msgid "Attendee address country"
|
||||
msgstr "כתובת המשתתף"
|
||||
msgstr "מדינת המשתתף"
|
||||
|
||||
#: pretix/base/datasync/sourcefields.py:279
|
||||
#: pretix/base/exporters/orderlist.py:687 pretix/base/pdf.py:346
|
||||
@@ -1000,16 +961,12 @@ msgid "Invoice address country"
|
||||
msgstr "מדינת כתובת לחשבונית"
|
||||
|
||||
#: pretix/base/datasync/sourcefields.py:353
|
||||
#, fuzzy
|
||||
#| msgid "Order details"
|
||||
msgid "Order email"
|
||||
msgstr "פרטי הזמנה"
|
||||
msgstr "דוא\"ל הזמנה"
|
||||
|
||||
#: pretix/base/datasync/sourcefields.py:362
|
||||
#, fuzzy
|
||||
#| msgid "Organizer domain"
|
||||
msgid "Order email domain"
|
||||
msgstr "דומיין מארגן"
|
||||
msgstr "דומיין מייל הזמנה"
|
||||
|
||||
#: pretix/base/datasync/sourcefields.py:371
|
||||
#: pretix/base/exporters/invoices.py:203 pretix/base/exporters/invoices.py:332
|
||||
@@ -1041,10 +998,8 @@ msgid "Order code"
|
||||
msgstr "קוד הזמנה"
|
||||
|
||||
#: pretix/base/datasync/sourcefields.py:380
|
||||
#, fuzzy
|
||||
#| msgid "End order date"
|
||||
msgid "Event and order code"
|
||||
msgstr "תאריך סיום הזמנה"
|
||||
msgstr "אירוע וקוד הזמנה"
|
||||
|
||||
#: pretix/base/datasync/sourcefields.py:389
|
||||
#: pretix/base/exporters/orderlist.py:283 pretix/base/notifications.py:201
|
||||
@@ -1069,16 +1024,12 @@ msgid "Product ID"
|
||||
msgstr "מזהה מוצר"
|
||||
|
||||
#: pretix/base/datasync/sourcefields.py:419
|
||||
#, fuzzy
|
||||
#| msgid "Non-admission product"
|
||||
msgid "Product is admission product"
|
||||
msgstr "מוצר שאינו עבור כניסה"
|
||||
msgstr "מוצר שהינו כרטיס כניסה"
|
||||
|
||||
#: pretix/base/datasync/sourcefields.py:428
|
||||
#, fuzzy
|
||||
#| msgid "Event short name"
|
||||
msgid "Event short form"
|
||||
msgstr "שם האירוע המקוצר"
|
||||
msgstr "טופס האירוע המקוצר"
|
||||
|
||||
#: pretix/base/datasync/sourcefields.py:437 pretix/base/exporters/events.py:57
|
||||
#: pretix/base/exporters/orderlist.py:283
|
||||
@@ -1121,10 +1072,8 @@ msgid "Order code and position number"
|
||||
msgstr "קוד הזמנה ומספר פריט"
|
||||
|
||||
#: pretix/base/datasync/sourcefields.py:482
|
||||
#, fuzzy
|
||||
#| msgid "Ticket page"
|
||||
msgid "Ticket price"
|
||||
msgstr "דף כרטיס"
|
||||
msgstr "מחיר כרטיס"
|
||||
|
||||
#: pretix/base/datasync/sourcefields.py:491 pretix/base/notifications.py:204
|
||||
#: pretix/control/forms/filter.py:220 pretix/control/forms/filter.py:1242
|
||||
@@ -1133,22 +1082,16 @@ msgid "Order status"
|
||||
msgstr "סטטוס הזמנה"
|
||||
|
||||
#: pretix/base/datasync/sourcefields.py:500
|
||||
#, fuzzy
|
||||
#| msgid "Device status"
|
||||
msgid "Ticket status"
|
||||
msgstr "סטטוס מכשיר"
|
||||
msgstr "סטטוס כרטיס"
|
||||
|
||||
#: pretix/base/datasync/sourcefields.py:509
|
||||
#, fuzzy
|
||||
#| msgid "Purchase date and time"
|
||||
msgid "Order date and time"
|
||||
msgstr "תאריך ושעת הקנייה"
|
||||
msgstr "תאריך ושעת ההזמנה"
|
||||
|
||||
#: pretix/base/datasync/sourcefields.py:518
|
||||
#, fuzzy
|
||||
#| msgid "Printing date and time"
|
||||
msgid "Payment date and time"
|
||||
msgstr "תאריך ושעת ההדפסה"
|
||||
msgstr "תאריך ושעת התשלום"
|
||||
|
||||
#: pretix/base/datasync/sourcefields.py:527
|
||||
#: pretix/base/exporters/orderlist.py:292
|
||||
@@ -1159,35 +1102,27 @@ msgid "Order locale"
|
||||
msgstr "שפת הזמנה"
|
||||
|
||||
#: pretix/base/datasync/sourcefields.py:536
|
||||
#, fuzzy
|
||||
#| msgid "Order position"
|
||||
msgid "Order position ID"
|
||||
msgstr "עמדת הזמנה"
|
||||
msgstr "מספר עמדת הזמנה"
|
||||
|
||||
#: pretix/base/datasync/sourcefields.py:545
|
||||
#: pretix/base/exporters/orderlist.py:312
|
||||
#, fuzzy
|
||||
#| msgid "Order time"
|
||||
msgid "Order link"
|
||||
msgstr "שעת הזמנה"
|
||||
msgstr "קישור הזמנה"
|
||||
|
||||
#: pretix/base/datasync/sourcefields.py:560
|
||||
#, fuzzy
|
||||
#| msgid "Ticket block"
|
||||
msgid "Ticket link"
|
||||
msgstr "חסימת כרטיס"
|
||||
msgstr "קישור כרטיס"
|
||||
|
||||
#: pretix/base/datasync/sourcefields.py:578
|
||||
#, fuzzy, python-brace-format
|
||||
#| msgid "Check-in list {val}"
|
||||
#, python-brace-format
|
||||
msgid "Check-in datetime on list {}"
|
||||
msgstr "רשימת הצ'ק-אין {val}"
|
||||
msgstr "צ'ק-אין בתאריך-זמן ברשימה {}"
|
||||
|
||||
#: pretix/base/datasync/sourcefields.py:590
|
||||
#, fuzzy, python-brace-format
|
||||
#| msgid "Question: %(name)s"
|
||||
#, python-brace-format
|
||||
msgid "Question: {name}"
|
||||
msgstr "שאלה: %(name)s"
|
||||
msgstr "שאלה: {name}"
|
||||
|
||||
#: pretix/base/datasync/sourcefields.py:604
|
||||
#: pretix/base/datasync/sourcefields.py:614 pretix/base/settings.py:3691
|
||||
@@ -2328,6 +2263,8 @@ msgid ""
|
||||
"contain at least one position of this product. The order totals etc. still "
|
||||
"include all products contained in the order."
|
||||
msgstr ""
|
||||
"אם אף אחד מהם לא נבחר, כל המוצרים כלולים. הפקודות נכללות אם הן כוללות לפחות "
|
||||
"עמדה אחת של המוצר. סך ההזמנות וכו'. עדיין כולל את כל המוצרים הכלולים בהזמנה."
|
||||
|
||||
#: pretix/base/exporters/orderlist.py:283
|
||||
#: pretix/base/exporters/orderlist.py:478
|
||||
@@ -2591,10 +2528,8 @@ msgid "Voucher"
|
||||
msgstr "שובר"
|
||||
|
||||
#: pretix/base/exporters/orderlist.py:653
|
||||
#, fuzzy
|
||||
#| msgid "Voucher code used:"
|
||||
msgid "Voucher budget usage"
|
||||
msgstr "השתמש בקוד שובר:"
|
||||
msgstr "שימוש בתקציב השוברים"
|
||||
|
||||
#: pretix/base/exporters/orderlist.py:654
|
||||
msgid "Pseudonymization ID"
|
||||
@@ -2686,10 +2621,8 @@ msgid "Check-in lists"
|
||||
msgstr "רשימות צ'ק-אין"
|
||||
|
||||
#: pretix/base/exporters/orderlist.py:706
|
||||
#, fuzzy
|
||||
#| msgid "Resend order link"
|
||||
msgid "Position order link"
|
||||
msgstr "שלח את קישור ההזמנה שוב"
|
||||
msgstr "עמדת קישור הזמנה"
|
||||
|
||||
#: pretix/base/exporters/orderlist.py:876
|
||||
msgid "Order transaction data"
|
||||
@@ -3326,10 +3259,8 @@ msgid "Repeat password"
|
||||
msgstr "חזור על הסיסמה"
|
||||
|
||||
#: pretix/base/forms/auth.py:220 pretix/base/forms/user.py:99
|
||||
#, fuzzy
|
||||
#| msgid "Email address"
|
||||
msgid "Your email address"
|
||||
msgstr "כתובת דוא\"ל"
|
||||
msgstr "כתובת הדוא\"ל שלך"
|
||||
|
||||
#: pretix/base/forms/auth.py:327 pretix/control/forms/orders.py:1041
|
||||
#: pretix/control/templates/pretixcontrol/shredder/download.html:53
|
||||
@@ -3410,14 +3341,12 @@ msgstr ""
|
||||
"למדינתך ומדינת המוכר."
|
||||
|
||||
#: pretix/base/forms/questions.py:1185
|
||||
#, fuzzy
|
||||
#| msgid "Cancellation requested"
|
||||
msgid "No invoice requested"
|
||||
msgstr "בקשת ביטול"
|
||||
msgstr "לא התבקשה חשבונית"
|
||||
|
||||
#: pretix/base/forms/questions.py:1187
|
||||
msgid "Invoice transmission method"
|
||||
msgstr ""
|
||||
msgstr "שיטת שידור חשבונית"
|
||||
|
||||
#: pretix/base/forms/questions.py:1333
|
||||
msgid "You need to provide a company name."
|
||||
@@ -3431,25 +3360,24 @@ msgstr "עליך לספק את שמך."
|
||||
msgid ""
|
||||
"If you enter an invoice address, you also need to select an invoice "
|
||||
"transmission method."
|
||||
msgstr ""
|
||||
msgstr "אם אתה מזין כתובת לחשבונית, עליך גם לבחור שיטת שידור חשבונית."
|
||||
|
||||
#: pretix/base/forms/questions.py:1403
|
||||
#, fuzzy
|
||||
#| msgid "The selected media type is not enabled in your organizer settings."
|
||||
msgid ""
|
||||
"The selected transmission type is not available in your country or for your "
|
||||
"type of address."
|
||||
msgstr "סוג המדיה שנבחר אינו מופעל בהגדרות הארגון שלכם."
|
||||
msgstr "סוג השידור שנבחר אינו זמין במדינתך או בסוג הכתובת שבחרת."
|
||||
|
||||
#: pretix/base/forms/questions.py:1412
|
||||
msgid ""
|
||||
"The selected type of invoice transmission requires a field that is currently "
|
||||
"not available, please reach out to the organizer."
|
||||
msgstr ""
|
||||
"סוג שידור החשבונית שנבחר דורש שדה שאינו זמין כרגע, נא ליצור קשר עם המארגן."
|
||||
|
||||
#: pretix/base/forms/questions.py:1416
|
||||
msgid "This field is required for the selected type of invoice transmission."
|
||||
msgstr ""
|
||||
msgstr "שדה זה הינו חובה לסוג שידור החשבונית שנבחר."
|
||||
|
||||
#: pretix/base/forms/user.py:54 pretix/control/forms/organizer.py:458
|
||||
#: pretix/control/forms/users.py:58
|
||||
@@ -3465,10 +3393,8 @@ msgstr ""
|
||||
"באזור הזמן של האירוע עצמו."
|
||||
|
||||
#: pretix/base/forms/user.py:77
|
||||
#, fuzzy
|
||||
#| msgid "Attendee email address"
|
||||
msgid "Change email address"
|
||||
msgstr "כתובת דוא\"ל של המשתתף"
|
||||
msgstr "שינוי כתובת דוא\"ל"
|
||||
|
||||
#: pretix/base/forms/user.py:83
|
||||
msgid "Device name"
|
||||
@@ -3516,16 +3442,12 @@ msgid ""
|
||||
msgstr "כבר קיים חשבון הקשור לכתובת האימייל הזו. אנא בחר כתובת אחרת."
|
||||
|
||||
#: pretix/base/forms/user.py:179
|
||||
#, fuzzy
|
||||
#| msgid "Email address"
|
||||
msgid "Old email address"
|
||||
msgstr "כתובת דוא\"ל"
|
||||
msgstr "כתובת דוא\"ל ישנה"
|
||||
|
||||
#: pretix/base/forms/user.py:180
|
||||
#, fuzzy
|
||||
#| msgid "Email address"
|
||||
msgid "New email address"
|
||||
msgstr "כתובת דוא\"ל"
|
||||
msgstr "כתובת דוא\"ל חדשה"
|
||||
|
||||
#: pretix/base/forms/validators.py:51
|
||||
msgid ""
|
||||
@@ -3569,60 +3491,47 @@ msgid "Individual customer"
|
||||
msgstr "לקוח פרטי"
|
||||
|
||||
#: pretix/base/invoicing/email.py:50
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Please additionally send my invoice directly to our accounting department"
|
||||
msgid "Email invoice directly to accounting department"
|
||||
msgstr "אנא שלח בנוסף את החשבונית ישירות למחלקת הנהלת החשבונות שלנו"
|
||||
msgstr "שלח חשבונית בדוא\"ל ישירות למחלקת הנהלת חשבונות."
|
||||
|
||||
#: pretix/base/invoicing/email.py:51
|
||||
#, fuzzy
|
||||
#| msgid "The invoice was sent to the designated email address."
|
||||
msgid ""
|
||||
"If not selected, the invoice will be sent to you using the email address "
|
||||
"listed above."
|
||||
msgstr "החשבונית נשלחה לכתובת הדוא\"ל שהוגדרה."
|
||||
msgstr "אם לא ייבחר, בחשבונית תישלח לכתובת הדוא\"ל המצויינת מעלה."
|
||||
|
||||
#: pretix/base/invoicing/email.py:55
|
||||
#, fuzzy
|
||||
#| msgid "Email address verified"
|
||||
msgid "Email address for invoice"
|
||||
msgstr "כתובת דוא\"ל מאומתת"
|
||||
msgstr "כתובת דוא\"ל לחשבונית"
|
||||
|
||||
#: pretix/base/invoicing/email.py:91
|
||||
#, fuzzy
|
||||
#| msgid "Preview email"
|
||||
msgid "PDF via email"
|
||||
msgstr "הצג תצוגה מקדימה של המייל"
|
||||
msgstr "PDF באמצעות דוא\"ל"
|
||||
|
||||
#: pretix/base/invoicing/national.py:37
|
||||
msgctxt "italian_invoice"
|
||||
msgid "Italian Exchange System (SdI)"
|
||||
msgstr ""
|
||||
msgstr "מערכת ההחלפה האיטלקית (SdI)"
|
||||
|
||||
#: pretix/base/invoicing/national.py:38
|
||||
msgctxt "italian_invoice"
|
||||
msgid "Exchange System (SdI)"
|
||||
msgstr ""
|
||||
msgstr "מערכת ההחלפה (SdI)"
|
||||
|
||||
#: pretix/base/invoicing/national.py:51
|
||||
#, fuzzy
|
||||
#| msgid "Gift card code"
|
||||
msgctxt "italian_invoice"
|
||||
msgid "Fiscal code"
|
||||
msgstr "קוד כרטיס מתנה"
|
||||
msgstr "קוד פיסקלי"
|
||||
|
||||
#: pretix/base/invoicing/national.py:55
|
||||
msgctxt "italian_invoice"
|
||||
msgid "Address for certified electronic mail"
|
||||
msgstr ""
|
||||
msgstr "כתובת לדואר אלקטרוני מאושר."
|
||||
|
||||
#: pretix/base/invoicing/national.py:59
|
||||
#, fuzzy
|
||||
#| msgid "Recipient"
|
||||
msgctxt "italian_invoice"
|
||||
msgid "Recipient code"
|
||||
msgstr "נמען"
|
||||
msgstr "קוד נמען"
|
||||
|
||||
#: pretix/base/invoicing/national.py:83
|
||||
msgctxt "italian_invoice"
|
||||
@@ -3632,6 +3541,9 @@ msgid ""
|
||||
"in accordance with the procedures and terms set forth in No. 89757/2018 of "
|
||||
"April 30, 2018, issued by the Director of the Revenue Agency."
|
||||
msgstr ""
|
||||
"קובץ PDF זה הוא העתק ויזואלי של החשבונית ואינו מהווה חשבונית לצרכי מע\"מ. "
|
||||
"החשבונית מונפקת בפורמט XML, ומשודרת בהתאם לנהלים ולתנאים המפורטים בתקנה "
|
||||
"89757/2018 מה30 באפריל, 2016 שפורסמה על ידי מנהל סוכנות ההכנסות."
|
||||
|
||||
#: pretix/base/invoicing/pdf.py:142
|
||||
#, python-format
|
||||
@@ -3812,12 +3724,10 @@ msgid "Remaining amount"
|
||||
msgstr "הסכום שנותר"
|
||||
|
||||
#: pretix/base/invoicing/pdf.py:1008
|
||||
#, fuzzy, python-brace-format
|
||||
#| msgctxt "invoice"
|
||||
#| msgid "Event date: {date_range}"
|
||||
#, python-brace-format
|
||||
msgctxt "invoice"
|
||||
msgid "Invoice period: {daterange}"
|
||||
msgstr "תאריך אירוע: {date_range}"
|
||||
msgstr "תקופת החשבונית: {daterange}"
|
||||
|
||||
#: pretix/base/invoicing/pdf.py:1039
|
||||
msgctxt "invoice"
|
||||
@@ -3880,7 +3790,7 @@ msgstr "תאריך אירוע: {date_range}"
|
||||
#: pretix/base/invoicing/peppol.py:136
|
||||
msgid ""
|
||||
"A Peppol participant ID always starts with a prefix, followed by a colon (:)."
|
||||
msgstr ""
|
||||
msgstr "מזהה משתתף של פפול תמיד מתחיל בתחילית ואחריה נקודתיים(:)."
|
||||
|
||||
#: pretix/base/invoicing/peppol.py:140
|
||||
#, python-format
|
||||
@@ -3888,6 +3798,8 @@ msgid ""
|
||||
"The Peppol participant ID prefix %(number)s is not known to our system. "
|
||||
"Please reach out to us if you are sure this ID is correct."
|
||||
msgstr ""
|
||||
"תחילית מזהה המשתתף של פפול %(number)s אינה מוכרת למערכת. צור עימנו קשר אם "
|
||||
"אתה בטוח שזהו המזהה הנכון."
|
||||
|
||||
#: pretix/base/invoicing/peppol.py:144
|
||||
#, python-format
|
||||
@@ -3895,21 +3807,21 @@ msgid ""
|
||||
"The Peppol participant ID does not match the validation rules for the prefix "
|
||||
"%(number)s. Please reach out to us if you are sure this ID is correct."
|
||||
msgstr ""
|
||||
"מזהה המשתתף של פפול אינו תואם לחוקי הולידציה של התחילית %(number)s. צור "
|
||||
"עימנו קשר אם אתה בטוח שהמזהה נכון."
|
||||
|
||||
#: pretix/base/invoicing/peppol.py:166
|
||||
msgid "The Peppol participant ID is not registered on the Peppol network."
|
||||
msgstr ""
|
||||
msgstr "מזהה המשתתף של פפול אינו רשום ברשת פפול."
|
||||
|
||||
#: pretix/base/invoicing/peppol.py:192
|
||||
msgid "Peppol participant ID"
|
||||
msgstr ""
|
||||
msgstr "מזהה משתתף פפול"
|
||||
|
||||
#: pretix/base/invoicing/peppol.py:208
|
||||
#, fuzzy
|
||||
#| msgid "Gift card code"
|
||||
msgctxt "peppol_invoice"
|
||||
msgid "Visual copy"
|
||||
msgstr "קוד כרטיס מתנה"
|
||||
msgstr "עותק ויזואלי"
|
||||
|
||||
#: pretix/base/invoicing/peppol.py:213
|
||||
msgctxt "peppol_invoice"
|
||||
@@ -3918,6 +3830,8 @@ msgid ""
|
||||
"invoice for VAT purposes. The original invoice is issued in XML format and "
|
||||
"transmitted through the Peppol network."
|
||||
msgstr ""
|
||||
"קובץ PDF זה הינו העתק ויזואלי של החשבונית ואינו מהווה חשבונית לצרכי מע\"מ. "
|
||||
"החשבונית המקורית מופקת בפורמט XML ומשודרת דרך רשת פפול."
|
||||
|
||||
#: pretix/base/logentrytype_registry.py:43
|
||||
msgid ""
|
||||
@@ -4030,7 +3944,7 @@ msgstr "נמצאו מספר תאריכים תואמים."
|
||||
|
||||
#: pretix/base/modelimport_orders.py:73
|
||||
msgid "Grouping"
|
||||
msgstr ""
|
||||
msgstr "קיבוץ"
|
||||
|
||||
#: pretix/base/modelimport_orders.py:75
|
||||
msgid ""
|
||||
@@ -4038,6 +3952,8 @@ msgid ""
|
||||
"together...\". Lines with the same grouping value will be put in the same "
|
||||
"order, but MUST be consecutive lines of the input file."
|
||||
msgstr ""
|
||||
"ישים רק כש\"מצב יבוא\" מוגדר ל\"קיבוץ מספר שורות יחד...\". שורות עם אותו ערך "
|
||||
"קיבוץ יוצבו באותו סדר, אך חייבים להיות שורות רציפות של קובץ הקלט."
|
||||
|
||||
#: pretix/base/modelimport_orders.py:101
|
||||
msgid "Enter a valid phone number."
|
||||
@@ -4049,6 +3965,8 @@ msgid ""
|
||||
"The date can be specified through its full name, full date and time, or "
|
||||
"internal ID, provided only one date in the system matches the input."
|
||||
msgstr ""
|
||||
"התאריך ניתן לציון דרך השם המלא, התאריך והשעה המלאים, או מזהה פנימי בתנאי "
|
||||
"שהמזהה תואם רק תאריך אחד."
|
||||
|
||||
#: pretix/base/modelimport_orders.py:120 pretix/presale/views/waiting.py:157
|
||||
msgctxt "subevent"
|
||||
@@ -4058,7 +3976,7 @@ msgstr "עליך לבחור תאריך."
|
||||
#: pretix/base/modelimport_orders.py:131
|
||||
msgid ""
|
||||
"The product can be specified by its internal ID, full name or internal name."
|
||||
msgstr ""
|
||||
msgstr "המוצר ניתן לציון ע\"י מזהה פנימי, שם מלא או שם פנימי."
|
||||
|
||||
#: pretix/base/modelimport_orders.py:149
|
||||
#: pretix/base/modelimport_vouchers.py:194
|
||||
@@ -4078,7 +3996,7 @@ msgstr "וריאציית מוצר"
|
||||
|
||||
#: pretix/base/modelimport_orders.py:161
|
||||
msgid "The variation can be specified by its internal ID or full name."
|
||||
msgstr ""
|
||||
msgstr "הוריאציה ניתנת לציון לפי מזהה פנימי או שם מלא."
|
||||
|
||||
#: pretix/base/modelimport_orders.py:181
|
||||
#: pretix/base/modelimport_vouchers.py:225
|
||||
@@ -4097,10 +4015,8 @@ msgid "You need to select a variation for this product."
|
||||
msgstr "עליך לבחור וריאציה למוצר זה."
|
||||
|
||||
#: pretix/base/modelimport_orders.py:265 pretix/base/modelimport_orders.py:417
|
||||
#, fuzzy
|
||||
#| msgid "The count needs to be equal to or greater than zero."
|
||||
msgid "The country needs to be specified using a two-letter country code."
|
||||
msgstr "הכמות צריכה להיות שווה או גדולה מאפס."
|
||||
msgstr "המדינה נדרשת להזנה לפי קוד מדינה בין 2 אותיות."
|
||||
|
||||
#: pretix/base/modelimport_orders.py:281 pretix/base/modelimport_orders.py:432
|
||||
msgid "Please enter a valid country code."
|
||||
@@ -4108,7 +4024,7 @@ msgstr "נא להזין קוד ארץ תקין."
|
||||
|
||||
#: pretix/base/modelimport_orders.py:290 pretix/base/modelimport_orders.py:441
|
||||
msgid "The state can be specified by its short form or full name."
|
||||
msgstr ""
|
||||
msgstr "המדינה ניתנת להזנה ע\"י שימוש בקיצור או בשמה המלא."
|
||||
|
||||
#: pretix/base/modelimport_orders.py:300 pretix/base/modelimport_orders.py:450
|
||||
msgid "States are not supported for this country."
|
||||
@@ -4164,17 +4080,15 @@ msgstr "אנא הזן קוד שפה תקין."
|
||||
msgid ""
|
||||
"The sales channel can be specified by it's internal identifier or its full "
|
||||
"name."
|
||||
msgstr ""
|
||||
msgstr "ערוץ המכירה ניתן להזנה ע\"י מזהה פנימי או שם מלא."
|
||||
|
||||
#: pretix/base/modelimport_orders.py:599 pretix/base/modelimport_orders.py:601
|
||||
msgid "Please enter a valid sales channel."
|
||||
msgstr "אנא הזן ערוץ מכירות תקין."
|
||||
|
||||
#: pretix/base/modelimport_orders.py:611
|
||||
#, fuzzy
|
||||
#| msgid "The refund amount needs to be positive and less than {}."
|
||||
msgid "The seat needs to be specified by its internal ID."
|
||||
msgstr "סכום ההחזר חייב להיות חיובי ופחות מ-{}."
|
||||
msgstr "המושב חייב להיות מצויין לפי המזהה הפנימי."
|
||||
|
||||
#: pretix/base/modelimport_orders.py:626
|
||||
#: pretix/base/modelimport_vouchers.py:291
|
||||
@@ -4376,17 +4290,17 @@ msgid ""
|
||||
"to confirm changing your email address from {old_email}\n"
|
||||
"to {new_email}, use the following code:"
|
||||
msgstr ""
|
||||
"לאימות שינוי כתובת הדוא\"ל מ{old_email} \n"
|
||||
"ל {new_email}, השתמש בקוד הבא:"
|
||||
|
||||
#: pretix/base/models/auth.py:377
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"to confirm that your email address {email} belongs to your pretix account, "
|
||||
"use the following code:"
|
||||
msgstr ""
|
||||
msgstr "לאימות שכתובת הדוא\"ל {email} שייכת לחשבונך, השתמש בקוד הבא:"
|
||||
|
||||
#: pretix/base/models/auth.py:391
|
||||
#, fuzzy
|
||||
#| msgid "Confirmation code"
|
||||
msgid "pretix confirmation code"
|
||||
msgstr "קוד אישור"
|
||||
|
||||
@@ -4646,21 +4560,19 @@ msgstr "הפרד בין ערכים מרובים באמצעות רווחים"
|
||||
|
||||
#: pretix/base/models/datasync.py:53
|
||||
msgid "Temporary error, auto-retry limit exceeded"
|
||||
msgstr ""
|
||||
msgstr "שגיאה זמנית, מכסת הניסיונות מחדש האוטומטיים נחרגה"
|
||||
|
||||
#: pretix/base/models/datasync.py:54
|
||||
#, fuzzy
|
||||
#| msgid "Stripe reported an error: %s"
|
||||
msgid "Provider reported a permanent error"
|
||||
msgstr "Stripe דיווח על שגיאה: %s"
|
||||
msgstr "הספק דיווח על שגיאה קבועה"
|
||||
|
||||
#: pretix/base/models/datasync.py:55
|
||||
msgid "Misconfiguration, please check provider settings"
|
||||
msgstr ""
|
||||
msgstr "שגיאת הגדרה, בדוק את הגדרות הספק"
|
||||
|
||||
#: pretix/base/models/datasync.py:56 pretix/base/models/datasync.py:57
|
||||
msgid "System error, needs manual intervention"
|
||||
msgstr ""
|
||||
msgstr "תקלת מערכת, נדרשת התערבות ידנית"
|
||||
|
||||
#: pretix/base/models/devices.py:70 pretix/base/models/items.py:1675
|
||||
msgid "Internal identifier"
|
||||
@@ -4908,13 +4820,15 @@ msgstr "לא חובה. לא יימכרו מוצרים לפני תאריך זה."
|
||||
|
||||
#: pretix/base/models/event.py:644
|
||||
msgid "This event is remote or partially remote."
|
||||
msgstr ""
|
||||
msgstr "אירוע זה הינו אירוע וירטואלי או חלקית וירטואלי."
|
||||
|
||||
#: pretix/base/models/event.py:645
|
||||
msgid ""
|
||||
"This will be used to let users know if the event is in a different timezone "
|
||||
"and let’s us calculate users’ local times."
|
||||
msgstr ""
|
||||
"זה ישמש לעדכן את המשתמשים לדעת אם השעה המצויינת הינה באזור זמן שונה ויאפשר "
|
||||
"לנו לחשב את השעה בהתאם לשעון המקומי של המשתמשים."
|
||||
|
||||
#: pretix/base/models/event.py:665 pretix/base/models/organizer.py:97
|
||||
#: pretix/control/navigation.py:65 pretix/control/navigation.py:499
|
||||
@@ -5191,7 +5105,7 @@ msgstr "יתרה ממתינה"
|
||||
|
||||
#: pretix/base/models/invoices.py:123
|
||||
msgid "currently being transmitted"
|
||||
msgstr ""
|
||||
msgstr "משודר כרגע"
|
||||
|
||||
#: pretix/base/models/invoices.py:124
|
||||
#, fuzzy
|
||||
@@ -6086,6 +6000,8 @@ msgid ""
|
||||
"with changing the type of question without data loss. Consider hiding this "
|
||||
"question and creating a new one instead."
|
||||
msgstr ""
|
||||
"המערכת כבר כוללת תשובות לשאלה זו שאינם מאפשרות שינוי סוג השאלה מבלי לאבד "
|
||||
"מידע. מומלץ לשקול להסתיר את שאלה זו וליצור חדשה במקום."
|
||||
|
||||
#: pretix/base/models/items.py:1961
|
||||
#: pretix/control/templates/pretixcontrol/items/question.html:75
|
||||
@@ -8026,6 +7942,9 @@ msgid ""
|
||||
"2017-05-31 14:00 – 16:00\n"
|
||||
"2017-05-31 14:00 – 2017-06-01 14:00"
|
||||
msgstr ""
|
||||
"2017-05-31 10:00 – 12:00\n"
|
||||
"2017-05-31 14:00 – 16:00\n"
|
||||
"2017-05-31 14:00 – 2017-06-01 14:00"
|
||||
|
||||
#: pretix/base/pdf.py:500
|
||||
msgid "Reusable Medium ID"
|
||||
@@ -8234,7 +8153,7 @@ msgstr "בחרת מוצר שאינו זמין למכירה."
|
||||
msgid ""
|
||||
"Some products can no longer be purchased and have been removed from your "
|
||||
"cart for the following reason: %s"
|
||||
msgstr ""
|
||||
msgstr "חלק מהמוצרים לא ניתנים לרכישה יותר והוסרו מעגלת הקניות מהסיבה הבאה: %s"
|
||||
|
||||
#: pretix/base/services/cart.py:117
|
||||
msgid ""
|
||||
@@ -8984,7 +8903,7 @@ msgstr "ההזמנה אינה יכולה להכיל יותר מ־%(max)s עמד
|
||||
msgid ""
|
||||
"The grouping \"%(value)s\" occurs on non-consecutive lines (seen again on "
|
||||
"line %(row)s)."
|
||||
msgstr ""
|
||||
msgstr "הקיבוץ \"%(value)s\" מתקיים בשורות לא רציפות (נראה שוב בשורה %(row)s)."
|
||||
|
||||
#: pretix/base/services/modelimport.py:154
|
||||
#, python-brace-format
|
||||
@@ -8992,6 +8911,8 @@ msgid ""
|
||||
"Inconsistent data in row {row}: Column {col} contains value \"{val_line}\", "
|
||||
"but for this order, the value has already been set to \"{val_order}\"."
|
||||
msgstr ""
|
||||
"מידע לא רציף בשורה {row}: טור {col} מכיל ערך \"{val_line}\", אך להזמנה זו, "
|
||||
"הערך כבר הוגדר ל \"{val_order}\"."
|
||||
|
||||
#: pretix/base/services/modelimport.py:168
|
||||
#: pretix/base/services/modelimport.py:289
|
||||
@@ -9433,15 +9354,15 @@ msgstr "השובר נשלח ל-{recipient}."
|
||||
|
||||
#: pretix/base/settings.py:82
|
||||
msgid "Compute taxes for every line individually"
|
||||
msgstr ""
|
||||
msgstr "חשב מיסים לכל שורה בנפרד"
|
||||
|
||||
#: pretix/base/settings.py:83
|
||||
msgid "Compute taxes based on net total"
|
||||
msgstr ""
|
||||
msgstr "חשב מיסים תוך ביסוס על סה\"כ נטו"
|
||||
|
||||
#: pretix/base/settings.py:84
|
||||
msgid "Compute taxes based on net total with stable gross prices"
|
||||
msgstr ""
|
||||
msgstr "חשב מיסים על סה\"כ נטו עם ברוטו יציב"
|
||||
|
||||
#: pretix/base/settings.py:134
|
||||
msgid "Allow usage of restricted plugins"
|
||||
@@ -9470,7 +9391,7 @@ msgstr "אם אפשרות זו מושבתת, תצטרך לחבר ספקי זיה
|
||||
|
||||
#: pretix/base/settings.py:189
|
||||
msgid "Require login to access order confirmation pages"
|
||||
msgstr ""
|
||||
msgstr "דרוש כניסה למשתמש על מנת לגשת לדפי אישור הזמנה"
|
||||
|
||||
#: pretix/base/settings.py:190
|
||||
msgid ""
|
||||
@@ -9479,6 +9400,9 @@ msgid ""
|
||||
"placing an order, the restriction only becomes active after the customer "
|
||||
"account is activated."
|
||||
msgstr ""
|
||||
"אם מופעל, משתמשים שהיו מחוברים לאתר בזמן רכישה יצטרכו להתחבר לחשבונם באתר על "
|
||||
"מנת לגשת לפרטי ההזמנה שלהם. אם החשבון נוצר במהלך הרכישה, ההגבלה נכנסת לתוקף "
|
||||
"רק לאחר הפעלת החשבון."
|
||||
|
||||
#: pretix/base/settings.py:202
|
||||
msgid "Match orders based on email address"
|
||||
@@ -9658,6 +9582,8 @@ msgid ""
|
||||
"for tax reporting, you need to make sure to account for possible rounding "
|
||||
"differences if your external system rounds differently than pretix."
|
||||
msgstr ""
|
||||
"שים לב- במידה ותייצא את נתוני המכירות שלך למערכת חיצונית לדיווח מס, עלייך "
|
||||
"לקחת בחשבון כי ייתכנו פערים אם המערכת החיצונית מבצעת עיגול בצורה שונה."
|
||||
|
||||
#: pretix/base/settings.py:514
|
||||
msgid "Ask for invoice address"
|
||||
@@ -9786,6 +9712,8 @@ msgid ""
|
||||
"ID in all countries. VAT ID will be required for all business addresses in "
|
||||
"the selected countries."
|
||||
msgstr ""
|
||||
"מספר עסק מגדר כרשות כברירת מחדל מאחר ובחלק מהמדינות ישנם עסקים שלא מוקצה להם "
|
||||
"מספר עסק. מספר עסק יוגדר כחובה בכל המדינות הנבחרות."
|
||||
|
||||
#: pretix/base/settings.py:685
|
||||
msgid "Invoice address explanation"
|
||||
@@ -10172,10 +10100,12 @@ msgid ""
|
||||
"Automatic based on ticket-specific validity, membership validity, event "
|
||||
"series date, or event date"
|
||||
msgstr ""
|
||||
"אוטומטי בהתאם לזמינות הכרטיס הספציפי, זמינות המנוי, תאריכי סדרת האירועים או "
|
||||
"תאריך האירוע"
|
||||
|
||||
#: pretix/base/settings.py:1179 pretix/base/settings.py:1190
|
||||
msgid "Automatic, but prefer invoice date over event date"
|
||||
msgstr ""
|
||||
msgstr "אוטומטי, אבל העדף תאריך חשבונית על תאריך אירוע"
|
||||
|
||||
#: pretix/base/settings.py:1182 pretix/base/settings.py:1193
|
||||
#, fuzzy
|
||||
@@ -10196,6 +10126,7 @@ msgid ""
|
||||
"This controls what dates are shown on the invoice, but is especially "
|
||||
"important for electronic invoicing."
|
||||
msgstr ""
|
||||
"זה שולט על איזה תאריכים מוצגים על החשבונית, ובמיוחד חשוב לחשבוניות דיגיטליות."
|
||||
|
||||
#: pretix/base/settings.py:1206
|
||||
msgid "Automatically cancel and reissue invoice on address changes"
|
||||
@@ -12767,7 +12698,7 @@ msgstr "אם זה לוקח יותר מכמה דקות, רענן את הדף או
|
||||
#: pretix/base/templates/pretixbase/email/cancel_confirm.txt:2
|
||||
msgid ""
|
||||
"You have requested us to cancel an event which includes a larger bulk-refund:"
|
||||
msgstr ""
|
||||
msgstr "ביקשת מאיתנו לבטל אירוע שכולל החזר כספי גדול יותר:"
|
||||
|
||||
#: pretix/base/templates/pretixbase/email/cancel_confirm.txt:6
|
||||
#, fuzzy
|
||||
@@ -12780,6 +12711,7 @@ msgid ""
|
||||
"Please confirm that you want to proceed by coping the following confirmation "
|
||||
"code into the cancellation form:"
|
||||
msgstr ""
|
||||
"נא לאשר שברצונך להמשיך באמצעות העתקה של קוד האימות הבא לתוך טופס הביטול:"
|
||||
|
||||
#: pretix/base/templates/pretixbase/email/email_footer.html:3
|
||||
#, python-format
|
||||
@@ -13457,7 +13389,7 @@ msgstr "כל השערים"
|
||||
|
||||
#: pretix/control/forms/checkin.py:222
|
||||
msgid "I am sure that the check-in state of the entire event should be reset."
|
||||
msgstr ""
|
||||
msgstr "אני בטוח שמצב הצ'ק אין של האירוע צריך לעבור איפוס."
|
||||
|
||||
#: pretix/control/forms/event.py:91
|
||||
msgid "Use languages"
|
||||
@@ -13556,7 +13488,7 @@ msgstr "ברירת מחדל ({value})"
|
||||
|
||||
#: pretix/control/forms/event.py:381
|
||||
msgid "The currency cannot be changed because orders already exist."
|
||||
msgstr ""
|
||||
msgstr "לא ניתן לבצע שינוי בסוג המטבע מאחר והזמנות כבר קיימות."
|
||||
|
||||
#: pretix/control/forms/event.py:392 pretix/control/forms/event.py:405
|
||||
msgid "Domain"
|
||||
@@ -13644,7 +13576,7 @@ msgstr "כולל כל המיסים"
|
||||
|
||||
#: pretix/control/forms/event.py:815
|
||||
msgid "Recommended if you sell tickets at least partly to consumers."
|
||||
msgstr ""
|
||||
msgstr "מומלץ אם תמכור כרטיסים לפחות חלקית ללקוחות."
|
||||
|
||||
#: pretix/control/forms/event.py:819
|
||||
#, fuzzy
|
||||
@@ -13655,7 +13587,7 @@ msgstr "כל העתיד (לא כולל היום)"
|
||||
|
||||
#: pretix/control/forms/event.py:820
|
||||
msgid "Recommended only if you sell tickets primarily to business customers."
|
||||
msgstr ""
|
||||
msgstr "מומלץ רק אם תמכור כרטיסים בעיקר ללקוחות עסקיים."
|
||||
|
||||
#: pretix/control/forms/event.py:856
|
||||
#, fuzzy
|
||||
@@ -13885,6 +13817,7 @@ msgid ""
|
||||
"This will only be used if the invoice is sent to a different email address "
|
||||
"or at a different time than the order confirmation."
|
||||
msgstr ""
|
||||
"זה ישומש רק אם החשבונית תישלח לכתובת מייל אחרת או בזמן אחר מאישור ההזמנה."
|
||||
|
||||
#: pretix/control/forms/event.py:1321
|
||||
msgid ""
|
||||
@@ -14335,7 +14268,7 @@ msgstr "שולם"
|
||||
#: pretix/control/forms/filter.py:1304
|
||||
msgctxt "subevent"
|
||||
msgid "Date doesn't start in selected date range."
|
||||
msgstr ""
|
||||
msgstr "תאריך לא מתחיל בטווח התאריכים שנבחר."
|
||||
|
||||
#: pretix/control/forms/filter.py:1360 pretix/control/forms/filter.py:1827
|
||||
msgid "Shop live and presale running"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,8 +8,8 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-01-26 13:19+0000\n"
|
||||
"PO-Revision-Date: 2025-12-19 00:00+0000\n"
|
||||
"Last-Translator: Daniel Branda <daniel.branda.ad@gmail.com>\n"
|
||||
"PO-Revision-Date: 2026-02-10 16:49+0000\n"
|
||||
"Last-Translator: Michele Pagnozzi <michele.pagnozzi@gmail.com>\n"
|
||||
"Language-Team: Italian <https://translate.pretix.eu/projects/pretix/pretix/"
|
||||
"it/>\n"
|
||||
"Language: it\n"
|
||||
@@ -17,7 +17,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 5.15\n"
|
||||
"X-Generator: Weblate 5.15.2\n"
|
||||
|
||||
#: pretix/_base_settings.py:87
|
||||
msgid "English"
|
||||
@@ -966,7 +966,7 @@ msgstr "Indirizzo di fatturazione dell'azienda"
|
||||
#: pretix/base/exporters/orderlist.py:688
|
||||
#: pretix/base/exporters/orderlist.py:692 pretix/base/pdf.py:341
|
||||
msgid "Invoice address name"
|
||||
msgstr "Nome dell'indirizzo di fatturazione"
|
||||
msgstr "Indirizzo di fatturazione"
|
||||
|
||||
#: pretix/base/datasync/sourcefields.py:317
|
||||
#: pretix/base/exporters/orderlist.py:694 pretix/base/pdf.py:351
|
||||
|
||||
@@ -8,8 +8,8 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-01-26 09:10+0000\n"
|
||||
"PO-Revision-Date: 2025-05-05 09:40+0000\n"
|
||||
"Last-Translator: \"Luca Martinelli [Sannita]\" <sannita@gmail.com>\n"
|
||||
"PO-Revision-Date: 2026-02-10 16:49+0000\n"
|
||||
"Last-Translator: Raffaele Doretto <ced@comune.portogruaro.ve.it>\n"
|
||||
"Language-Team: Italian <https://translate.pretix.eu/projects/pretix/pretix-"
|
||||
"js/it/>\n"
|
||||
"Language: it\n"
|
||||
@@ -17,7 +17,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 5.11.1\n"
|
||||
"X-Generator: Weblate 5.15.2\n"
|
||||
|
||||
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:56
|
||||
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:62
|
||||
@@ -1134,6 +1134,9 @@ msgid ""
|
||||
"add yourself to the waiting list. We will then notify if seats are available "
|
||||
"again."
|
||||
msgstr ""
|
||||
"Alcune o tutte le categorie di biglietti sono attualmente esaurite. Se lo "
|
||||
"desideri, puoi aggiungerti alla lista d'attesa. Ti informeremo se i posti "
|
||||
"saranno nuovamente disponibili."
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:76
|
||||
msgctxt "widget"
|
||||
|
||||
+1164
-1207
File diff suppressed because it is too large
Load Diff
@@ -8,8 +8,8 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-01-26 09:10+0000\n"
|
||||
"PO-Revision-Date: 2025-11-18 17:00+0000\n"
|
||||
"Last-Translator: Hijiri Umemoto <hijiri@umemoto.org>\n"
|
||||
"PO-Revision-Date: 2026-02-12 20:00+0000\n"
|
||||
"Last-Translator: Yasunobu YesNo Kawaguchi <kawaguti@gmail.com>\n"
|
||||
"Language-Team: Japanese <https://translate.pretix.eu/projects/pretix/pretix-"
|
||||
"js/ja/>\n"
|
||||
"Language: ja\n"
|
||||
@@ -17,7 +17,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"X-Generator: Weblate 5.14.3\n"
|
||||
"X-Generator: Weblate 5.15.2\n"
|
||||
|
||||
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:56
|
||||
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:62
|
||||
@@ -27,7 +27,7 @@ msgstr "支払い済み"
|
||||
|
||||
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:76
|
||||
msgid "Comment:"
|
||||
msgstr "注釈:"
|
||||
msgstr "コメント:"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:34
|
||||
msgid "PayPal"
|
||||
@@ -152,22 +152,22 @@ msgstr "支払い方法が利用できません"
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:15
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:63
|
||||
msgid "Placed orders"
|
||||
msgstr "受注状況"
|
||||
msgstr "受注件数"
|
||||
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:15
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:63
|
||||
msgid "Paid orders"
|
||||
msgstr "支払い済みの注文"
|
||||
msgstr "支払い済み件数"
|
||||
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:27
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:39
|
||||
msgid "Attendees (ordered)"
|
||||
msgstr ""
|
||||
msgstr "参加者 (注文済み)"
|
||||
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:27
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:39
|
||||
msgid "Attendees (paid)"
|
||||
msgstr ""
|
||||
msgstr "参加者 (支払い済み)"
|
||||
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:51
|
||||
msgid "Total revenue"
|
||||
@@ -191,7 +191,7 @@ msgstr "チェックインリストを選択してください"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:31
|
||||
msgid "No active check-in lists found."
|
||||
msgstr "アクティブなチェックインリストは見つかりません。"
|
||||
msgstr "有効なチェックインリストが見つかりません。"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:32
|
||||
msgid "Switch check-in list"
|
||||
@@ -199,7 +199,7 @@ msgstr "チェックインリストを切り替え"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:33
|
||||
msgid "Search results"
|
||||
msgstr "結果を検索する"
|
||||
msgstr "検索結果"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:34
|
||||
msgid "No tickets found"
|
||||
@@ -215,15 +215,15 @@ msgstr "このチケットは特別な対応が必要です"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:37
|
||||
msgid "Switch direction"
|
||||
msgstr "方向転換"
|
||||
msgstr "向きを切り替え"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:38
|
||||
msgid "Entry"
|
||||
msgstr "エントリー"
|
||||
msgstr "入場"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:39
|
||||
msgid "Exit"
|
||||
msgstr "退出"
|
||||
msgstr "退場"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:40
|
||||
msgid "Scan a ticket or search and press return…"
|
||||
@@ -281,7 +281,7 @@ msgstr "有効なチケット"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:55
|
||||
msgid "Exit recorded"
|
||||
msgstr "記録を保存"
|
||||
msgstr "退出を記録しました"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:56
|
||||
msgid "Ticket already used"
|
||||
@@ -297,15 +297,15 @@ msgstr "不明なチケット"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:59
|
||||
msgid "Ticket type not allowed here"
|
||||
msgstr "この種類のチケットは使用できません"
|
||||
msgstr "この種類のチケットはここでは使用できません"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:61
|
||||
msgid "Entry not allowed"
|
||||
msgstr "入力できません"
|
||||
msgstr "入場できません"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:62
|
||||
msgid "Ticket code revoked/changed"
|
||||
msgstr "チケットコードのブロック/変更"
|
||||
msgstr "チケットコードが取り消し/変更されました"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:63
|
||||
msgid "Ticket blocked"
|
||||
@@ -321,11 +321,11 @@ msgstr "注文がキャンセルされました"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:66
|
||||
msgid "Ticket code is ambiguous on list"
|
||||
msgstr "リストのチケットコードは曖昧です"
|
||||
msgstr "リスト上でチケットコードが一意に特定できません"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:67
|
||||
msgid "Order not approved"
|
||||
msgstr "承認されない注文"
|
||||
msgstr "未承認の注文"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:68
|
||||
msgid "Checked-in Tickets"
|
||||
@@ -358,7 +358,7 @@ msgstr "閉じる"
|
||||
#: pretix/static/pretixbase/js/addressform.js:101
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:529
|
||||
msgid "required"
|
||||
msgstr "必要"
|
||||
msgstr "必須"
|
||||
|
||||
#: pretix/static/pretixbase/js/asynctask.js:13
|
||||
msgid ""
|
||||
@@ -370,8 +370,7 @@ msgstr ""
|
||||
|
||||
#: pretix/static/pretixbase/js/asynctask.js:17
|
||||
msgid "Your request has been queued on the server and will soon be processed."
|
||||
msgstr ""
|
||||
"サーバへ送信されたリクエスト順にお応えしています。今しばらくお待ちください。"
|
||||
msgstr "お客様のリクエストはサーバーで受け付けられました。まもなく処理されます。"
|
||||
|
||||
#: pretix/static/pretixbase/js/asynctask.js:21
|
||||
msgid ""
|
||||
@@ -394,8 +393,7 @@ msgstr "{code} のエラーが発生しました。"
|
||||
msgid ""
|
||||
"We currently cannot reach the server, but we keep trying. Last error code: "
|
||||
"{code}"
|
||||
msgstr ""
|
||||
"現在サーバへの接続ができませんが、接続試行中です。エラーコード: {code}"
|
||||
msgstr "現在サーバへの接続ができませんが、接続試行中です。最新のエラーコード: {code}"
|
||||
|
||||
#: pretix/static/pretixbase/js/asynctask.js:162
|
||||
#: pretix/static/pretixcontrol/js/ui/mail.js:21
|
||||
@@ -419,9 +417,8 @@ msgid ""
|
||||
"than one minute, please check your internet connection and then reload this "
|
||||
"page and try again."
|
||||
msgstr ""
|
||||
"リクエストがサーバへ送信されました。1分以上経っても応答がない場合は、イン"
|
||||
"ターネット接続を確認してください。確認完了後、ウェブページを再度読込み、再試"
|
||||
"行してください。"
|
||||
"現在リクエストをサーバへ送信中です。1分以上経っても応答がない場合は、"
|
||||
"インターネット接続を確認し、このページを再読み込みして再試行してください。"
|
||||
|
||||
#: pretix/static/pretixbase/js/asynctask.js:276
|
||||
msgid "If this takes longer than a few minutes, please contact us."
|
||||
@@ -429,7 +426,7 @@ msgstr "数分以上かかる場合は、お問い合わせください。"
|
||||
|
||||
#: pretix/static/pretixbase/js/asynctask.js:331
|
||||
msgid "Close message"
|
||||
msgstr "閉じる"
|
||||
msgstr "メッセージを閉じる"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/clipboard.js:23
|
||||
msgid "Copied!"
|
||||
@@ -443,7 +440,7 @@ msgstr "Ctrl-Cを押してコピー!"
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:18
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:24
|
||||
msgid "is one of"
|
||||
msgstr "の一つです"
|
||||
msgstr "次のいずれか"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:30
|
||||
msgid "is before"
|
||||
@@ -463,7 +460,7 @@ msgstr "製品"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:103
|
||||
msgid "Product variation"
|
||||
msgstr "商品の種類"
|
||||
msgstr "製品バリエーション"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:107
|
||||
msgid "Gate"
|
||||
@@ -479,51 +476,51 @@ msgstr "現在の曜日 (1 = 月曜日, 7 = 日曜日)"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:119
|
||||
msgid "Current entry status"
|
||||
msgstr "現在の登録ステータス"
|
||||
msgstr "現在の入場状態"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:123
|
||||
msgid "Number of previous entries"
|
||||
msgstr "これまでの入力件数"
|
||||
msgstr "これまでの入場回数"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:127
|
||||
msgid "Number of previous entries since midnight"
|
||||
msgstr "0時から現在までの入力件数"
|
||||
msgstr "0時から現在までの入場回数"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:131
|
||||
msgid "Number of previous entries since"
|
||||
msgstr "この時点から今までの入力件数"
|
||||
msgstr "この時点から今までの入場回数"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:135
|
||||
msgid "Number of previous entries before"
|
||||
msgstr "この時点より前に入力された件数"
|
||||
msgstr "この時点より前の入場回数"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:139
|
||||
msgid "Number of days with a previous entry"
|
||||
msgstr "これまでの入力日数"
|
||||
msgstr "これまでの入場日数"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:143
|
||||
msgid "Number of days with a previous entry since"
|
||||
msgstr "この時点より後に入力が行われた日数"
|
||||
msgstr "この時点より後に入場があった日数"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:147
|
||||
msgid "Number of days with a previous entry before"
|
||||
msgstr "この時点より前に入力が行われた日数"
|
||||
msgstr "この時点より前に入場があった日数"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:151
|
||||
msgid "Minutes since last entry (-1 on first entry)"
|
||||
msgstr "最後の登録からの経過分数(最初の登録は-1)"
|
||||
msgstr "最後の入場からの経過分数(最初の入場は-1)"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:155
|
||||
msgid "Minutes since first entry (-1 on first entry)"
|
||||
msgstr "最初のとうろくからの経過分数(最初の登録は-1)"
|
||||
msgstr "最初の入場からの経過分数(最初の入場は-1)"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:182
|
||||
msgid "All of the conditions below (AND)"
|
||||
msgstr "以下全ての条件(と)"
|
||||
msgstr "以下のすべての条件(AND)"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:183
|
||||
msgid "At least one of the conditions below (OR)"
|
||||
msgstr "以下の条件のうち、最低1つ(または)"
|
||||
msgstr "以下の条件のうち、最低1つ(OR)"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:184
|
||||
msgid "Event start"
|
||||
@@ -539,11 +536,11 @@ msgstr "イベントの入場"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:187
|
||||
msgid "custom date and time"
|
||||
msgstr "日時確定"
|
||||
msgstr "カスタム日時"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:188
|
||||
msgid "custom time"
|
||||
msgstr "時刻確定"
|
||||
msgstr "カスタム時刻"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:189
|
||||
msgid "Tolerance (minutes)"
|
||||
@@ -564,16 +561,16 @@ msgstr "複製"
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:193
|
||||
msgctxt "entry_status"
|
||||
msgid "present"
|
||||
msgstr "出席"
|
||||
msgstr "入場中"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:194
|
||||
msgctxt "entry_status"
|
||||
msgid "absent"
|
||||
msgstr "欠席"
|
||||
msgstr "未入場"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:289
|
||||
msgid "Error: Product not found!"
|
||||
msgstr "エラー:製品が見つかりません!"
|
||||
msgstr "エラー:商品が見つかりません!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:296
|
||||
msgid "Error: Variation not found!"
|
||||
@@ -585,7 +582,7 @@ msgstr "チェックイン用QRコード"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:549
|
||||
msgid "The PDF background file could not be loaded for the following reason:"
|
||||
msgstr "以下の理由によりPDFファイルの読み込みに失敗しました:"
|
||||
msgstr "以下の理由によりPDF背景ファイルの読み込みに失敗しました:"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:904
|
||||
msgid "Group of objects"
|
||||
@@ -593,7 +590,7 @@ msgstr "オブジェクトグループ"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:909
|
||||
msgid "Text object (deprecated)"
|
||||
msgstr "テキストオブジェクト (廃止済)"
|
||||
msgstr "テキストオブジェクト(非推奨)"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:911
|
||||
msgid "Text box"
|
||||
@@ -609,7 +606,7 @@ msgstr "画像エリア"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:917
|
||||
msgid "Powered by pretix"
|
||||
msgstr "Pretixのイベントチケット売り場"
|
||||
msgstr "Powered by pretix"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:919
|
||||
msgid "Object"
|
||||
@@ -647,24 +644,24 @@ msgstr "不明なエラー。"
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:309
|
||||
msgid "Your color has great contrast and will provide excellent accessibility."
|
||||
msgstr ""
|
||||
"あなたの色は素晴らしいコントラストを持ち、優れたアクセシビリティを提供しま"
|
||||
"す。"
|
||||
"選択した色は素晴らしいコントラストを持ち、優れたアクセシビリティを提供します"
|
||||
"。"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:313
|
||||
msgid ""
|
||||
"Your color has decent contrast and is sufficient for minimum accessibility "
|
||||
"requirements."
|
||||
msgstr ""
|
||||
"あなたの色は適切なコントラストを持ち、最小限のアクセシビリティ要件に十分で"
|
||||
"す。"
|
||||
"選択した色は適切なコントラストを持ち、最小限のアクセシビリティ要件に十分です"
|
||||
"。"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:317
|
||||
msgid ""
|
||||
"Your color has insufficient contrast to white. Accessibility of your site "
|
||||
"will be impacted."
|
||||
msgstr ""
|
||||
"あなたの色は白に対して十分なコントラストがありません。サイトのアクセシビリ"
|
||||
"ティに影響します。"
|
||||
"選択した色は白に対して十分なコントラストがありません。サイトの"
|
||||
"アクセシビリティに影響します。"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:443
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:463
|
||||
@@ -677,7 +674,7 @@ msgstr "全て"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:462
|
||||
msgid "None"
|
||||
msgstr "ない"
|
||||
msgstr "なし"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:466
|
||||
msgid "Selected only"
|
||||
@@ -693,7 +690,7 @@ msgstr "無効なページ番号。"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:1000
|
||||
msgid "Use a different name internally"
|
||||
msgstr "内部で別の名前を使用してください"
|
||||
msgstr "内部で別の名前を使用する"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:1040
|
||||
msgid "Click to close"
|
||||
@@ -722,15 +719,15 @@ msgstr "カウント"
|
||||
#: pretix/static/pretixcontrol/js/ui/subevent.js:112
|
||||
msgid "(one more date)"
|
||||
msgid_plural "({num} more dates)"
|
||||
msgstr[0] "({num} 他の日程)"
|
||||
msgstr[0] "(他に{num}件の日程)"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/cart.js:47
|
||||
msgid ""
|
||||
"The items in your cart are no longer reserved for you. You can still "
|
||||
"complete your order as long as they’re available."
|
||||
msgstr ""
|
||||
"カートに入っている商品は現在売り切れです。在庫があれば、このまま注文を完了す"
|
||||
"ることができます。"
|
||||
"カート内のアイテムの予約が解除されました。在庫がある限り、引き続き注文を完了"
|
||||
"できます。"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/cart.js:49
|
||||
msgid "Cart expired"
|
||||
@@ -744,27 +741,27 @@ msgstr "カートの有効期限が近づいています。"
|
||||
#: pretix/static/pretixpresale/js/ui/cart.js:62
|
||||
msgid "The items in your cart are reserved for you for one minute."
|
||||
msgid_plural "The items in your cart are reserved for you for {num} minutes."
|
||||
msgstr[0] "カート内の商品の予約は {num} 分以内に完了します。"
|
||||
msgstr[0] "カート内の商品はあと {num} 分間確保されています。"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/cart.js:83
|
||||
msgid "Your cart has expired."
|
||||
msgstr "カートの保存期限が切れています。"
|
||||
msgstr "カートの有効期限が切れています。"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/cart.js:86
|
||||
msgid ""
|
||||
"The items in your cart are no longer reserved for you. You can still "
|
||||
"complete your order as long as they're available."
|
||||
msgstr ""
|
||||
"カートに入っている商品はお取り置きできません。在庫があれば、このまま注文を進"
|
||||
"めることができます。"
|
||||
"カート内の商品の確保期限が切れました。在庫があれば、このまま注文を完了するこ"
|
||||
"とができます。"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/cart.js:87
|
||||
msgid "Do you want to renew the reservation period?"
|
||||
msgstr "予約の期間を更新しますか?"
|
||||
msgstr "確保期間を更新しますか?"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/cart.js:90
|
||||
msgid "Renew reservation"
|
||||
msgstr "予約を更新"
|
||||
msgstr "確保を更新"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:194
|
||||
msgid "The organizer keeps %(currency)s %(amount)s"
|
||||
@@ -780,7 +777,7 @@ msgstr "主催者が留保する料金を入力してください。"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:577
|
||||
msgid "Your local time:"
|
||||
msgstr "現地時間:"
|
||||
msgstr "お使いの地域の時刻:"
|
||||
|
||||
#: pretix/static/pretixpresale/js/walletdetection.js:39
|
||||
msgid "Google Pay"
|
||||
@@ -843,7 +840,7 @@ msgstr "%sを選択"
|
||||
#, javascript-format
|
||||
msgctxt "widget"
|
||||
msgid "Select variant %s"
|
||||
msgstr "バリアント %sを選択"
|
||||
msgstr "バリエーション %sを選択"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:27
|
||||
msgctxt "widget"
|
||||
@@ -853,7 +850,7 @@ msgstr "売り切れ"
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:28
|
||||
msgctxt "widget"
|
||||
msgid "Buy"
|
||||
msgstr "カート内"
|
||||
msgstr "購入"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:29
|
||||
msgctxt "widget"
|
||||
@@ -863,7 +860,7 @@ msgstr "登録"
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:30
|
||||
msgctxt "widget"
|
||||
msgid "Reserved"
|
||||
msgstr "予約完了"
|
||||
msgstr "予約済み"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:31
|
||||
msgctxt "widget"
|
||||
@@ -879,7 +876,7 @@ msgstr "%(currency)s %(price)sから"
|
||||
#, javascript-format
|
||||
msgctxt "widget"
|
||||
msgid "Image of %s"
|
||||
msgstr "%sのイメージ"
|
||||
msgstr "%sの画像"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:34
|
||||
msgctxt "widget"
|
||||
@@ -889,7 +886,7 @@ msgstr "%(rate)s% %(taxname)s込"
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:35
|
||||
msgctxt "widget"
|
||||
msgid "plus %(rate)s% %(taxname)s"
|
||||
msgstr "%(rate)s% %(taxname)s抜"
|
||||
msgstr "別途%(rate)s% %(taxname)s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:36
|
||||
msgctxt "widget"
|
||||
@@ -899,18 +896,18 @@ msgstr "税込"
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:37
|
||||
msgctxt "widget"
|
||||
msgid "plus taxes"
|
||||
msgstr "税抜"
|
||||
msgstr "税別"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:38
|
||||
#, javascript-format
|
||||
msgctxt "widget"
|
||||
msgid "currently available: %s"
|
||||
msgstr "現在%s使用可能"
|
||||
msgstr "現在の残数: %s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:39
|
||||
msgctxt "widget"
|
||||
msgid "Only available with a voucher"
|
||||
msgstr "クーポンをお持ちの方のみ"
|
||||
msgstr "バウチャーをお持ちの方のみ"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:40
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:43
|
||||
@@ -921,7 +918,7 @@ msgstr "提供開始前"
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:41
|
||||
msgctxt "widget"
|
||||
msgid "Not available anymore"
|
||||
msgstr "今後の提供不可"
|
||||
msgstr "提供終了"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:42
|
||||
msgctxt "widget"
|
||||
@@ -937,7 +934,7 @@ msgstr "最小注文数量:%s"
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:45
|
||||
msgctxt "widget"
|
||||
msgid "Close ticket shop"
|
||||
msgstr "チケットショップ閉店"
|
||||
msgstr "チケットショップを閉じる"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:46
|
||||
msgctxt "widget"
|
||||
@@ -950,8 +947,8 @@ msgid ""
|
||||
"There are currently a lot of users in this ticket shop. Please open the shop "
|
||||
"in a new tab to continue."
|
||||
msgstr ""
|
||||
"現在チケットショップが混み合っています。新しいタブでチケットショップを開き続"
|
||||
"行してください。"
|
||||
"現在チケットショップが混み合っています。新しいタブでチケットショップを開いて"
|
||||
"続行してください。"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:49
|
||||
msgctxt "widget"
|
||||
@@ -975,7 +972,7 @@ msgid ""
|
||||
"this ticket shop. Please click \"Continue\" to retry in a new tab."
|
||||
msgstr ""
|
||||
"現在チケットショップが混雑しているため、お客様のカートを作ることができません"
|
||||
"でした。新しいタブを開き「次へ」をクリックしてください。"
|
||||
"でした。\"続ける\"をクリックして、新しいタブで再試行してください。"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:54
|
||||
msgctxt "widget"
|
||||
@@ -988,8 +985,8 @@ msgid ""
|
||||
"You currently have an active cart for this event. If you select more "
|
||||
"products, they will be added to your existing cart."
|
||||
msgstr ""
|
||||
"お客様のカートはイベントの申し込みに有効です。商品を選択し、カートへ追加して"
|
||||
"ください。"
|
||||
"このイベントのカートに商品が入っています。商品を追加すると、既存のカートに追"
|
||||
"加されます。"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:57
|
||||
msgctxt "widget"
|
||||
@@ -999,7 +996,7 @@ msgstr "チェックアウトを続行する"
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:58
|
||||
msgctxt "widget"
|
||||
msgid "Redeem a voucher"
|
||||
msgstr "クーポンを使用する"
|
||||
msgstr "バウチャーを使用する"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:59
|
||||
msgctxt "widget"
|
||||
@@ -1009,7 +1006,7 @@ msgstr "使用する"
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:60
|
||||
msgctxt "widget"
|
||||
msgid "Voucher code"
|
||||
msgstr "クーポンコード"
|
||||
msgstr "バウチャーコード"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:61
|
||||
msgctxt "widget"
|
||||
@@ -1079,7 +1076,7 @@ msgstr "前週"
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:74
|
||||
msgctxt "widget"
|
||||
msgid "Open seat selection"
|
||||
msgstr "座席一覧を開く"
|
||||
msgstr "座席選択を開く"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:75
|
||||
msgctxt "widget"
|
||||
@@ -1095,7 +1092,7 @@ msgstr ""
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:76
|
||||
msgctxt "widget"
|
||||
msgid "Load more"
|
||||
msgstr "さらに読み込む"
|
||||
msgstr "もっと見る"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:78
|
||||
msgid "Mo"
|
||||
|
||||
@@ -8,16 +8,16 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-01-26 13:19+0000\n"
|
||||
"PO-Revision-Date: 2025-12-03 23:00+0000\n"
|
||||
"Last-Translator: SJang1 <git@sjang.dev>\n"
|
||||
"Language-Team: Korean <https://translate.pretix.eu/projects/pretix/pretix/ko/"
|
||||
">\n"
|
||||
"PO-Revision-Date: 2026-02-01 21:00+0000\n"
|
||||
"Last-Translator: z3rrry <z3rrry@gmail.com>\n"
|
||||
"Language-Team: Korean <https://translate.pretix.eu/projects/pretix/pretix/"
|
||||
"ko/>\n"
|
||||
"Language: ko\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"X-Generator: Weblate 5.14.3\n"
|
||||
"X-Generator: Weblate 5.15.2\n"
|
||||
|
||||
#: pretix/_base_settings.py:87
|
||||
msgid "English"
|
||||
@@ -2283,6 +2283,9 @@ msgid ""
|
||||
"contain at least one position of this product. The order totals etc. still "
|
||||
"include all products contained in the order."
|
||||
msgstr ""
|
||||
"아무것도 선택하지 않으면, 모든 상품이 포함됩니다. 상품이 1개 이상 포함되는 "
|
||||
"경우에 주문이 포함됩니다. 주문 합계 등에는 주문에 포함된 모든 상품이 "
|
||||
"포함됩니다."
|
||||
|
||||
#: pretix/base/exporters/orderlist.py:283
|
||||
#: pretix/base/exporters/orderlist.py:478
|
||||
@@ -2546,10 +2549,8 @@ msgid "Voucher"
|
||||
msgstr "바우처"
|
||||
|
||||
#: pretix/base/exporters/orderlist.py:653
|
||||
#, fuzzy
|
||||
#| msgid "Voucher deleted"
|
||||
msgid "Voucher budget usage"
|
||||
msgstr "바우처 제거됨"
|
||||
msgstr "바우처 예산 사용량"
|
||||
|
||||
#: pretix/base/exporters/orderlist.py:654
|
||||
msgid "Pseudonymization ID"
|
||||
@@ -26784,11 +26785,11 @@ msgstr ""
|
||||
|
||||
#: pretix/control/views/dashboards.py:114
|
||||
msgid "Attendees (ordered)"
|
||||
msgstr ""
|
||||
msgstr "참가자 (정렬된)"
|
||||
|
||||
#: pretix/control/views/dashboards.py:124
|
||||
msgid "Attendees (paid)"
|
||||
msgstr ""
|
||||
msgstr "참가자 (결제된)"
|
||||
|
||||
#: pretix/control/views/dashboards.py:136
|
||||
#, python-brace-format
|
||||
|
||||
@@ -8,8 +8,8 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-01-26 09:10+0000\n"
|
||||
"PO-Revision-Date: 2025-11-18 17:00+0000\n"
|
||||
"Last-Translator: Hijiri Umemoto <hijiri@umemoto.org>\n"
|
||||
"PO-Revision-Date: 2026-02-01 21:00+0000\n"
|
||||
"Last-Translator: z3rrry <z3rrry@gmail.com>\n"
|
||||
"Language-Team: Korean <https://translate.pretix.eu/projects/pretix/pretix-js/"
|
||||
"ko/>\n"
|
||||
"Language: ko\n"
|
||||
@@ -17,7 +17,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"X-Generator: Weblate 5.14.3\n"
|
||||
"X-Generator: Weblate 5.15.2\n"
|
||||
|
||||
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:56
|
||||
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:62
|
||||
@@ -175,12 +175,12 @@ msgstr "유료 주문"
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:27
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:39
|
||||
msgid "Attendees (ordered)"
|
||||
msgstr ""
|
||||
msgstr "참가자 (정렬된)"
|
||||
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:27
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:39
|
||||
msgid "Attendees (paid)"
|
||||
msgstr ""
|
||||
msgstr "참가자 (결제된)"
|
||||
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:51
|
||||
msgid "Total revenue"
|
||||
|
||||
+1976
-2001
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ msgstr ""
|
||||
"Project-Id-Version: 1\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-01-26 09:10+0000\n"
|
||||
"PO-Revision-Date: 2026-01-24 01:00+0000\n"
|
||||
"PO-Revision-Date: 2026-02-05 23:00+0000\n"
|
||||
"Last-Translator: Ruud Hendrickx <ruud@leckxicon.eu>\n"
|
||||
"Language-Team: Dutch <https://translate.pretix.eu/projects/pretix/pretix-js/"
|
||||
"nl/>\n"
|
||||
@@ -55,7 +55,7 @@ msgstr "Kredietkaart"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:40
|
||||
msgid "PayPal Pay Later"
|
||||
msgstr "PayPal Pay Later"
|
||||
msgstr "PayPal - Later betalen"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:41
|
||||
msgid "iDEAL"
|
||||
@@ -161,12 +161,12 @@ msgstr "Betaalde bestellingen"
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:27
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:39
|
||||
msgid "Attendees (ordered)"
|
||||
msgstr ""
|
||||
msgstr "Deelnemers (besteld)"
|
||||
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:27
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:39
|
||||
msgid "Attendees (paid)"
|
||||
msgstr ""
|
||||
msgstr "Deelnemers (betaald)"
|
||||
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:51
|
||||
msgid "Total revenue"
|
||||
@@ -186,15 +186,15 @@ msgstr "Verbinding maken met uw bank …"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:30
|
||||
msgid "Select a check-in list"
|
||||
msgstr "Kies een inchecklijst"
|
||||
msgstr "Kies een check-in-lijst"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:31
|
||||
msgid "No active check-in lists found."
|
||||
msgstr "Geen actieve check-inlijsten gevonden."
|
||||
msgstr "Geen actieve check-in-lijsten gevonden."
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:32
|
||||
msgid "Switch check-in list"
|
||||
msgstr "Andere inchecklijst kiezen"
|
||||
msgstr "Andere check-in-lijst kiezen"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:33
|
||||
msgid "Search results"
|
||||
@@ -251,7 +251,7 @@ msgstr "Bevestigd"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:47
|
||||
msgid "Approval pending"
|
||||
msgstr "Goedkeuring in afwachting"
|
||||
msgstr "Goedkeuring in behandeling"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:48
|
||||
msgid "Redeemed"
|
||||
@@ -336,7 +336,7 @@ msgstr "Geldige tickets"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:70
|
||||
msgid "Currently inside"
|
||||
msgstr "Op dit moment binnen"
|
||||
msgstr "Nu binnen"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:71
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:136
|
||||
@@ -406,8 +406,8 @@ msgstr "De aanvraag duurde te lang. Probeer het opnieuw."
|
||||
msgid ""
|
||||
"We currently cannot reach the server. Please try again. Error code: {code}"
|
||||
msgstr ""
|
||||
"De server is op dit moment niet bereikbaar. Probeer het alstublieft opnieuw. "
|
||||
"Foutcode: {code}"
|
||||
"De server is op dit moment niet bereikbaar. Probeer het opnieuw. Foutcode: "
|
||||
"{code}"
|
||||
|
||||
#: pretix/static/pretixbase/js/asynctask.js:216
|
||||
msgid "We are processing your request …"
|
||||
@@ -602,11 +602,11 @@ msgstr "Tekstvak"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:913
|
||||
msgid "Barcode area"
|
||||
msgstr "Barcode gebied"
|
||||
msgstr "Ruimte voor streepjescode"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:915
|
||||
msgid "Image area"
|
||||
msgstr "Afbeeldingsgebied"
|
||||
msgstr "Ruimte voor afbeelding"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:917
|
||||
msgid "Powered by pretix"
|
||||
@@ -664,8 +664,8 @@ msgid ""
|
||||
"Your color has insufficient contrast to white. Accessibility of your site "
|
||||
"will be impacted."
|
||||
msgstr ""
|
||||
"Uw kleur heeft te weinig contrast met wit. De toegankelijkheid van uw site "
|
||||
"wordt negatief beïnvloed."
|
||||
"Uw kleur heeft onvoldoende contrast met wit. Dit heeft invloed op de "
|
||||
"toegankelijkheid van uw website."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:443
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:463
|
||||
@@ -736,7 +736,7 @@ msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/cart.js:49
|
||||
msgid "Cart expired"
|
||||
msgstr "Winkelwagen is verlopen"
|
||||
msgstr "Winkelwagen verlopen"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/cart.js:58
|
||||
#: pretix/static/pretixpresale/js/ui/cart.js:84
|
||||
@@ -936,12 +936,12 @@ msgstr "Momenteel niet beschikbaar"
|
||||
#, javascript-format
|
||||
msgctxt "widget"
|
||||
msgid "minimum amount to order: %s"
|
||||
msgstr "minimale hoeveelheid om te bestellen: %s"
|
||||
msgstr "minimale bestelhoeveelheid: %s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:45
|
||||
msgctxt "widget"
|
||||
msgid "Close ticket shop"
|
||||
msgstr "Sluit ticketverkoop"
|
||||
msgstr "Sluit ticketwinkel"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:46
|
||||
msgctxt "widget"
|
||||
@@ -1004,7 +1004,7 @@ msgstr "Doorgaan met afrekenen"
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:58
|
||||
msgctxt "widget"
|
||||
msgid "Redeem a voucher"
|
||||
msgstr "Voucher inwisselen"
|
||||
msgstr "Een voucher inwisselen"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:59
|
||||
msgctxt "widget"
|
||||
@@ -1160,51 +1160,51 @@ msgstr "zondag"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:94
|
||||
msgid "January"
|
||||
msgstr "Januari"
|
||||
msgstr "januari"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:95
|
||||
msgid "February"
|
||||
msgstr "Februari"
|
||||
msgstr "februari"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:96
|
||||
msgid "March"
|
||||
msgstr "Maart"
|
||||
msgstr "maart"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:97
|
||||
msgid "April"
|
||||
msgstr "April"
|
||||
msgstr "april"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:98
|
||||
msgid "May"
|
||||
msgstr "Mei"
|
||||
msgstr "mei"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:99
|
||||
msgid "June"
|
||||
msgstr "Juni"
|
||||
msgstr "juni"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:100
|
||||
msgid "July"
|
||||
msgstr "Juli"
|
||||
msgstr "juli"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:101
|
||||
msgid "August"
|
||||
msgstr "Augustus"
|
||||
msgstr "augustus"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:102
|
||||
msgid "September"
|
||||
msgstr "September"
|
||||
msgstr "september"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:103
|
||||
msgid "October"
|
||||
msgstr "Oktober"
|
||||
msgstr "oktober"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:104
|
||||
msgid "November"
|
||||
msgstr "November"
|
||||
msgstr "november"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:105
|
||||
msgid "December"
|
||||
msgstr "December"
|
||||
msgstr "december"
|
||||
|
||||
#~ msgid "Time zone:"
|
||||
#~ msgstr "Tijdzone:"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -8,8 +8,8 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-01-26 09:10+0000\n"
|
||||
"PO-Revision-Date: 2021-08-05 04:00+0000\n"
|
||||
"Last-Translator: Maarten van den Berg <maartenberg1@gmail.com>\n"
|
||||
"PO-Revision-Date: 2026-01-29 19:43+0000\n"
|
||||
"Last-Translator: Ruud Hendrickx <ruud@leckxicon.eu>\n"
|
||||
"Language-Team: Dutch (informal) <https://translate.pretix.eu/projects/pretix/"
|
||||
"pretix-js/nl_Informal/>\n"
|
||||
"Language: nl_Informal\n"
|
||||
@@ -17,7 +17,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"X-Generator: Weblate 4.6\n"
|
||||
"X-Generator: Weblate 5.15.2\n"
|
||||
|
||||
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:56
|
||||
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:62
|
||||
@@ -31,106 +31,104 @@ msgstr "Opmerking:"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:34
|
||||
msgid "PayPal"
|
||||
msgstr ""
|
||||
msgstr "PayPal"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:35
|
||||
msgid "Venmo"
|
||||
msgstr ""
|
||||
msgstr "Venmo"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:36
|
||||
#: pretix/static/pretixpresale/js/walletdetection.js:38
|
||||
msgid "Apple Pay"
|
||||
msgstr ""
|
||||
msgstr "Apple Pay"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:37
|
||||
msgid "Itaú"
|
||||
msgstr ""
|
||||
msgstr "Itaú"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:38
|
||||
msgid "PayPal Credit"
|
||||
msgstr ""
|
||||
msgstr "PayPal-krediet"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:39
|
||||
msgid "Credit Card"
|
||||
msgstr ""
|
||||
msgstr "Creditcard"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:40
|
||||
msgid "PayPal Pay Later"
|
||||
msgstr ""
|
||||
msgstr "PayPal Later betalen"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:41
|
||||
msgid "iDEAL"
|
||||
msgstr ""
|
||||
msgstr "iDEAL"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:42
|
||||
msgid "SEPA Direct Debit"
|
||||
msgstr ""
|
||||
msgstr "SEPA-incasso"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:43
|
||||
msgid "Bancontact"
|
||||
msgstr ""
|
||||
msgstr "Bancontact"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:44
|
||||
msgid "giropay"
|
||||
msgstr ""
|
||||
msgstr "giropay"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:45
|
||||
msgid "SOFORT"
|
||||
msgstr ""
|
||||
msgstr "SOFORT"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:46
|
||||
#, fuzzy
|
||||
#| msgid "Yes"
|
||||
msgid "eps"
|
||||
msgstr "Ja"
|
||||
msgstr "eps"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:47
|
||||
msgid "MyBank"
|
||||
msgstr ""
|
||||
msgstr "MyBank"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:48
|
||||
msgid "Przelewy24"
|
||||
msgstr ""
|
||||
msgstr "Przelewy24"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:49
|
||||
msgid "Verkkopankki"
|
||||
msgstr ""
|
||||
msgstr "Verkkopankki"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:50
|
||||
msgid "PayU"
|
||||
msgstr ""
|
||||
msgstr "PayU"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:51
|
||||
msgid "BLIK"
|
||||
msgstr ""
|
||||
msgstr "BLIK"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:52
|
||||
msgid "Trustly"
|
||||
msgstr ""
|
||||
msgstr "Trustly"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:53
|
||||
msgid "Zimpler"
|
||||
msgstr ""
|
||||
msgstr "Zimpler"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:54
|
||||
msgid "Maxima"
|
||||
msgstr ""
|
||||
msgstr "Maxima"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:55
|
||||
msgid "OXXO"
|
||||
msgstr ""
|
||||
msgstr "OXXO"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:56
|
||||
msgid "Boleto"
|
||||
msgstr ""
|
||||
msgstr "Boleto"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:57
|
||||
msgid "WeChat Pay"
|
||||
msgstr ""
|
||||
msgstr "WeChat Pay"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:58
|
||||
msgid "Mercado Pago"
|
||||
msgstr ""
|
||||
msgstr "Mercado Pago"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:167
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:50
|
||||
@@ -149,7 +147,7 @@ msgstr "Betaling bevestigen …"
|
||||
|
||||
#: pretix/plugins/paypal2/static/pretixplugins/paypal2/pretix-paypal.js:254
|
||||
msgid "Payment method unavailable"
|
||||
msgstr ""
|
||||
msgstr "Betaalmethode niet beschikbaar"
|
||||
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:15
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:63
|
||||
@@ -164,12 +162,12 @@ msgstr "Betaalde bestellingen"
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:27
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:39
|
||||
msgid "Attendees (ordered)"
|
||||
msgstr ""
|
||||
msgstr "Deelnemers (geordend)"
|
||||
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:27
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:39
|
||||
msgid "Attendees (paid)"
|
||||
msgstr ""
|
||||
msgstr "Deelnemers (betaald)"
|
||||
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:51
|
||||
msgid "Total revenue"
|
||||
@@ -189,15 +187,15 @@ msgstr "Verbinding maken met je bank …"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:30
|
||||
msgid "Select a check-in list"
|
||||
msgstr "Kies een inchecklijst"
|
||||
msgstr "Kies een check-inlijst"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:31
|
||||
msgid "No active check-in lists found."
|
||||
msgstr "Geen actieve inchecklijsten gevonden."
|
||||
msgstr "Geen actieve check-inlijsten gevonden."
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:32
|
||||
msgid "Switch check-in list"
|
||||
msgstr "Andere inchecklijst kiezen"
|
||||
msgstr "Andere check-inlijst kiezen"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:33
|
||||
msgid "Search results"
|
||||
@@ -205,7 +203,7 @@ msgstr "Zoekresultaten"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:34
|
||||
msgid "No tickets found"
|
||||
msgstr "Geen kaartjes gevonden"
|
||||
msgstr "Geen tickets gevonden"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:35
|
||||
msgid "Result"
|
||||
@@ -213,7 +211,7 @@ msgstr "Resultaat"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:36
|
||||
msgid "This ticket requires special attention"
|
||||
msgstr "Dit kaartje heeft speciale aandacht nodig"
|
||||
msgstr "Dit ticket heeft speciale aandacht nodig"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:37
|
||||
msgid "Switch direction"
|
||||
@@ -229,7 +227,7 @@ msgstr "Vertrek"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:40
|
||||
msgid "Scan a ticket or search and press return…"
|
||||
msgstr "Scan een kaartje of voer een zoekterm in en druk op Enter…"
|
||||
msgstr "Scan een ticket of voer een zoekterm in en druk op Enter…"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:41
|
||||
msgid "Load more"
|
||||
@@ -250,15 +248,15 @@ msgstr "Geannuleerd"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:46
|
||||
msgid "Confirmed"
|
||||
msgstr ""
|
||||
msgstr "Bevestigd"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:47
|
||||
msgid "Approval pending"
|
||||
msgstr ""
|
||||
msgstr "Goedkeuring in behandeling"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:48
|
||||
msgid "Redeemed"
|
||||
msgstr "Gebruikt"
|
||||
msgstr "Ingewisseld"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:49
|
||||
msgid "Cancel"
|
||||
@@ -267,19 +265,19 @@ msgstr "Annuleren"
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:51
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:60
|
||||
msgid "Ticket not paid"
|
||||
msgstr "Kaartje niet betaald"
|
||||
msgstr "Ticket niet betaald"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:52
|
||||
msgid "This ticket is not yet paid. Do you want to continue anyways?"
|
||||
msgstr "Dit kaartje is nog niet betaald. Wil je toch doorgaan?"
|
||||
msgstr "Dit ticket is nog niet betaald. Wil je toch doorgaan?"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:53
|
||||
msgid "Additional information required"
|
||||
msgstr "Extra informatie nodig"
|
||||
msgstr "Aanvullende informatie vereist"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:54
|
||||
msgid "Valid ticket"
|
||||
msgstr "Geldig kaartje"
|
||||
msgstr "Geldig ticket"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:55
|
||||
msgid "Exit recorded"
|
||||
@@ -287,7 +285,7 @@ msgstr "Vertrek opgeslagen"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:56
|
||||
msgid "Ticket already used"
|
||||
msgstr "Kaartje al gebruikt"
|
||||
msgstr "Ticket al gebruikt"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:57
|
||||
msgid "Information required"
|
||||
@@ -295,11 +293,11 @@ msgstr "Informatie nodig"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:58
|
||||
msgid "Unknown ticket"
|
||||
msgstr "Onbekend kaartje"
|
||||
msgstr "Onbekend ticket"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:59
|
||||
msgid "Ticket type not allowed here"
|
||||
msgstr "Kaartjestype hier niet toegestaan"
|
||||
msgstr "Dit type ticket is hier niet toegestaan"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:61
|
||||
msgid "Entry not allowed"
|
||||
@@ -307,19 +305,15 @@ msgstr "Binnenkomst niet toegestaan"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:62
|
||||
msgid "Ticket code revoked/changed"
|
||||
msgstr "Kaartjescode ingetrokken/veranderd"
|
||||
msgstr "Ticketcode ingetrokken/veranderd"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:63
|
||||
#, fuzzy
|
||||
#| msgid "Ticket not paid"
|
||||
msgid "Ticket blocked"
|
||||
msgstr "Kaartje niet betaald"
|
||||
msgstr "Ticket geblokkeerd"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:64
|
||||
#, fuzzy
|
||||
#| msgid "Ticket not paid"
|
||||
msgid "Ticket not valid at this time"
|
||||
msgstr "Kaartje niet betaald"
|
||||
msgstr "Ticket niet geldig op dit tijdstip"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:65
|
||||
msgid "Order canceled"
|
||||
@@ -327,11 +321,11 @@ msgstr "Bestelling geannuleerd"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:66
|
||||
msgid "Ticket code is ambiguous on list"
|
||||
msgstr ""
|
||||
msgstr "Ticketcode is dubbelzinnig op lijst"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:67
|
||||
msgid "Order not approved"
|
||||
msgstr ""
|
||||
msgstr "Bestelling niet goedgekeurd"
|
||||
|
||||
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:68
|
||||
msgid "Checked-in Tickets"
|
||||
@@ -358,11 +352,8 @@ msgid "No"
|
||||
msgstr "Nee"
|
||||
|
||||
#: pretix/static/lightbox/js/lightbox.js:96
|
||||
#, fuzzy
|
||||
#| msgctxt "widget"
|
||||
#| msgid "Close"
|
||||
msgid "close"
|
||||
msgstr "Sluiten"
|
||||
msgstr "sluiten"
|
||||
|
||||
#: pretix/static/pretixbase/js/addressform.js:101
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:529
|
||||
@@ -434,7 +425,7 @@ msgstr ""
|
||||
|
||||
#: pretix/static/pretixbase/js/asynctask.js:276
|
||||
msgid "If this takes longer than a few minutes, please contact us."
|
||||
msgstr ""
|
||||
msgstr "Als dit langer dan een paar minuten duurt, neem dan contact met ons op."
|
||||
|
||||
#: pretix/static/pretixbase/js/asynctask.js:331
|
||||
msgid "Close message"
|
||||
@@ -464,7 +455,7 @@ msgstr "is na"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:40
|
||||
msgid "="
|
||||
msgstr ""
|
||||
msgstr "="
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:99
|
||||
msgid "Product"
|
||||
@@ -476,7 +467,7 @@ msgstr "Productvariant"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:107
|
||||
msgid "Gate"
|
||||
msgstr ""
|
||||
msgstr "Ingang"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:111
|
||||
msgid "Current date and time"
|
||||
@@ -484,11 +475,11 @@ msgstr "Huidige datum en tijd"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:115
|
||||
msgid "Current day of the week (1 = Monday, 7 = Sunday)"
|
||||
msgstr ""
|
||||
msgstr "Huidige dag van de week (1 = maandag, 7 = zondag)"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:119
|
||||
msgid "Current entry status"
|
||||
msgstr ""
|
||||
msgstr "Huidige toegangsstatus"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:123
|
||||
msgid "Number of previous entries"
|
||||
@@ -499,40 +490,32 @@ msgid "Number of previous entries since midnight"
|
||||
msgstr "Aantal eerdere binnenkomsten sinds middernacht"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:131
|
||||
#, fuzzy
|
||||
#| msgid "Number of previous entries"
|
||||
msgid "Number of previous entries since"
|
||||
msgstr "Aantal eerdere binnenkomsten"
|
||||
msgstr "Aantal eerdere binnenkomsten sinds"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:135
|
||||
#, fuzzy
|
||||
#| msgid "Number of previous entries"
|
||||
msgid "Number of previous entries before"
|
||||
msgstr "Aantal eerdere binnenkomsten"
|
||||
msgstr "Aantal eerdere binnenkomsten vóór"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:139
|
||||
msgid "Number of days with a previous entry"
|
||||
msgstr "Aantal dagen met een eerdere binnenkomst"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:143
|
||||
#, fuzzy
|
||||
#| msgid "Number of days with a previous entry"
|
||||
msgid "Number of days with a previous entry since"
|
||||
msgstr "Aantal dagen met een eerdere binnenkomst"
|
||||
msgstr "Aantal dagen met een eerdere binnenkomst sinds"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:147
|
||||
#, fuzzy
|
||||
#| msgid "Number of days with a previous entry"
|
||||
msgid "Number of days with a previous entry before"
|
||||
msgstr "Aantal dagen met een eerdere binnenkomst"
|
||||
msgstr "Aantal dagen met een eerdere binnenkomst voor"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:151
|
||||
msgid "Minutes since last entry (-1 on first entry)"
|
||||
msgstr ""
|
||||
msgstr "Minuten sinds laatste binnenkomst (-1 bij eerste binnenkomst)"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:155
|
||||
msgid "Minutes since first entry (-1 on first entry)"
|
||||
msgstr ""
|
||||
msgstr "Minuten sinds eerste binnenkomst (-1 bij eerste binnenkomst)"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:182
|
||||
msgid "All of the conditions below (AND)"
|
||||
@@ -576,25 +559,25 @@ msgstr "minuten"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:192
|
||||
msgid "Duplicate"
|
||||
msgstr ""
|
||||
msgstr "Duplicaat"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:193
|
||||
msgctxt "entry_status"
|
||||
msgid "present"
|
||||
msgstr ""
|
||||
msgstr "aanwezig"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:194
|
||||
msgctxt "entry_status"
|
||||
msgid "absent"
|
||||
msgstr ""
|
||||
msgstr "afwezig"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:289
|
||||
msgid "Error: Product not found!"
|
||||
msgstr ""
|
||||
msgstr "Fout: Product niet gevonden!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:296
|
||||
msgid "Error: Variation not found!"
|
||||
msgstr ""
|
||||
msgstr "Fout: Variant niet gevonden!"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:171
|
||||
msgid "Check-in QR"
|
||||
@@ -610,16 +593,12 @@ msgid "Group of objects"
|
||||
msgstr "Groep van objecten"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:909
|
||||
#, fuzzy
|
||||
#| msgid "Text object"
|
||||
msgid "Text object (deprecated)"
|
||||
msgstr "Tekstobject"
|
||||
msgstr "Tekstobject (verouderd)"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:911
|
||||
#, fuzzy
|
||||
#| msgid "Text object"
|
||||
msgid "Text box"
|
||||
msgstr "Tekstobject"
|
||||
msgstr "Tekstveld"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/editor.js:913
|
||||
msgid "Barcode area"
|
||||
@@ -667,25 +646,26 @@ msgid "Unknown error."
|
||||
msgstr "Onbekende fout."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:309
|
||||
#, fuzzy
|
||||
#| msgid "Your color has great contrast and is very easy to read!"
|
||||
msgid "Your color has great contrast and will provide excellent accessibility."
|
||||
msgstr "Je kleur heeft een goed contrast, en is gemakkelijk te lezen!"
|
||||
msgstr ""
|
||||
"Je kleur heeft een groot contrast en zorgt voor een uitstekende "
|
||||
"toegankelijkheid."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:313
|
||||
#, fuzzy
|
||||
#| msgid "Your color has decent contrast and is probably good-enough to read!"
|
||||
msgid ""
|
||||
"Your color has decent contrast and is sufficient for minimum accessibility "
|
||||
"requirements."
|
||||
msgstr ""
|
||||
"Je kleur heeft een redelijk contrast, en is waarschijnlijk goed te lezen!"
|
||||
"Je kleur heeft een behoorlijk contrast en voldoet aan de minimale "
|
||||
"toegankelijkheidseisen."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:317
|
||||
msgid ""
|
||||
"Your color has insufficient contrast to white. Accessibility of your site "
|
||||
"will be impacted."
|
||||
msgstr ""
|
||||
"Je kleur heeft onvoldoende contrast met wit. Dit heeft invloed op de "
|
||||
"toegankelijkheid van je website."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:443
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:463
|
||||
@@ -706,11 +686,11 @@ msgstr "Alleen geselecteerde"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:839
|
||||
msgid "Enter page number between 1 and %(max)s."
|
||||
msgstr ""
|
||||
msgstr "Voer een paginanummer in tussen 1 en %(max)s."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:842
|
||||
msgid "Invalid page number."
|
||||
msgstr ""
|
||||
msgstr "Ongeldig paginanummer."
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/main.js:1000
|
||||
msgid "Use a different name internally"
|
||||
@@ -729,10 +709,8 @@ msgid "Calculating default price…"
|
||||
msgstr "Standaardprijs berekenen…"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/plugins.js:69
|
||||
#, fuzzy
|
||||
#| msgid "Search results"
|
||||
msgid "No results"
|
||||
msgstr "Zoekresultaten"
|
||||
msgstr "Geen resultaten"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:41
|
||||
msgid "Others"
|
||||
@@ -740,7 +718,7 @@ msgstr "Andere"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/question.js:81
|
||||
msgid "Count"
|
||||
msgstr "Aantal"
|
||||
msgstr "Tellen"
|
||||
|
||||
#: pretix/static/pretixcontrol/js/ui/subevent.js:112
|
||||
msgid "(one more date)"
|
||||
@@ -749,12 +727,12 @@ msgstr[0] "(één andere datum)"
|
||||
msgstr[1] "({num} andere datums)"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/cart.js:47
|
||||
#, fuzzy
|
||||
#| msgid "The items in your cart are no longer reserved for you."
|
||||
msgid ""
|
||||
"The items in your cart are no longer reserved for you. You can still "
|
||||
"complete your order as long as they’re available."
|
||||
msgstr "De items in je winkelwagen zijn niet meer voor je gereserveerd."
|
||||
msgstr ""
|
||||
"De artikelen in je winkelwagen zijn niet langer voor je gereserveerd. Je "
|
||||
"kunt je bestelling nog steeds voltooien zolang ze beschikbaar zijn."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/cart.js:49
|
||||
msgid "Cart expired"
|
||||
@@ -763,41 +741,34 @@ msgstr "Winkelwagen is verlopen"
|
||||
#: pretix/static/pretixpresale/js/ui/cart.js:58
|
||||
#: pretix/static/pretixpresale/js/ui/cart.js:84
|
||||
msgid "Your cart is about to expire."
|
||||
msgstr ""
|
||||
msgstr "Je winkelwagen verloopt bijna."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/cart.js:62
|
||||
#, fuzzy
|
||||
#| msgid "The items in your cart are reserved for you for one minute."
|
||||
#| msgid_plural ""
|
||||
#| "The items in your cart are reserved for you for {num} minutes."
|
||||
msgid "The items in your cart are reserved for you for one minute."
|
||||
msgid_plural "The items in your cart are reserved for you for {num} minutes."
|
||||
msgstr[0] ""
|
||||
"De items in je winkelwagen zijn nog één minuut voor je gereserveerd."
|
||||
msgstr[0] "De artikelen in je winkelwagen worden één minuut voor je gereserveerd."
|
||||
msgstr[1] ""
|
||||
"De items in je winkelwagen zijn nog {num} minuten voor je gereserveerd."
|
||||
"De artikelen in je winkelwagen worden {num} minuten voor je gereserveerd."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/cart.js:83
|
||||
#, fuzzy
|
||||
#| msgid "Cart expired"
|
||||
msgid "Your cart has expired."
|
||||
msgstr "Winkelwagen is verlopen"
|
||||
msgstr "Je winkelwagen is verlopen."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/cart.js:86
|
||||
#, fuzzy
|
||||
#| msgid "The items in your cart are no longer reserved for you."
|
||||
msgid ""
|
||||
"The items in your cart are no longer reserved for you. You can still "
|
||||
"complete your order as long as they're available."
|
||||
msgstr "De items in je winkelwagen zijn niet meer voor je gereserveerd."
|
||||
msgstr ""
|
||||
"De artikelen in je winkelwagen zijn niet langer voor je gereserveerd. Je "
|
||||
"kunt je bestelling nog steeds voltooien zolang ze beschikbaar zijn."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/cart.js:87
|
||||
msgid "Do you want to renew the reservation period?"
|
||||
msgstr ""
|
||||
msgstr "Wil je de reserveringsperiode verlengen?"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/cart.js:90
|
||||
msgid "Renew reservation"
|
||||
msgstr ""
|
||||
msgstr "Reservering verlengen"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:194
|
||||
msgid "The organizer keeps %(currency)s %(amount)s"
|
||||
@@ -817,71 +788,66 @@ msgstr "Je lokale tijd:"
|
||||
|
||||
#: pretix/static/pretixpresale/js/walletdetection.js:39
|
||||
msgid "Google Pay"
|
||||
msgstr ""
|
||||
msgstr "Google Pay"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:16
|
||||
msgctxt "widget"
|
||||
msgid "Quantity"
|
||||
msgstr ""
|
||||
msgstr "Hoeveelheid"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:17
|
||||
msgctxt "widget"
|
||||
msgid "Decrease quantity"
|
||||
msgstr ""
|
||||
msgstr "Hoeveelheid verminderen"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:18
|
||||
msgctxt "widget"
|
||||
msgid "Increase quantity"
|
||||
msgstr ""
|
||||
msgstr "Hoeveelheid verhogen"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:19
|
||||
msgctxt "widget"
|
||||
msgid "Filter events by"
|
||||
msgstr ""
|
||||
msgstr "Filter evenementen op"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:20
|
||||
msgctxt "widget"
|
||||
msgid "Filter"
|
||||
msgstr ""
|
||||
msgstr "Filteren"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:21
|
||||
msgctxt "widget"
|
||||
msgid "Price"
|
||||
msgstr ""
|
||||
msgstr "Prijs"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:22
|
||||
#, javascript-format
|
||||
msgctxt "widget"
|
||||
msgid "Original price: %s"
|
||||
msgstr ""
|
||||
msgstr "Oorspronkelijke prijs: %s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:23
|
||||
#, javascript-format
|
||||
msgctxt "widget"
|
||||
msgid "New price: %s"
|
||||
msgstr ""
|
||||
msgstr "Nieuwe prijs: %s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:24
|
||||
#, fuzzy
|
||||
#| msgid "Selected only"
|
||||
msgctxt "widget"
|
||||
msgid "Select"
|
||||
msgstr "Alleen geselecteerde"
|
||||
msgstr "Selecteren"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:25
|
||||
#, fuzzy, javascript-format
|
||||
#| msgid "Selected only"
|
||||
#, javascript-format
|
||||
msgctxt "widget"
|
||||
msgid "Select %s"
|
||||
msgstr "Alleen geselecteerde"
|
||||
msgstr "Selecteer %s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:26
|
||||
#, fuzzy, javascript-format
|
||||
#| msgctxt "widget"
|
||||
#| msgid "See variations"
|
||||
#, javascript-format
|
||||
msgctxt "widget"
|
||||
msgid "Select variant %s"
|
||||
msgstr "Zie variaties"
|
||||
msgstr "Selecteer variant %s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:27
|
||||
msgctxt "widget"
|
||||
@@ -917,7 +883,7 @@ msgstr "vanaf %(currency)s %(price)s"
|
||||
#, javascript-format
|
||||
msgctxt "widget"
|
||||
msgid "Image of %s"
|
||||
msgstr ""
|
||||
msgstr "Afbeelding van %s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:34
|
||||
msgctxt "widget"
|
||||
@@ -952,25 +918,19 @@ msgstr "Alleen beschikbaar met een voucher"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:40
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:43
|
||||
#, fuzzy
|
||||
#| msgctxt "widget"
|
||||
#| msgid "currently available: %s"
|
||||
msgctxt "widget"
|
||||
msgid "Not yet available"
|
||||
msgstr "nu beschikbaar: %s"
|
||||
msgstr "Nog niet beschikbaar"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:41
|
||||
msgctxt "widget"
|
||||
msgid "Not available anymore"
|
||||
msgstr ""
|
||||
msgstr "Niet meer beschikbaar"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:42
|
||||
#, fuzzy
|
||||
#| msgctxt "widget"
|
||||
#| msgid "currently available: %s"
|
||||
msgctxt "widget"
|
||||
msgid "Currently not available"
|
||||
msgstr "nu beschikbaar: %s"
|
||||
msgstr "Momenteel niet beschikbaar"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:44
|
||||
#, javascript-format
|
||||
@@ -1003,12 +963,9 @@ msgid "Open ticket shop"
|
||||
msgstr "Open de kaartjeswinkel"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:50
|
||||
#, fuzzy
|
||||
#| msgctxt "widget"
|
||||
#| msgid "Resume checkout"
|
||||
msgctxt "widget"
|
||||
msgid "Checkout"
|
||||
msgstr "Doorgaan met afrekenen"
|
||||
msgstr "Afrekenen"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:51
|
||||
msgctxt "widget"
|
||||
@@ -1067,17 +1024,14 @@ msgid "Close"
|
||||
msgstr "Sluiten"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:62
|
||||
#, fuzzy
|
||||
#| msgctxt "widget"
|
||||
#| msgid "Resume checkout"
|
||||
msgctxt "widget"
|
||||
msgid "Close checkout"
|
||||
msgstr "Doorgaan met afrekenen"
|
||||
msgstr "Afrekening afsluiten"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:63
|
||||
msgctxt "widget"
|
||||
msgid "You cannot cancel this operation. Please wait for loading to finish."
|
||||
msgstr ""
|
||||
msgstr "Je kunt deze bewerking niet annuleren. Wacht tot het laden voltooid is."
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:64
|
||||
msgctxt "widget"
|
||||
@@ -1085,20 +1039,14 @@ msgid "Continue"
|
||||
msgstr "Ga verder"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:65
|
||||
#, fuzzy
|
||||
#| msgctxt "widget"
|
||||
#| msgid "See variations"
|
||||
msgctxt "widget"
|
||||
msgid "Show variants"
|
||||
msgstr "Zie variaties"
|
||||
msgstr "Varianten weergeven"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:66
|
||||
#, fuzzy
|
||||
#| msgctxt "widget"
|
||||
#| msgid "See variations"
|
||||
msgctxt "widget"
|
||||
msgid "Hide variants"
|
||||
msgstr "Zie variaties"
|
||||
msgstr "Varianten verbergen"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:67
|
||||
msgctxt "widget"
|
||||
@@ -1147,6 +1095,9 @@ msgid ""
|
||||
"add yourself to the waiting list. We will then notify if seats are available "
|
||||
"again."
|
||||
msgstr ""
|
||||
"Sommige of alle ticketcategorieën zijn momenteel uitverkocht. Als je dat "
|
||||
"wilt, kun je je op de wachtlijst laten plaatsen. Wij zullen je dan op de "
|
||||
"hoogte brengen als er weer plaatsen beschikbaar zijn."
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:76
|
||||
msgctxt "widget"
|
||||
@@ -1183,79 +1134,79 @@ msgstr "Zo"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:85
|
||||
msgid "Monday"
|
||||
msgstr ""
|
||||
msgstr "maandag"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:86
|
||||
msgid "Tuesday"
|
||||
msgstr ""
|
||||
msgstr "dinsdag"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:87
|
||||
msgid "Wednesday"
|
||||
msgstr ""
|
||||
msgstr "woensdag"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:88
|
||||
msgid "Thursday"
|
||||
msgstr ""
|
||||
msgstr "donderdag"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:89
|
||||
msgid "Friday"
|
||||
msgstr ""
|
||||
msgstr "vrijdag"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:90
|
||||
msgid "Saturday"
|
||||
msgstr ""
|
||||
msgstr "zaterdag"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:91
|
||||
msgid "Sunday"
|
||||
msgstr ""
|
||||
msgstr "zondag"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:94
|
||||
msgid "January"
|
||||
msgstr "Januari"
|
||||
msgstr "januari"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:95
|
||||
msgid "February"
|
||||
msgstr "Februari"
|
||||
msgstr "februari"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:96
|
||||
msgid "March"
|
||||
msgstr "Maart"
|
||||
msgstr "maart"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:97
|
||||
msgid "April"
|
||||
msgstr "April"
|
||||
msgstr "april"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:98
|
||||
msgid "May"
|
||||
msgstr "Mei"
|
||||
msgstr "mei"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:99
|
||||
msgid "June"
|
||||
msgstr "Juni"
|
||||
msgstr "juni"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:100
|
||||
msgid "July"
|
||||
msgstr "Juli"
|
||||
msgstr "juli"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:101
|
||||
msgid "August"
|
||||
msgstr "Augustus"
|
||||
msgstr "augustus"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:102
|
||||
msgid "September"
|
||||
msgstr "September"
|
||||
msgstr "september"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:103
|
||||
msgid "October"
|
||||
msgstr "Oktober"
|
||||
msgstr "oktober"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:104
|
||||
msgid "November"
|
||||
msgstr "November"
|
||||
msgstr "november"
|
||||
|
||||
#: pretix/static/pretixpresale/js/widget/widget.js:105
|
||||
msgid "December"
|
||||
msgstr "December"
|
||||
msgstr "december"
|
||||
|
||||
#~ msgid "Time zone:"
|
||||
#~ msgstr "Tijdzone:"
|
||||
|
||||
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-01-26 13:19+0000\n"
|
||||
"PO-Revision-Date: 2025-12-18 01:00+0000\n"
|
||||
"PO-Revision-Date: 2026-01-26 22:00+0000\n"
|
||||
"Last-Translator: Renne Rocha <renne@rocha.dev.br>\n"
|
||||
"Language-Team: Portuguese (Brazil) <https://translate.pretix.eu/projects/"
|
||||
"pretix/pretix/pt_BR/>\n"
|
||||
@@ -17,7 +17,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n > 1;\n"
|
||||
"X-Generator: Weblate 5.15\n"
|
||||
"X-Generator: Weblate 5.15.2\n"
|
||||
|
||||
#: pretix/_base_settings.py:87
|
||||
msgid "English"
|
||||
@@ -4366,6 +4366,8 @@ msgid ""
|
||||
"to confirm changing your email address from {old_email}\n"
|
||||
"to {new_email}, use the following code:"
|
||||
msgstr ""
|
||||
"para confirmar a alteração do seu endereço de email de {old_email}\n"
|
||||
"para {new_email}, use o código a seguir:"
|
||||
|
||||
#: pretix/base/models/auth.py:377
|
||||
#, python-brace-format
|
||||
@@ -4373,6 +4375,8 @@ msgid ""
|
||||
"to confirm that your email address {email} belongs to your pretix account, "
|
||||
"use the following code:"
|
||||
msgstr ""
|
||||
"para confirmar que o seu endereço de email {email} pertence a sua conta do "
|
||||
"pretix, use o código a seguir:"
|
||||
|
||||
#: pretix/base/models/auth.py:391
|
||||
msgid "pretix confirmation code"
|
||||
@@ -8185,6 +8189,9 @@ msgid ""
|
||||
"2017-05-31 14:00 – 16:00\n"
|
||||
"2017-05-31 14:00 – 2017-06-01 14:00"
|
||||
msgstr ""
|
||||
"2017-05-31 10:00 – 12:00\n"
|
||||
"2017-05-31 14:00 – 16:00\n"
|
||||
"2017-05-31 14:00 – 2017-06-01 14:00"
|
||||
|
||||
#: pretix/base/pdf.py:500
|
||||
msgid "Reusable Medium ID"
|
||||
@@ -16267,7 +16274,7 @@ msgstr ""
|
||||
|
||||
#: pretix/control/forms/orders.py:1037
|
||||
msgid "I understand that this is not reversible and want to continue"
|
||||
msgstr ""
|
||||
msgstr "Eu entendo que esta ação não é reversível e eu quero continuar"
|
||||
|
||||
#: pretix/control/forms/orders.py:1042
|
||||
msgid ""
|
||||
@@ -27627,7 +27634,7 @@ msgstr "A lista selecionada foi apagada."
|
||||
|
||||
#: pretix/control/views/dashboards.py:114
|
||||
msgid "Attendees (ordered)"
|
||||
msgstr "Participantes (com pedidos)"
|
||||
msgstr "Participantes (com pedido)"
|
||||
|
||||
#: pretix/control/views/dashboards.py:124
|
||||
msgid "Attendees (paid)"
|
||||
|
||||
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-01-26 09:10+0000\n"
|
||||
"PO-Revision-Date: 2025-12-09 00:47+0000\n"
|
||||
"PO-Revision-Date: 2026-01-26 22:00+0000\n"
|
||||
"Last-Translator: Renne Rocha <renne@rocha.dev.br>\n"
|
||||
"Language-Team: Portuguese (Brazil) <https://translate.pretix.eu/projects/"
|
||||
"pretix/pretix-js/pt_BR/>\n"
|
||||
@@ -17,7 +17,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=n > 1;\n"
|
||||
"X-Generator: Weblate 5.14.3\n"
|
||||
"X-Generator: Weblate 5.15.2\n"
|
||||
|
||||
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:56
|
||||
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:62
|
||||
@@ -162,12 +162,12 @@ msgstr "Pedidos pagos"
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:27
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:39
|
||||
msgid "Attendees (ordered)"
|
||||
msgstr ""
|
||||
msgstr "Participantes (com pedido)"
|
||||
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:27
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:39
|
||||
msgid "Attendees (paid)"
|
||||
msgstr ""
|
||||
msgstr "Participantes (pago)"
|
||||
|
||||
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:51
|
||||
msgid "Total revenue"
|
||||
|
||||
+2630
-1845
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-01-26 13:19+0000\n"
|
||||
"PO-Revision-Date: 2026-01-12 17:00+0000\n"
|
||||
"PO-Revision-Date: 2026-01-26 22:00+0000\n"
|
||||
"Last-Translator: Hijiri Umemoto <hijiri@umemoto.org>\n"
|
||||
"Language-Team: Chinese (Traditional Han script) <https://translate.pretix.eu/"
|
||||
"projects/pretix/pretix/zh_Hant/>\n"
|
||||
@@ -17,7 +17,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
"X-Generator: Weblate 5.15.1\n"
|
||||
"X-Generator: Weblate 5.15.2\n"
|
||||
|
||||
#: pretix/_base_settings.py:87
|
||||
msgid "English"
|
||||
@@ -9583,17 +9583,13 @@ msgid "Ask for VAT ID"
|
||||
msgstr "詢問增值稅號"
|
||||
|
||||
#: pretix/base/settings.py:645
|
||||
#, fuzzy, python-brace-format
|
||||
#| msgid ""
|
||||
#| "Only works if an invoice address is asked for. VAT ID is never required "
|
||||
#| "and only requested from business customers in the following countries: "
|
||||
#| "{countries}"
|
||||
#, python-brace-format
|
||||
msgid ""
|
||||
"Only works if an invoice address is asked for. VAT ID is only requested from "
|
||||
"business customers in the following countries: {countries}."
|
||||
msgstr ""
|
||||
"僅當要求提供發票位址時才有效。增值稅號從來都不是必需的,並且僅向以下國家/地區"
|
||||
"的企業客戶請求:{countries}"
|
||||
"僅當要求提供發票地址時才有效。 僅以下國家的企業客戶要求提供增值稅 ID:"
|
||||
"{countries}。"
|
||||
|
||||
#: pretix/base/settings.py:664
|
||||
#, fuzzy
|
||||
@@ -26554,10 +26550,8 @@ msgid "Please try again."
|
||||
msgstr "請重試。"
|
||||
|
||||
#: pretix/control/views/auth.py:544
|
||||
#, fuzzy
|
||||
#| msgid "Two-factor authentication is required to log in"
|
||||
msgid "A recovery code for two-factor authentification was used to log in."
|
||||
msgstr "登入需要兩步驟驗證"
|
||||
msgstr "用於雙因素身份驗證的恢復程式用於登入。"
|
||||
|
||||
#: pretix/control/views/auth.py:560
|
||||
msgid "Invalid code, please try again."
|
||||
|
||||
@@ -56,7 +56,6 @@ from pretix.base.models import (
|
||||
)
|
||||
from pretix.base.payment import PaymentException
|
||||
from pretix.base.services.locking import LockTimeoutException
|
||||
from pretix.base.services.mail import SendMailException
|
||||
from pretix.base.services.orders import change_payment_provider
|
||||
from pretix.base.services.tasks import TransactionAwareTask
|
||||
from pretix.celery_app import app
|
||||
@@ -72,13 +71,10 @@ def notify_incomplete_payment(o: Order):
|
||||
email_context = get_email_context(event=o.event, order=o, pending_sum=o.pending_sum)
|
||||
email_subject = o.event.settings.mail_subject_order_incomplete_payment
|
||||
|
||||
try:
|
||||
o.send_mail(
|
||||
email_subject, email_template, email_context,
|
||||
'pretix.event.order.email.expire_warning_sent'
|
||||
)
|
||||
except SendMailException:
|
||||
logger.exception('Reminder email could not be sent')
|
||||
o.send_mail(
|
||||
email_subject, email_template, email_context,
|
||||
'pretix.event.order.email.expire_warning_sent'
|
||||
)
|
||||
|
||||
|
||||
def cancel_old_payments(order):
|
||||
@@ -288,9 +284,6 @@ def _handle_transaction(trans: BankTransaction, matches: tuple, regex_match_to_s
|
||||
except Quota.QuotaExceededException:
|
||||
# payment confirmed but order status could not be set, no longer problem of this plugin
|
||||
cancel_old_payments(order)
|
||||
except SendMailException:
|
||||
# payment confirmed but order status could not be set, no longer problem of this plugin
|
||||
cancel_old_payments(order)
|
||||
else:
|
||||
cancel_old_payments(order)
|
||||
|
||||
|
||||
@@ -58,7 +58,6 @@ from localflavor.generic.forms import BICFormField, IBANFormField
|
||||
|
||||
from pretix.base.forms.widgets import DatePickerWidget
|
||||
from pretix.base.models import Event, Order, OrderPayment, OrderRefund, Quota
|
||||
from pretix.base.services.mail import SendMailException
|
||||
from pretix.base.settings import SettingsSandbox
|
||||
from pretix.base.templatetags.money import money_filter
|
||||
from pretix.control.permissions import (
|
||||
@@ -160,11 +159,6 @@ class ActionView(View):
|
||||
p.confirm(user=self.request.user)
|
||||
except Quota.QuotaExceededException:
|
||||
pass
|
||||
except SendMailException:
|
||||
return JsonResponse({
|
||||
'status': 'error',
|
||||
'message': _('Problem sending email.')
|
||||
})
|
||||
trans.state = BankTransaction.STATE_VALID
|
||||
trans.save()
|
||||
trans.order.payments.filter(
|
||||
|
||||
@@ -57,7 +57,6 @@ from pretix.base.decimal import round_decimal
|
||||
from pretix.base.forms import SecretKeySettingsField
|
||||
from pretix.base.models import Event, Order, OrderPayment, OrderRefund, Quota
|
||||
from pretix.base.payment import BasePaymentProvider, PaymentException
|
||||
from pretix.base.services.mail import SendMailException
|
||||
from pretix.base.settings import SettingsSandbox
|
||||
from pretix.multidomain.urlreverse import build_absolute_uri
|
||||
from pretix.plugins.paypal.api import Api
|
||||
@@ -468,9 +467,6 @@ class Paypal(BasePaymentProvider):
|
||||
payment_obj.confirm()
|
||||
except Quota.QuotaExceededException as e:
|
||||
raise PaymentException(str(e))
|
||||
|
||||
except SendMailException:
|
||||
messages.warning(request, _('There was an error sending the confirmation mail.'))
|
||||
return None
|
||||
|
||||
def payment_pending_render(self, request, payment) -> str:
|
||||
|
||||
@@ -54,7 +54,6 @@ from pretix.base.forms import SecretKeySettingsField
|
||||
from pretix.base.forms.questions import guess_country
|
||||
from pretix.base.models import Event, Order, OrderPayment, OrderRefund, Quota
|
||||
from pretix.base.payment import BasePaymentProvider, PaymentException
|
||||
from pretix.base.services.mail import SendMailException
|
||||
from pretix.base.settings import SettingsSandbox
|
||||
from pretix.helpers import OF_SELF
|
||||
from pretix.helpers.urls import build_absolute_uri as build_global_uri
|
||||
@@ -821,9 +820,6 @@ class PaypalMethod(BasePaymentProvider):
|
||||
payment.confirm()
|
||||
except Quota.QuotaExceededException as e:
|
||||
raise PaymentException(str(e))
|
||||
|
||||
except SendMailException:
|
||||
messages.warning(request, _('There was an error sending the confirmation mail.'))
|
||||
finally:
|
||||
if 'payment_paypal_oid' in request.session:
|
||||
del request.session['payment_paypal_oid']
|
||||
|
||||
@@ -38,7 +38,6 @@ from pretix.base.models import (
|
||||
fields,
|
||||
)
|
||||
from pretix.base.models.base import LoggingMixin
|
||||
from pretix.base.services.mail import SendMailException
|
||||
|
||||
|
||||
class ScheduledMail(models.Model):
|
||||
@@ -180,13 +179,10 @@ class ScheduledMail(models.Model):
|
||||
invoice_address=ia,
|
||||
event_or_subevent=self.subevent or e,
|
||||
)
|
||||
try:
|
||||
o.send_mail(self.rule.subject, self.rule.template, email_ctx,
|
||||
attach_ical=self.rule.attach_ical,
|
||||
log_entry_type='pretix.plugins.sendmail.rule.order.email.sent')
|
||||
o_sent = True
|
||||
except SendMailException:
|
||||
... # ¯\_(ツ)_/¯
|
||||
o.send_mail(self.rule.subject, self.rule.template, email_ctx,
|
||||
attach_ical=self.rule.attach_ical,
|
||||
log_entry_type='pretix.plugins.sendmail.rule.order.email.sent')
|
||||
o_sent = True
|
||||
|
||||
if send_to_attendees:
|
||||
if not self.rule.all_products:
|
||||
@@ -195,31 +191,28 @@ class ScheduledMail(models.Model):
|
||||
positions = [p for p in positions if p.subevent_id == self.subevent_id]
|
||||
|
||||
for p in positions:
|
||||
try:
|
||||
if p.attendee_email and (p.attendee_email != o.email or not o_sent):
|
||||
email_ctx = get_email_context(
|
||||
event=e,
|
||||
order=o,
|
||||
invoice_address=ia,
|
||||
position=p,
|
||||
event_or_subevent=self.subevent or e,
|
||||
)
|
||||
p.send_mail(self.rule.subject, self.rule.template, email_ctx,
|
||||
attach_ical=self.rule.attach_ical,
|
||||
log_entry_type='pretix.plugins.sendmail.rule.order.position.email.sent')
|
||||
elif not o_sent and o.email:
|
||||
email_ctx = get_email_context(
|
||||
event=e,
|
||||
order=o,
|
||||
invoice_address=ia,
|
||||
event_or_subevent=self.subevent or e,
|
||||
)
|
||||
o.send_mail(self.rule.subject, self.rule.template, email_ctx,
|
||||
attach_ical=self.rule.attach_ical,
|
||||
log_entry_type='pretix.plugins.sendmail.rule.order.email.sent')
|
||||
o_sent = True
|
||||
except SendMailException:
|
||||
... # ¯\_(ツ)_/¯
|
||||
if p.attendee_email and (p.attendee_email != o.email or not o_sent):
|
||||
email_ctx = get_email_context(
|
||||
event=e,
|
||||
order=o,
|
||||
invoice_address=ia,
|
||||
position=p,
|
||||
event_or_subevent=self.subevent or e,
|
||||
)
|
||||
p.send_mail(self.rule.subject, self.rule.template, email_ctx,
|
||||
attach_ical=self.rule.attach_ical,
|
||||
log_entry_type='pretix.plugins.sendmail.rule.order.position.email.sent')
|
||||
elif not o_sent and o.email:
|
||||
email_ctx = get_email_context(
|
||||
event=e,
|
||||
order=o,
|
||||
invoice_address=ia,
|
||||
event_or_subevent=self.subevent or e,
|
||||
)
|
||||
o.send_mail(self.rule.subject, self.rule.template, email_ctx,
|
||||
attach_ical=self.rule.attach_ical,
|
||||
log_entry_type='pretix.plugins.sendmail.rule.order.email.sent')
|
||||
o_sent = True
|
||||
|
||||
self.last_successful_order_id = o.pk
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ from pretix.base.i18n import language
|
||||
from pretix.base.models import (
|
||||
CachedFile, Checkin, Event, InvoiceAddress, Order, User,
|
||||
)
|
||||
from pretix.base.services.mail import SendMailException, mail
|
||||
from pretix.base.services.mail import mail
|
||||
from pretix.base.services.tasks import ProfiledEventTask
|
||||
from pretix.celery_app import app
|
||||
from pretix.helpers.format import format_map
|
||||
@@ -61,7 +61,6 @@ def send_mails_to_orders(event: Event, user: int, subject: dict, message: dict,
|
||||
recipients: str, filter_checkins: bool, not_checked_in: bool, checkin_lists: list,
|
||||
attachments: list = None, attach_tickets: bool = False,
|
||||
attach_ical: bool = False) -> None:
|
||||
failures = []
|
||||
user = User.objects.get(pk=user) if user else None
|
||||
subject = LazyI18nString(subject)
|
||||
message = LazyI18nString(message)
|
||||
@@ -121,70 +120,64 @@ def send_mails_to_orders(event: Event, user: int, subject: dict, message: dict,
|
||||
if subevents_to and p.subevent.date_from >= subevents_to:
|
||||
continue
|
||||
|
||||
try:
|
||||
with language(o.locale, event.settings.region):
|
||||
email_context = get_email_context(event=event, order=o, invoice_address=ia, position=p)
|
||||
mail(
|
||||
p.attendee_email,
|
||||
subject,
|
||||
message,
|
||||
email_context,
|
||||
event,
|
||||
locale=o.locale,
|
||||
order=o,
|
||||
position=p,
|
||||
attach_tickets=attach_tickets,
|
||||
attach_ical=attach_ical,
|
||||
attach_cached_files=attachments
|
||||
)
|
||||
o.log_action(
|
||||
'pretix.plugins.sendmail.order.email.sent.attendee',
|
||||
user=user,
|
||||
data={
|
||||
'position': p.positionid,
|
||||
'subject': format_map(subject.localize(o.locale), email_context),
|
||||
'message': format_map(message.localize(o.locale), email_context),
|
||||
'recipient': p.attendee_email,
|
||||
'attach_tickets': attach_tickets,
|
||||
'attach_ical': attach_ical,
|
||||
'attach_other_files': [],
|
||||
'attach_cached_files': attachments_for_log,
|
||||
}
|
||||
)
|
||||
except SendMailException:
|
||||
failures.append(p.attendee_email)
|
||||
|
||||
if send_to_order and o.email:
|
||||
try:
|
||||
with language(o.locale, event.settings.region):
|
||||
email_context = get_email_context(event=event, order=o, invoice_address=ia)
|
||||
email_context = get_email_context(event=event, order=o, invoice_address=ia, position=p)
|
||||
mail(
|
||||
o.email,
|
||||
p.attendee_email,
|
||||
subject,
|
||||
message,
|
||||
email_context,
|
||||
event,
|
||||
locale=o.locale,
|
||||
order=o,
|
||||
position=p,
|
||||
attach_tickets=attach_tickets,
|
||||
attach_ical=attach_ical,
|
||||
attach_cached_files=attachments,
|
||||
attach_cached_files=attachments
|
||||
)
|
||||
o.log_action(
|
||||
'pretix.plugins.sendmail.order.email.sent',
|
||||
'pretix.plugins.sendmail.order.email.sent.attendee',
|
||||
user=user,
|
||||
data={
|
||||
'position': p.positionid,
|
||||
'subject': format_map(subject.localize(o.locale), email_context),
|
||||
'message': format_map(message.localize(o.locale), email_context),
|
||||
'recipient': o.email,
|
||||
'recipient': p.attendee_email,
|
||||
'attach_tickets': attach_tickets,
|
||||
'attach_ical': attach_ical,
|
||||
'attach_other_files': [],
|
||||
'attach_cached_files': attachments_for_log,
|
||||
}
|
||||
)
|
||||
except SendMailException:
|
||||
failures.append(o.email)
|
||||
|
||||
if send_to_order and o.email:
|
||||
with language(o.locale, event.settings.region):
|
||||
email_context = get_email_context(event=event, order=o, invoice_address=ia)
|
||||
mail(
|
||||
o.email,
|
||||
subject,
|
||||
message,
|
||||
email_context,
|
||||
event,
|
||||
locale=o.locale,
|
||||
order=o,
|
||||
attach_tickets=attach_tickets,
|
||||
attach_ical=attach_ical,
|
||||
attach_cached_files=attachments,
|
||||
)
|
||||
o.log_action(
|
||||
'pretix.plugins.sendmail.order.email.sent',
|
||||
user=user,
|
||||
data={
|
||||
'subject': format_map(subject.localize(o.locale), email_context),
|
||||
'message': format_map(message.localize(o.locale), email_context),
|
||||
'recipient': o.email,
|
||||
'attach_tickets': attach_tickets,
|
||||
'attach_ical': attach_ical,
|
||||
'attach_other_files': [],
|
||||
'attach_cached_files': attachments_for_log,
|
||||
}
|
||||
)
|
||||
|
||||
for chunk in _chunks(objects, 1000):
|
||||
orders = Order.objects.filter(pk__in=chunk, event=event)
|
||||
|
||||
@@ -71,7 +71,6 @@ from pretix.base.payment import (
|
||||
BasePaymentProvider, PaymentException, WalletQueries,
|
||||
)
|
||||
from pretix.base.plugins import get_all_plugins
|
||||
from pretix.base.services.mail import SendMailException
|
||||
from pretix.base.settings import SettingsSandbox
|
||||
from pretix.helpers import OF_SELF
|
||||
from pretix.helpers.countries import CachedCountries
|
||||
@@ -1000,9 +999,6 @@ class StripeMethod(BasePaymentProvider):
|
||||
payment.confirm()
|
||||
except Quota.QuotaExceededException as e:
|
||||
raise PaymentException(str(e))
|
||||
|
||||
except SendMailException:
|
||||
raise PaymentException(_('There was an error sending the confirmation mail.'))
|
||||
elif intent.status == 'processing':
|
||||
if request:
|
||||
messages.warning(request, _('Your payment is pending completion. We will inform you as soon as the '
|
||||
|
||||
@@ -1654,11 +1654,6 @@ class ConfirmStep(CartMixin, AsyncAction, TemplateFlowStep):
|
||||
order = Order.objects.get(id=value)
|
||||
return self.get_order_url(order)
|
||||
|
||||
def get_error_message(self, exception):
|
||||
if exception.__class__.__name__ == 'SendMailException':
|
||||
return _('There was an error sending the confirmation mail. Please try again later.')
|
||||
return super().get_error_message(exception)
|
||||
|
||||
def get_error_url(self):
|
||||
return self.get_step_url(self.request)
|
||||
|
||||
|
||||
@@ -179,6 +179,7 @@ def _default_context(request):
|
||||
ctx['html_page_header'] = "".join(h for h in _html_page_header if h)
|
||||
ctx['footer'] = _footer
|
||||
ctx['site_url'] = settings.SITE_URL
|
||||
ctx['request_get_items'] = request.GET.items()
|
||||
|
||||
ctx['js_datetime_format'] = get_javascript_format_without_seconds('DATETIME_INPUT_FORMATS')
|
||||
ctx['js_date_format'] = get_javascript_format_without_seconds('DATE_INPUT_FORMATS')
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
{% endif %}
|
||||
<div id="invoice" class="profile-scope"
|
||||
data-profiles-id="addresses_json"
|
||||
data-address-information-url="{% url "js_helpers.address_form" %}?invoice=true&organizer={{ event.organizer.slug|urlencode }}&event={{ event.slug|urlencode }}">
|
||||
data-address-information-url="{% url "js_helpers.address_form" %}?invoice=true&organizer={{ event.organizer.slug|urlencode }}&event={{ event.slug|urlencode }}&locale={{ request.LANGUAGE_CODE }}">
|
||||
<div class="panel-body">
|
||||
{% if addresses_data %}
|
||||
<div class="form-group profile-select-container js-do-not-copy-answers">
|
||||
|
||||
@@ -372,6 +372,19 @@
|
||||
</article>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% if c.items_missing %}
|
||||
<div class="product-appendix-row">
|
||||
<p class="text-muted">
|
||||
{% trans "There are products selected in this add-on category that currently cannot be changed because they are not on sale:" %}
|
||||
</p>
|
||||
<ul class="text-muted">
|
||||
{% for itemvar, count in c.items_missing.items %}
|
||||
<li>{{ count }}x {{ itemvar.0 }}{% if itemvar.1 %} – {{ itemvar.1 }}{% endif %}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
</fieldset>
|
||||
{% endwith %}
|
||||
{% empty %}
|
||||
|
||||
@@ -493,7 +493,18 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if cart.show_rounding_info %}
|
||||
<div class="text-muted">
|
||||
<small>
|
||||
{% icon "info-circle" %}
|
||||
{% blocktrans trimmed %}
|
||||
Since you entered a business address, your price was computed from the
|
||||
VAT-exclusive price. Due to rounding, this caused a small change to the
|
||||
total price.
|
||||
{% endblocktrans %}
|
||||
</small>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
{% if not cart.is_ordered %}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
</li>
|
||||
<li class="text-center">
|
||||
<form class="form-inline" method="get" id="monthselform" action="{% eventurl event "presale:event.index" cart_namespace=cart_namespace %}">
|
||||
{% for f, v in request.GET.items %}
|
||||
{% for f, v in request_get_items %}
|
||||
{% if f != "date" %}
|
||||
<input type="hidden" name="{{ f }}" value="{{ v }}">
|
||||
{% endif %}
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@
|
||||
</li>
|
||||
<li class="text-center">
|
||||
<form class="form-inline" method="get" id="monthselform" action="{% eventurl event "presale:event.index" cart_namespace=cart_namespace %}">
|
||||
{% for f, v in request.GET.items %}
|
||||
{% for f, v in request_get_items %}
|
||||
{% if f != "date" %}
|
||||
<input type="hidden" name="{{ f }}" value="{{ v }}">
|
||||
{% endif %}
|
||||
|
||||
@@ -304,7 +304,7 @@
|
||||
<dt>{% trans "Phone number" %}</dt>
|
||||
<dd>{{ order.phone|phone_format }}</dd>
|
||||
{% endif %}
|
||||
{% if invoice_address_asked %}
|
||||
{% if invoice_address_asked and order.invoice_address.is_business %}
|
||||
<dt>{% trans "Company" %}</dt>
|
||||
<dd>{{ order.invoice_address.company }}</dd>
|
||||
{% endif %}
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
</h4>
|
||||
</summary>
|
||||
<div id="invoice" class="panel-collapse"
|
||||
data-address-information-url="{% url "js_helpers.address_form" %}?invoice=true&organizer={{ event.organizer.slug|urlencode }}&event={{ event.slug|urlencode }}">
|
||||
data-address-information-url="{% url "js_helpers.address_form" %}?invoice=true&organizer={{ event.organizer.slug|urlencode }}&event={{ event.slug|urlencode }}&locale={{ request.LANGUAGE_CODE }}">
|
||||
<div class="panel-body">
|
||||
{% if event.settings.invoice_address_explanation_text %}
|
||||
<div>
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
{% extends "pretixpresale/event/base.html" %}
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 %}
|
||||
{% block title %}{% trans "Resend order links" %}{% endblock %}
|
||||
{% block title %}{% trans "Resend order link" %}{% endblock %}
|
||||
{% block custom_header %}
|
||||
{{ block.super }}
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<h2>
|
||||
{% trans "Resend order links" %}
|
||||
{% trans "Resend order link" %}
|
||||
</h2>
|
||||
<p>
|
||||
{% blocktrans trimmed %}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user