mirror of
https://github.com/pretix/pretix.git
synced 2026-01-19 23:52:27 +00:00
Compare commits
55 Commits
py310
...
fix-progra
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8164f469d3 | ||
|
|
b5ad372bb2 | ||
|
|
cdea82d206 | ||
|
|
de9045afcf | ||
|
|
6b65cb4e33 | ||
|
|
c4792800f0 | ||
|
|
ca23f7ebc2 | ||
|
|
0259899e00 | ||
|
|
efb94265b2 | ||
|
|
2aa27f56f1 | ||
|
|
4f3d90fc50 | ||
|
|
9cf66de437 | ||
|
|
9f4cbabd30 | ||
|
|
0fc2d6134f | ||
|
|
1e0e16642d | ||
|
|
a58403559e | ||
|
|
dfd53f0ea2 | ||
|
|
06250ef55e | ||
|
|
ab3104fe65 | ||
|
|
bb6e424cde | ||
|
|
c2623dba60 | ||
|
|
d8f7465b03 | ||
|
|
ac0546499b | ||
|
|
ebbb532478 | ||
|
|
94dad4d0d2 | ||
|
|
a06cd687ba | ||
|
|
fd9f3ea6ed | ||
|
|
608622e3f3 | ||
|
|
4d94294e5a | ||
|
|
4dbdadabb5 | ||
|
|
d494c61cba | ||
|
|
55a7dfbff3 | ||
|
|
b8c271cf9c | ||
|
|
5af7e1b6d6 | ||
|
|
9222ce0ecd | ||
|
|
8afb0e43e0 | ||
|
|
c65fecf45e | ||
|
|
1c684d62d4 | ||
|
|
48809dc477 | ||
|
|
71df116079 | ||
|
|
ad64f6e88b | ||
|
|
891ba9d99c | ||
|
|
5cd1476a07 | ||
|
|
cb393a0b31 | ||
|
|
af59a89ecb | ||
|
|
1eb0008da9 | ||
|
|
d6489c6dd8 | ||
|
|
abe6acc9d8 | ||
|
|
2dcbb791f0 | ||
|
|
2efc40e20b | ||
|
|
0693681473 | ||
|
|
3aabc8a163 | ||
|
|
062f8fa409 | ||
|
|
106339c928 | ||
|
|
222ea08dd0 |
@@ -1,5 +1,5 @@
|
||||
sphinx==9.1.*
|
||||
sphinx-rtd-theme~=3.1.0rc1
|
||||
sphinx-rtd-theme~=3.1.0
|
||||
sphinxcontrib-httpdomain~=1.8.1
|
||||
sphinxcontrib-images~=1.0.1
|
||||
sphinxcontrib-jquery~=4.1
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
-e ../
|
||||
sphinx==9.1.*
|
||||
sphinx-rtd-theme~=3.1.0rc1
|
||||
sphinx-rtd-theme~=3.1.0
|
||||
sphinxcontrib-httpdomain~=1.8.1
|
||||
sphinxcontrib-images~=1.0.1
|
||||
sphinxcontrib-jquery~=4.1
|
||||
|
||||
@@ -29,7 +29,7 @@ dependencies = [
|
||||
"arabic-reshaper==3.0.0", # Support for Arabic in reportlab
|
||||
"babel",
|
||||
"BeautifulSoup4==4.14.*",
|
||||
"bleach==6.2.*",
|
||||
"bleach==6.3.*",
|
||||
"celery==5.6.*",
|
||||
"chardet==5.2.*",
|
||||
"cryptography>=44.0.0",
|
||||
@@ -37,8 +37,8 @@ dependencies = [
|
||||
"defusedcsv>=1.1.0",
|
||||
"dnspython==2.*",
|
||||
"Django[argon2]==4.2.*,>=4.2.26",
|
||||
"django-bootstrap3==25.2",
|
||||
"django-compressor==4.5.1",
|
||||
"django-bootstrap3==26.1",
|
||||
"django-compressor==4.6.0",
|
||||
"django-countries==8.2.*",
|
||||
"django-filter==25.1",
|
||||
"django-formset-js-improved==0.5.0.4",
|
||||
@@ -50,13 +50,13 @@ dependencies = [
|
||||
"django-localflavor==5.0",
|
||||
"django-markup",
|
||||
"django-oauth-toolkit==2.3.*",
|
||||
"django-otp==1.6.*",
|
||||
"django-phonenumber-field==8.3.*",
|
||||
"django-otp==1.7.*",
|
||||
"django-phonenumber-field==8.4.*",
|
||||
"django-redis==6.0.*",
|
||||
"django-scopes==2.0.*",
|
||||
"django-statici18n==2.6.*",
|
||||
"djangorestframework==3.16.*",
|
||||
"dnspython==2.7.*",
|
||||
"dnspython==2.8.*",
|
||||
"drf_ujson2==1.7.*",
|
||||
"geoip2==5.*",
|
||||
"importlib_metadata==8.*", # Polyfill, we can probably drop this once we require Python 3.10+
|
||||
@@ -65,7 +65,7 @@ dependencies = [
|
||||
"kombu==5.6.*",
|
||||
"libsass==0.23.*",
|
||||
"lxml",
|
||||
"markdown==3.9", # 3.3.5 requires importlib-metadata>=4.4, but django-bootstrap3 requires importlib-metadata<3.
|
||||
"markdown==3.10", # 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.*",
|
||||
@@ -75,7 +75,7 @@ dependencies = [
|
||||
"paypal-checkout-serversdk==1.0.*",
|
||||
"PyJWT==2.10.*",
|
||||
"phonenumberslite==9.0.*",
|
||||
"Pillow==11.3.*",
|
||||
"Pillow==12.1.*",
|
||||
"pretix-plugin-build",
|
||||
"protobuf==6.33.*",
|
||||
"psycopg2-binary",
|
||||
@@ -89,10 +89,10 @@ dependencies = [
|
||||
"pytz-deprecation-shim==0.1.*",
|
||||
"pyuca",
|
||||
"qrcode==8.2",
|
||||
"redis==7.0.*",
|
||||
"redis==7.1.*",
|
||||
"reportlab==4.4.*",
|
||||
"requests==2.32.*",
|
||||
"sentry-sdk==2.48.*",
|
||||
"sentry-sdk==2.49.*",
|
||||
"sepaxml==2.7.*",
|
||||
"stripe==7.9.*",
|
||||
"text-unidecode==1.*",
|
||||
@@ -113,7 +113,7 @@ dev = [
|
||||
"fakeredis==2.33.*",
|
||||
"flake8==7.3.*",
|
||||
"freezegun",
|
||||
"isort==6.1.*",
|
||||
"isort==7.0.*",
|
||||
"pep8-naming==0.15.*",
|
||||
"potypo",
|
||||
"pytest-asyncio>=0.24",
|
||||
@@ -123,7 +123,7 @@ dev = [
|
||||
"pytest-mock==3.15.*",
|
||||
"pytest-sugar",
|
||||
"pytest-xdist==3.8.*",
|
||||
"pytest==8.4.*",
|
||||
"pytest==9.0.*",
|
||||
"responses",
|
||||
]
|
||||
|
||||
|
||||
@@ -1601,7 +1601,7 @@ class OrderCreateSerializer(I18nAwareModelSerializer):
|
||||
order.sales_channel,
|
||||
[
|
||||
(cp.item_id, cp.subevent_id, cp.subevent.date_from if cp.subevent_id else None, cp.price,
|
||||
bool(cp.addon_to), cp.is_bundled, pos._voucher_discount)
|
||||
cp.addon_to, cp.is_bundled, pos._voucher_discount)
|
||||
for cp in order_positions
|
||||
]
|
||||
)
|
||||
|
||||
@@ -443,6 +443,7 @@ class OrganizerSettingsSerializer(SettingsSerializer):
|
||||
'customer_accounts',
|
||||
'customer_accounts_native',
|
||||
'customer_accounts_link_by_email',
|
||||
'customer_accounts_require_login_for_order_access',
|
||||
'invoice_regenerate_allowed',
|
||||
'contact_mail',
|
||||
'imprint_url',
|
||||
|
||||
@@ -106,7 +106,7 @@ class ItemViewSet(ConditionalListView, viewsets.ModelViewSet):
|
||||
'variations', 'addons', 'bundles', 'meta_values', 'meta_values__property',
|
||||
'variations__meta_values', 'variations__meta_values__property',
|
||||
'require_membership_types', 'variations__require_membership_types',
|
||||
'limit_sales_channels', 'variations__limit_sales_channels',
|
||||
'limit_sales_channels', 'variations__limit_sales_channels', 'program_times'
|
||||
).all()
|
||||
|
||||
def perform_create(self, serializer):
|
||||
|
||||
@@ -34,14 +34,13 @@
|
||||
|
||||
from contextlib import contextmanager
|
||||
|
||||
from asgiref.local import Local
|
||||
from babel import localedata
|
||||
from django.conf import settings
|
||||
from django.utils import translation
|
||||
from django.utils.formats import date_format, number_format
|
||||
from django.utils.translation import gettext
|
||||
|
||||
from pretix.base.templatetags.money import money_filter
|
||||
|
||||
from i18nfield.fields import ( # noqa
|
||||
I18nCharField, I18nTextarea, I18nTextField, I18nTextInput,
|
||||
)
|
||||
@@ -51,6 +50,9 @@ from i18nfield.strings import LazyI18nString # noqa
|
||||
from i18nfield.utils import I18nJSONEncoder # noqa
|
||||
|
||||
|
||||
_active_region = Local()
|
||||
|
||||
|
||||
class LazyDate:
|
||||
def __init__(self, value):
|
||||
self.value = value
|
||||
@@ -86,6 +88,8 @@ class LazyCurrencyNumber:
|
||||
return self.__str__()
|
||||
|
||||
def __str__(self):
|
||||
from pretix.base.templatetags.money import money_filter
|
||||
|
||||
return money_filter(self.value, self.currency)
|
||||
|
||||
|
||||
@@ -105,14 +109,41 @@ ALLOWED_LANGUAGES = dict(settings.LANGUAGES)
|
||||
|
||||
|
||||
def get_babel_locale():
|
||||
babel_locale = 'en'
|
||||
# Babel, and therefore django-phonenumberfield, do not support our custom locales such das de_Informal
|
||||
if translation.get_language():
|
||||
if localedata.exists(translation.get_language()):
|
||||
babel_locale = translation.get_language()
|
||||
elif localedata.exists(translation.get_language()[:2]):
|
||||
babel_locale = translation.get_language()[:2]
|
||||
return babel_locale
|
||||
# Babel, and therefore also django-phonenumberfield, do not support our custom locales such das de_Informal
|
||||
# Also, this returns best-effort region information for number formatting etc
|
||||
current_language = translation.get_language()
|
||||
current_region = getattr(_active_region, "value", None)
|
||||
|
||||
# Babel only accepts locales that exist on the system. We try combinations in the following order:
|
||||
# language-languageversion-region
|
||||
# language-region
|
||||
# language-languageversion
|
||||
# language
|
||||
# fallback to system default
|
||||
# fallback to english
|
||||
|
||||
try_locales = []
|
||||
if current_language:
|
||||
if "-" in current_language:
|
||||
lng_parts = current_language.split("-")
|
||||
if current_region:
|
||||
try_locales.append(f"{lng_parts[0]}_{lng_parts[1].title()}_{current_region.upper()}")
|
||||
try_locales.append(f"{lng_parts[0]}_{current_region.upper()}")
|
||||
try_locales.append(f"{lng_parts[0]}_{lng_parts[1].upper()}")
|
||||
try_locales.append(f"{lng_parts[0]}_{lng_parts[1].title()}")
|
||||
try_locales.append(f"{lng_parts[0]}")
|
||||
else:
|
||||
if current_region:
|
||||
try_locales.append(f"{current_language}_{current_region.upper()}")
|
||||
try_locales.append(f"{current_language}")
|
||||
|
||||
try_locales.append(settings.LANGUAGE_CODE)
|
||||
|
||||
for locale in try_locales:
|
||||
if localedata.exists(locale):
|
||||
return locale
|
||||
|
||||
return "en"
|
||||
|
||||
|
||||
def get_language_without_region(lng=None):
|
||||
@@ -132,6 +163,10 @@ def get_language_without_region(lng=None):
|
||||
return lng
|
||||
|
||||
|
||||
def set_region(region):
|
||||
_active_region.value = region
|
||||
|
||||
|
||||
@contextmanager
|
||||
def language(lng, region=None):
|
||||
"""
|
||||
@@ -143,15 +178,18 @@ def language(lng, region=None):
|
||||
formatting. If you pass a ``lng`` that already contains a region, e.g. ``pt-br``, the ``region``
|
||||
attribute will be ignored.
|
||||
"""
|
||||
_lng = translation.get_language()
|
||||
lng_before = translation.get_language()
|
||||
region_before = getattr(_active_region, "value", None)
|
||||
lng = lng or settings.LANGUAGE_CODE
|
||||
if '-' not in lng and region:
|
||||
lng += '-' + region.lower()
|
||||
translation.activate(lng)
|
||||
_active_region.value = region
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
translation.activate(_lng)
|
||||
translation.activate(lng_before)
|
||||
_active_region.value = region_before
|
||||
|
||||
|
||||
class LazyLocaleException(Exception):
|
||||
|
||||
@@ -64,7 +64,7 @@ class PeppolIdValidator:
|
||||
"0020": "[0-9]{9}",
|
||||
"0201": "[0-9a-zA-Z]{6}",
|
||||
"0204": "[0-9]{2,12}(-[0-9A-Z]{0,30})?-[0-9]{2}",
|
||||
"0208": "0[0-9]{9}",
|
||||
"0208": "[01][0-9]{9}",
|
||||
"0209": ".*",
|
||||
"0210": "[A-Z0-9]+",
|
||||
"0211": "IT[0-9]{11}",
|
||||
|
||||
@@ -35,7 +35,7 @@ from django.utils.translation.trans_real import (
|
||||
parse_accept_lang_header,
|
||||
)
|
||||
|
||||
from pretix.base.i18n import get_language_without_region
|
||||
from pretix.base.i18n import get_language_without_region, set_region
|
||||
from pretix.base.settings import global_settings_object
|
||||
from pretix.multidomain.urlreverse import (
|
||||
get_event_domain, get_organizer_domain,
|
||||
@@ -92,10 +92,14 @@ class LocaleMiddleware(MiddlewareMixin):
|
||||
)
|
||||
if '-' not in language and settings_holder.settings.region:
|
||||
language += '-' + settings_holder.settings.region
|
||||
if settings_holder.settings.region:
|
||||
set_region(settings_holder.settings.region)
|
||||
else:
|
||||
gs = global_settings_object(request)
|
||||
if '-' not in language and gs.settings.region:
|
||||
language += '-' + gs.settings.region
|
||||
if gs.settings.region:
|
||||
set_region(gs.settings.region)
|
||||
|
||||
translation.activate(language)
|
||||
request.LANGUAGE_CODE = get_language_without_region()
|
||||
|
||||
@@ -37,7 +37,7 @@ from pretix.base.decimal import round_decimal
|
||||
from pretix.base.models.base import LoggedModel
|
||||
|
||||
PositionInfo = namedtuple('PositionInfo',
|
||||
['item_id', 'subevent_id', 'subevent_date_from', 'line_price_gross', 'is_addon_to',
|
||||
['item_id', 'subevent_id', 'subevent_date_from', 'line_price_gross', 'addon_to',
|
||||
'voucher_discount'])
|
||||
|
||||
|
||||
@@ -279,6 +279,42 @@ class Discount(LoggedModel):
|
||||
for idx in condition_idx_group:
|
||||
collect_potential_discounts[idx] = [(self, inf, -1, subevent_id)]
|
||||
|
||||
def _addon_idx(self, positions, idx):
|
||||
"""
|
||||
If we have the following cart:
|
||||
|
||||
- Main product
|
||||
- 10x Addon product 5€
|
||||
- Main product
|
||||
- 10x Addon product 5€
|
||||
|
||||
And we have a discount rule that grants "every 10th product is free", people tend to expect
|
||||
|
||||
- Main product
|
||||
- 9x Addon product 5€
|
||||
- 1x Addon product free
|
||||
- Main product
|
||||
- 9x Addon product 5€
|
||||
- 1x Addon product free
|
||||
|
||||
And get confused if they get
|
||||
|
||||
- Main product
|
||||
- 8x Addon product 5€
|
||||
- 2x Addon product free
|
||||
- Main product
|
||||
- 10x Addon product 5€
|
||||
|
||||
Even if the result is the same. Therefore, we sort positions in the cart not only by price, but also by their
|
||||
relative index within their addon group. This is only a heuristic and there are *still* scenarios where the more
|
||||
unexpected version happens, e.g. if prices are different. We need to accept this as long as discounts work on
|
||||
cart level and not on addon-group level, but this simple sorting reduces the number of support issues by making
|
||||
the weird case less likely.
|
||||
"""
|
||||
if not positions[idx].addon_to:
|
||||
return 0
|
||||
return len([1 for i, p in positions.items() if i < idx and p.addon_to == positions[idx].addon_to])
|
||||
|
||||
def _apply_min_count(self, positions, condition_idx_group, benefit_idx_group, result, collect_potential_discounts, subevent_id):
|
||||
if len(condition_idx_group) < self.condition_min_count:
|
||||
return
|
||||
@@ -288,8 +324,8 @@ class Discount(LoggedModel):
|
||||
|
||||
if self.benefit_only_apply_to_cheapest_n_matches:
|
||||
# sort by line_price
|
||||
condition_idx_group = sorted(condition_idx_group, key=lambda idx: (positions[idx].line_price_gross, -idx))
|
||||
benefit_idx_group = sorted(benefit_idx_group, key=lambda idx: (positions[idx].line_price_gross, -idx))
|
||||
condition_idx_group = sorted(condition_idx_group, key=lambda idx: (positions[idx].line_price_gross, self._addon_idx(positions, idx), -idx))
|
||||
benefit_idx_group = sorted(benefit_idx_group, key=lambda idx: (positions[idx].line_price_gross, self._addon_idx(positions, idx), -idx))
|
||||
|
||||
# Prevent over-consuming of items, i.e. if our discount is "buy 2, get 1 free", we only
|
||||
# want to match multiples of 3
|
||||
@@ -434,7 +470,7 @@ class Discount(LoggedModel):
|
||||
for idx, p in positions.items():
|
||||
subevent_to_idx[p.subevent_id].append(idx)
|
||||
for v in subevent_to_idx.values():
|
||||
v.sort(key=lambda idx: positions[idx].line_price_gross)
|
||||
v.sort(key=lambda idx: (positions[idx].line_price_gross, self._addon_idx(positions, idx)))
|
||||
subevent_order = sorted(list(subevent_to_idx.keys()), key=lambda s: len(subevent_to_idx[s]), reverse=True)
|
||||
|
||||
# Build groups of exactly condition_min_count distinct subevents
|
||||
@@ -458,7 +494,7 @@ class Discount(LoggedModel):
|
||||
|
||||
# Sort the list by prices, then pick one. For "buy 2 get 1 free" we apply a "pick 1 from the start
|
||||
# and 2 from the end" scheme to optimize price distribution among groups
|
||||
candidates = sorted(candidates, key=lambda idx: positions[idx].line_price_gross)
|
||||
candidates = sorted(candidates, key=lambda idx: (positions[idx].line_price_gross, self._addon_idx(positions, idx)))
|
||||
if len(current_group) < (self.benefit_only_apply_to_cheapest_n_matches or 0):
|
||||
candidate = candidates[0]
|
||||
else:
|
||||
|
||||
@@ -141,8 +141,9 @@ class LogEntry(models.Model):
|
||||
|
||||
log_entry_type, meta = log_entry_types.get(action_type=self.action_type)
|
||||
if log_entry_type:
|
||||
sender = self.event if self.event else self.organizer
|
||||
link_info = log_entry_type.get_object_link_info(self)
|
||||
if is_app_active(self.event, meta['plugin']):
|
||||
if is_app_active(sender, meta['plugin']):
|
||||
return make_link(link_info, log_entry_type.object_link_wrapper)
|
||||
else:
|
||||
return make_link(link_info, log_entry_type.object_link_wrapper, is_active=False,
|
||||
|
||||
@@ -35,6 +35,7 @@ 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.helpers import OF_SELF
|
||||
|
||||
from ...helpers.format import format_map
|
||||
from ...helpers.names import build_name
|
||||
@@ -185,44 +186,47 @@ class WaitingListEntry(LoggedModel):
|
||||
if not free_seats:
|
||||
raise WaitingListException(_('No seat with this product is currently available.'))
|
||||
|
||||
if self.voucher:
|
||||
raise WaitingListException(_('A voucher has already been sent to this person.'))
|
||||
if '@' not in self.email:
|
||||
raise WaitingListException(_('This entry is anonymized and can no longer be used.'))
|
||||
|
||||
with transaction.atomic():
|
||||
e = self.email
|
||||
if self.name:
|
||||
e += ' / ' + self.name
|
||||
locked_wle = WaitingListEntry.objects.select_for_update(of=OF_SELF).get(pk=self.pk)
|
||||
if locked_wle.voucher:
|
||||
raise WaitingListException(_('A voucher has already been sent to this person.'))
|
||||
e = locked_wle.email
|
||||
if locked_wle.name:
|
||||
e += ' / ' + locked_wle.name
|
||||
v = Voucher.objects.create(
|
||||
event=self.event,
|
||||
event=locked_wle.event,
|
||||
max_usages=1,
|
||||
valid_until=now() + timedelta(hours=self.event.settings.waiting_list_hours),
|
||||
item=self.item,
|
||||
variation=self.variation,
|
||||
valid_until=now() + timedelta(hours=locked_wle.event.settings.waiting_list_hours),
|
||||
item=locked_wle.item,
|
||||
variation=locked_wle.variation,
|
||||
tag='waiting-list',
|
||||
comment=_('Automatically created from waiting list entry for {email}').format(
|
||||
email=e
|
||||
),
|
||||
block_quota=True,
|
||||
subevent=self.subevent,
|
||||
subevent=locked_wle.subevent,
|
||||
)
|
||||
v.log_action('pretix.voucher.added', {
|
||||
'item': self.item.pk,
|
||||
'variation': self.variation.pk if self.variation else None,
|
||||
'item': locked_wle.item.pk,
|
||||
'variation': locked_wle.variation.pk if locked_wle.variation else None,
|
||||
'tag': 'waiting-list',
|
||||
'block_quota': True,
|
||||
'valid_until': v.valid_until.isoformat(),
|
||||
'max_usages': 1,
|
||||
'subevent': self.subevent.pk if self.subevent else None,
|
||||
'subevent': locked_wle.subevent.pk if locked_wle.subevent else None,
|
||||
'source': 'waitinglist',
|
||||
}, user=user, auth=auth)
|
||||
v.log_action('pretix.voucher.added.waitinglist', {
|
||||
'email': self.email,
|
||||
'waitinglistentry': self.pk,
|
||||
'email': locked_wle.email,
|
||||
'waitinglistentry': locked_wle.pk,
|
||||
}, user=user, auth=auth)
|
||||
self.voucher = v
|
||||
self.save()
|
||||
locked_wle.voucher = v
|
||||
locked_wle.save()
|
||||
|
||||
self.refresh_from_db()
|
||||
|
||||
with language(self.locale, self.event.settings.region):
|
||||
self.send_mail(
|
||||
|
||||
@@ -1528,7 +1528,7 @@ class CartManager:
|
||||
self._sales_channel.identifier,
|
||||
[
|
||||
(cp.item_id, cp.subevent_id, cp.subevent.date_from if cp.subevent_id else None, cp.line_price_gross,
|
||||
bool(cp.addon_to), cp.is_bundled, cp.listed_price - cp.price_after_voucher)
|
||||
cp.addon_to, cp.is_bundled, cp.listed_price - cp.price_after_voucher)
|
||||
for cp in positions
|
||||
]
|
||||
)
|
||||
|
||||
@@ -121,7 +121,7 @@ class CrossSellingService:
|
||||
self.sales_channel,
|
||||
[
|
||||
(cp.item_id, cp.subevent_id, cp.subevent.date_from if cp.subevent_id else None, cp.line_price_gross,
|
||||
bool(cp.addon_to), cp.is_bundled,
|
||||
cp.addon_to, cp.is_bundled,
|
||||
cp.listed_price - cp.price_after_voucher)
|
||||
for cp in self.cartpositions
|
||||
],
|
||||
|
||||
@@ -914,7 +914,7 @@ def _check_positions(event: Event, now_dt: datetime, time_machine_now_dt: dateti
|
||||
sales_channel.identifier,
|
||||
[
|
||||
(cp.item_id, cp.subevent_id, cp.subevent.date_from if cp.subevent_id else None, cp.line_price_gross,
|
||||
bool(cp.addon_to), cp.is_bundled, cp.listed_price - cp.price_after_voucher)
|
||||
cp.addon_to, cp.is_bundled, cp.listed_price - cp.price_after_voucher)
|
||||
for cp in sorted_positions
|
||||
]
|
||||
)
|
||||
|
||||
@@ -174,7 +174,9 @@ def apply_discounts(event: Event, sales_channel: Union[str, SalesChannel],
|
||||
|
||||
:param event: Event the cart belongs to
|
||||
:param sales_channel: Sales channel the cart was created with
|
||||
:param positions: Tuple of the form ``(item_id, subevent_id, subevent_date_from, line_price_gross, is_addon_to, is_bundled, voucher_discount)``
|
||||
:param positions: Tuple of the form ``(item_id, subevent_id, subevent_date_from, line_price_gross, addon_to_id, is_bundled, voucher_discount)``
|
||||
``addon_to_id`` does not have to be the proper ID, any identifier is okay, even ``True``/``False`` are accepted, but
|
||||
a better result may be given if addons to the same main product have the same distinct value.
|
||||
:param collect_potential_discounts: If a `defaultdict(list)` is supplied, all discounts that could be applied to the cart
|
||||
based on the "consumed" items, but lack matching "benefitting" items will be collected therein.
|
||||
The dict will contain a mapping from index in the `positions` list of the item that could be consumed, to a list
|
||||
@@ -196,9 +198,9 @@ def apply_discounts(event: Event, sales_channel: Union[str, SalesChannel],
|
||||
).prefetch_related('condition_limit_products', 'benefit_limit_products').order_by('position', 'pk')
|
||||
for discount in discount_qs:
|
||||
result = discount.apply({
|
||||
idx: PositionInfo(item_id, subevent_id, subevent_date_from, line_price_gross, is_addon_to, voucher_discount)
|
||||
idx: PositionInfo(item_id, subevent_id, subevent_date_from, line_price_gross, addon_to, voucher_discount)
|
||||
for
|
||||
idx, (item_id, subevent_id, subevent_date_from, line_price_gross, is_addon_to, is_bundled, voucher_discount)
|
||||
idx, (item_id, subevent_id, subevent_date_from, line_price_gross, addon_to, is_bundled, voucher_discount)
|
||||
in enumerate(positions)
|
||||
if not is_bundled and idx not in new_prices
|
||||
}, collect_potential_discounts)
|
||||
|
||||
@@ -180,6 +180,19 @@ DEFAULTS = {
|
||||
widget=forms.CheckboxInput(attrs={'data-display-dependency': '#id_settings-customer_accounts'}),
|
||||
)
|
||||
},
|
||||
'customer_accounts_require_login_for_order_access': {
|
||||
'default': 'False',
|
||||
'type': bool,
|
||||
'form_class': forms.BooleanField,
|
||||
'serializer_class': serializers.BooleanField,
|
||||
'form_kwargs': dict(
|
||||
label=_("Require login to access order confirmation pages"),
|
||||
help_text=_("If enabled, users who were logged in at the time of purchase must also log in to access their order information. "
|
||||
"If a customer account is created while placing an order, the restriction only becomes active after the customer "
|
||||
"account is activated."),
|
||||
widget=forms.CheckboxInput(attrs={'data-display-dependency': '#id_settings-customer_accounts'}),
|
||||
)
|
||||
},
|
||||
'customer_accounts_link_by_email': {
|
||||
'default': 'False',
|
||||
'type': bool,
|
||||
|
||||
@@ -26,7 +26,8 @@ from babel.numbers import format_currency
|
||||
from django import template
|
||||
from django.conf import settings
|
||||
from django.template.defaultfilters import floatformat
|
||||
from django.utils import translation
|
||||
|
||||
from pretix.base.i18n import get_babel_locale
|
||||
|
||||
register = template.Library()
|
||||
|
||||
@@ -59,13 +60,10 @@ def money_filter(value: Decimal, arg='', hide_currency=False):
|
||||
if hide_currency:
|
||||
return floatformat(value, f"{places}g")
|
||||
|
||||
locale_parts = translation.get_language().split("-", 1)
|
||||
locale = locale_parts[0]
|
||||
if len(locale_parts) > 1 and len(locale_parts[1]) == 2:
|
||||
try:
|
||||
locale = Locale(locale_parts[0], locale_parts[1].upper())
|
||||
except UnknownLocaleError:
|
||||
pass
|
||||
try:
|
||||
locale = Locale(get_babel_locale())
|
||||
except UnknownLocaleError:
|
||||
locale = "en"
|
||||
|
||||
try:
|
||||
return format_currency(value, arg, locale=locale)
|
||||
|
||||
@@ -32,13 +32,14 @@
|
||||
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations under the License.
|
||||
|
||||
import html
|
||||
import re
|
||||
import urllib.parse
|
||||
|
||||
import bleach
|
||||
import markdown
|
||||
from bleach import DEFAULT_CALLBACKS
|
||||
from bleach.linkifier import build_email_re, build_url_re
|
||||
from bleach import DEFAULT_CALLBACKS, html5lib_shim
|
||||
from bleach.linkifier import build_email_re
|
||||
from django import template
|
||||
from django.conf import settings
|
||||
from django.core import signing
|
||||
@@ -124,6 +125,23 @@ ALLOWED_ATTRIBUTES = {
|
||||
|
||||
ALLOWED_PROTOCOLS = {'http', 'https', 'mailto', 'tel'}
|
||||
|
||||
|
||||
def build_url_re(tlds=tld_set, protocols=html5lib_shim.allowed_protocols):
|
||||
# Differs from bleach regex by allowing { and } in URL to allow placeholders in URL parameters
|
||||
return re.compile(
|
||||
r"""\(* # Match any opening parentheses.
|
||||
\b(?<![@.])(?:(?:{0}):/{{0,3}}(?:(?:\w+:)?\w+@)?)? # http://
|
||||
([\w-]+\.)+(?:{1})(?:\:[0-9]+)?(?!\.\w)\b # xx.yy.tld(:##)?
|
||||
(?:[/?][^\s\|\\\^`<>"]*)?
|
||||
# /path/zz (excluding "unsafe" chars from RFC 3986,
|
||||
# except for # and ~, which happen in practice)
|
||||
""".format(
|
||||
"|".join(sorted(protocols)), "|".join(sorted(tlds))
|
||||
),
|
||||
re.IGNORECASE | re.VERBOSE | re.UNICODE,
|
||||
)
|
||||
|
||||
|
||||
URL_RE = SimpleLazyObject(lambda: build_url_re(tlds=sorted(tld_set, key=len, reverse=True)))
|
||||
|
||||
EMAIL_RE = SimpleLazyObject(lambda: build_email_re(tlds=sorted(tld_set, key=len, reverse=True)))
|
||||
@@ -333,8 +351,14 @@ def markdown_compile_email(source, allowed_tags=None, allowed_attributes=ALLOWED
|
||||
# This is a workaround to fix placeholders in URL targets
|
||||
def context_callback(attrs, new=False):
|
||||
if (None, "href") in attrs and "{" in attrs[None, "href"]:
|
||||
# Do not use MODE_RICH_TO_HTML to avoid recursive linkification
|
||||
attrs[None, "href"] = escape(format_map(attrs[None, "href"], context=context, mode=SafeFormatter.MODE_RICH_TO_PLAIN))
|
||||
# Do not use MODE_RICH_TO_HTML to avoid recursive linkification.
|
||||
# We want to esacpe the end result, however, we need to unescape the input to prevent & being turned
|
||||
# to &amp; because the input is already escaped by the markdown parser.
|
||||
attrs[None, "href"] = escape(format_map(
|
||||
html.unescape(attrs[None, "href"]),
|
||||
context=context,
|
||||
mode=SafeFormatter.MODE_RICH_TO_PLAIN
|
||||
))
|
||||
return attrs
|
||||
|
||||
context_callbacks.append(context_callback)
|
||||
|
||||
@@ -474,6 +474,7 @@ class OrganizerSettingsForm(SettingsForm):
|
||||
'customer_accounts',
|
||||
'customer_accounts_native',
|
||||
'customer_accounts_link_by_email',
|
||||
'customer_accounts_require_login_for_order_access',
|
||||
'invoice_regenerate_allowed',
|
||||
'contact_mail',
|
||||
'imprint_url',
|
||||
|
||||
@@ -814,7 +814,7 @@ class OrganizerPluginStateLogEntryType(LogEntryType):
|
||||
if app and hasattr(app, 'PretixPluginMeta'):
|
||||
return {
|
||||
'href': reverse('control:organizer.settings.plugins', kwargs={
|
||||
'organizer': logentry.event.organizer.slug,
|
||||
'organizer': logentry.organizer.slug,
|
||||
}) + '#plugin_' + logentry.parsed_data['plugin'],
|
||||
'val': app.PretixPluginMeta.name
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
<div class="col-md-2">
|
||||
{% bootstrap_field formset.empty_form.overwrite layout='inline' form_group_class="" %}
|
||||
</div>
|
||||
{{ f.value_map.as_hidden }}
|
||||
{{ formset.empty_form.value_map.as_hidden }}
|
||||
<div class="col-md-2 text-right flip">
|
||||
<i class="fa fa-warning hidden" data-toggle="tooltip" title=""></i>
|
||||
<button type="button" class="btn btn-default hidden" data-edit-value-map data-toggle="modal"
|
||||
|
||||
@@ -132,6 +132,7 @@
|
||||
<legend>{% trans "Customer accounts" %}</legend>
|
||||
{% bootstrap_field sform.customer_accounts layout="control" %}
|
||||
{% bootstrap_field sform.customer_accounts_native layout="control" %}
|
||||
{% bootstrap_field sform.customer_accounts_require_login_for_order_access layout="control" %}
|
||||
{% bootstrap_field sform.customer_accounts_link_by_email layout="control" %}
|
||||
{% bootstrap_field sform.name_scheme layout="control" %}
|
||||
{% bootstrap_field sform.name_scheme_titles layout="control" %}
|
||||
|
||||
@@ -188,6 +188,8 @@ class LicenseCheckView(StaffMemberRequiredMixin, FormView):
|
||||
return None, None
|
||||
try:
|
||||
for k, v in pkg.metadata.items():
|
||||
if k == "License-Expression":
|
||||
license = v
|
||||
if k == "License":
|
||||
license = v
|
||||
if k == "Home-page":
|
||||
|
||||
@@ -2583,7 +2583,7 @@ class LogView(OrganizerPermissionRequiredMixin, PaginationMixin, ListView):
|
||||
def get_queryset(self):
|
||||
# technically, we'd also need to sort by pk since this is a paginated list, but in this case we just can't
|
||||
# bear the performance cost
|
||||
qs = self.request.organizer.all_logentries().select_related(
|
||||
qs = self.request.organizer.logentry_set.filter(event=None).select_related(
|
||||
'user', 'content_type', 'api_token', 'oauth_application', 'device'
|
||||
).order_by('-datetime')
|
||||
qs = qs.exclude(action_type__in=OVERVIEW_BANLIST)
|
||||
|
||||
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-01-05 12:12+0000\n"
|
||||
"PO-Revision-Date: 2026-01-05 15:14+0000\n"
|
||||
"PO-Revision-Date: 2026-01-11 22:00+0000\n"
|
||||
"Last-Translator: Jiří Pastrňák <jiri@pastrnak.email>\n"
|
||||
"Language-Team: Czech <https://translate.pretix.eu/projects/pretix/pretix/cs/>"
|
||||
"\n"
|
||||
@@ -1881,7 +1881,7 @@ msgstr "IČO"
|
||||
#: pretix/presale/templates/pretixpresale/event/checkout_confirm.html:99
|
||||
#: pretix/presale/templates/pretixpresale/event/order.html:327
|
||||
msgid "VAT ID"
|
||||
msgstr "DPH"
|
||||
msgstr "DIČ"
|
||||
|
||||
#: pretix/base/exporters/invoices.py:216 pretix/base/exporters/invoices.py:217
|
||||
#: pretix/base/exporters/invoices.py:218 pretix/base/exporters/invoices.py:219
|
||||
@@ -1926,7 +1926,7 @@ msgstr "Příjemce"
|
||||
#: pretix/control/templates/pretixcontrol/order/index.html:1064
|
||||
#: pretix/presale/templates/pretixpresale/event/checkout_confirm.html:111
|
||||
msgid "Internal reference"
|
||||
msgstr "Interní číslo"
|
||||
msgstr "Interní označení"
|
||||
|
||||
#: pretix/base/exporters/invoices.py:226 pretix/base/models/tax.py:161
|
||||
#: pretix/control/forms/event.py:1628
|
||||
@@ -2594,7 +2594,7 @@ msgstr "Kód vstupenky"
|
||||
#: pretix/base/modelimport_vouchers.py:272
|
||||
#: pretix/plugins/checkinlists/exporters.py:527
|
||||
msgid "Seat ID"
|
||||
msgstr "ID sedadla"
|
||||
msgstr "ID místa"
|
||||
|
||||
#: pretix/base/exporters/orderlist.py:623
|
||||
#: pretix/plugins/checkinlists/exporters.py:528
|
||||
@@ -2614,7 +2614,7 @@ msgstr "Řada"
|
||||
#: pretix/base/exporters/orderlist.py:626
|
||||
#: pretix/plugins/checkinlists/exporters.py:531
|
||||
msgid "Seat number"
|
||||
msgstr "Číslo sedadla"
|
||||
msgstr "Číslo místa"
|
||||
|
||||
#: pretix/base/exporters/orderlist.py:627
|
||||
#: pretix/control/templates/pretixcontrol/order/change.html:224
|
||||
@@ -3345,7 +3345,7 @@ msgstr "Prosím uveďte kratší jméno."
|
||||
#: pretix/base/forms/questions.py:314
|
||||
msgctxt "phonenumber"
|
||||
msgid "International area code"
|
||||
msgstr "PSČ"
|
||||
msgstr "Mezinárodní předvolba"
|
||||
|
||||
#: pretix/base/forms/questions.py:340
|
||||
msgctxt "phonenumber"
|
||||
@@ -3561,7 +3561,7 @@ msgstr "Firma nebo instituce"
|
||||
|
||||
#: pretix/base/forms/widgets.py:238
|
||||
msgid "Individual customer"
|
||||
msgstr "Zákazník"
|
||||
msgstr "Fyzická osoba"
|
||||
|
||||
#: pretix/base/invoicing/email.py:50
|
||||
msgid "Email invoice directly to accounting department"
|
||||
@@ -3571,19 +3571,15 @@ msgstr "Zaslat fakturu přímo účetnímu oddělení"
|
||||
msgid ""
|
||||
"If not selected, the invoice will be sent to you using the email address "
|
||||
"listed above."
|
||||
msgstr ""
|
||||
msgstr "Pokud tuto možnost nezvolíte, zašleme fakturu na e-mail uvedený výše."
|
||||
|
||||
#: pretix/base/invoicing/email.py:55
|
||||
#, fuzzy
|
||||
#| msgid "Email address verified"
|
||||
msgid "Email address for invoice"
|
||||
msgstr "E-mailová adresa ověřena"
|
||||
msgstr "E-mail pro zaslání faktury"
|
||||
|
||||
#: pretix/base/invoicing/email.py:91
|
||||
#, fuzzy
|
||||
#| msgid "Preview email"
|
||||
msgid "PDF via email"
|
||||
msgstr "Náhled e-mailu"
|
||||
msgstr "PDF do e-mailu"
|
||||
|
||||
#: pretix/base/invoicing/national.py:37
|
||||
msgctxt "italian_invoice"
|
||||
@@ -3642,7 +3638,7 @@ msgstr "Faktura od"
|
||||
#: pretix/base/invoicing/pdf.py:433
|
||||
msgctxt "invoice"
|
||||
msgid "Invoice to"
|
||||
msgstr "Faktura na"
|
||||
msgstr "Fakturováno"
|
||||
|
||||
#: pretix/base/invoicing/pdf.py:470 pretix/base/invoicing/pdf.py:1221
|
||||
msgctxt "invoice"
|
||||
@@ -3672,12 +3668,12 @@ msgstr "Datum zrušení"
|
||||
#: pretix/base/invoicing/pdf.py:504
|
||||
msgctxt "invoice"
|
||||
msgid "Original invoice date"
|
||||
msgstr "Původní datum faktury"
|
||||
msgstr "Datum originální faktury"
|
||||
|
||||
#: pretix/base/invoicing/pdf.py:511 pretix/base/invoicing/pdf.py:1258
|
||||
msgctxt "invoice"
|
||||
msgid "Invoice date"
|
||||
msgstr "Datum faktury"
|
||||
msgstr "Datum vystavení"
|
||||
|
||||
#: pretix/base/invoicing/pdf.py:527
|
||||
msgctxt "invoice"
|
||||
@@ -3704,7 +3700,7 @@ msgstr "Faktura č. {num}"
|
||||
#, python-brace-format
|
||||
msgctxt "invoice"
|
||||
msgid "Customer reference: {reference}"
|
||||
msgstr "Referenční číslo zákazníka: {reference}"
|
||||
msgstr "Interní označení: {reference}"
|
||||
|
||||
#: pretix/base/invoicing/pdf.py:668
|
||||
msgctxt "invoice"
|
||||
@@ -3732,7 +3728,7 @@ msgstr "Faktura"
|
||||
#: pretix/presale/templates/pretixpresale/event/order.html:244
|
||||
msgctxt "invoice"
|
||||
msgid "Cancellation"
|
||||
msgstr "Zrušení"
|
||||
msgstr "Storno"
|
||||
|
||||
#: pretix/base/invoicing/pdf.py:732 pretix/base/invoicing/pdf.py:740
|
||||
msgctxt "invoice"
|
||||
@@ -3768,13 +3764,13 @@ msgstr "Suma"
|
||||
#, python-brace-format
|
||||
msgctxt "invoice"
|
||||
msgid "Single price: {net_price} net / {gross_price} gross"
|
||||
msgstr "Jednotlivá cena: {net_price} netto / {gross_price} brutto"
|
||||
msgstr "Jednotková cena: {net_price} netto / {gross_price} brutto"
|
||||
|
||||
#: pretix/base/invoicing/pdf.py:900
|
||||
#, python-brace-format
|
||||
msgctxt "invoice"
|
||||
msgid "Single price: {price}"
|
||||
msgstr "Jednotná cena: {price}"
|
||||
msgstr "Jednotková cena: {price}"
|
||||
|
||||
#: pretix/base/invoicing/pdf.py:943 pretix/base/invoicing/pdf.py:948
|
||||
msgctxt "invoice"
|
||||
@@ -3802,12 +3798,10 @@ msgid "Remaining amount"
|
||||
msgstr "Zbývající částka"
|
||||
|
||||
#: 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 "Datum akce: {date_range}"
|
||||
msgstr "Fakturované období: {daterange}"
|
||||
|
||||
#: pretix/base/invoicing/pdf.py:1039
|
||||
msgctxt "invoice"
|
||||
@@ -4175,7 +4169,7 @@ msgstr "Bylo nalezeno více shodných míst."
|
||||
#: pretix/base/modelimport_orders.py:628
|
||||
#: pretix/base/modelimport_vouchers.py:293
|
||||
msgid "No matching seat was found."
|
||||
msgstr "Nebylo nalezeno žádné odpovídající sedadlo."
|
||||
msgstr "Nebylo nalezeno žádné odpovídající místo."
|
||||
|
||||
#: pretix/base/modelimport_orders.py:631
|
||||
#: pretix/base/modelimport_vouchers.py:296 pretix/base/services/cart.py:220
|
||||
@@ -4280,7 +4274,7 @@ msgstr "Pokud si vyberete místo, musíte si vybrat datum."
|
||||
|
||||
#: pretix/base/modelimport_vouchers.py:299 pretix/base/models/vouchers.py:516
|
||||
msgid "You need to choose a specific product if you select a seat."
|
||||
msgstr "Pokud si vyberete sedadlo, musíte si vybrat konkrétní produkt."
|
||||
msgstr "Pokud si vyberete místo, musíte zvolit konkrétní produkt."
|
||||
|
||||
#: pretix/base/modelimport_vouchers.py:302 pretix/base/models/vouchers.py:519
|
||||
msgid "Seat-specific vouchers can only be used once."
|
||||
@@ -4289,7 +4283,7 @@ msgstr "Poukazy na konkrétní místo lze použít pouze jednou."
|
||||
#: pretix/base/modelimport_vouchers.py:306 pretix/base/models/vouchers.py:522
|
||||
#, python-brace-format
|
||||
msgid "You need to choose the product \"{prod}\" for this seat."
|
||||
msgstr "Pro toto sedadlo je třeba vybrat produkt \"{prod}\"."
|
||||
msgstr "Pro toto místo je třeba vybrat produkt \"{prod}\"."
|
||||
|
||||
#: pretix/base/modelimport_vouchers.py:318 pretix/base/models/vouchers.py:288
|
||||
#: pretix/control/templates/pretixcontrol/vouchers/index.html:129
|
||||
@@ -5237,13 +5231,13 @@ msgstr ""
|
||||
#, python-format
|
||||
msgctxt "invoice"
|
||||
msgid "Tax ID: %s"
|
||||
msgstr "DIČ: %s"
|
||||
msgstr "IČO: %s"
|
||||
|
||||
#: pretix/base/models/invoices.py:240 pretix/base/services/invoices.py:155
|
||||
#, python-format
|
||||
msgctxt "invoice"
|
||||
msgid "VAT-ID: %s"
|
||||
msgstr "IČO: %s"
|
||||
msgstr "DIČ: %s"
|
||||
|
||||
#: pretix/base/models/items.py:93
|
||||
msgid "Category name"
|
||||
@@ -6446,7 +6440,7 @@ msgstr "Objednaný produkt \"{item}\" již není k dispozici."
|
||||
#: pretix/base/models/orders.py:1066
|
||||
#, python-brace-format
|
||||
msgid "The seat \"{seat}\" is no longer available."
|
||||
msgstr "Sedadlo \"{seat}\" již není k dispozici.."
|
||||
msgstr "Místo \"{seat}\" již není k dispozici."
|
||||
|
||||
#: pretix/base/models/orders.py:1067
|
||||
#, python-brace-format
|
||||
@@ -6635,7 +6629,7 @@ msgstr "Obchodní zákazník"
|
||||
|
||||
#: pretix/base/models/orders.py:3407
|
||||
msgid "This reference will be printed on your invoice for your convenience."
|
||||
msgstr "Tento odkaz bude pro vaše potřeby vytištěn na faktuře."
|
||||
msgstr "Tato informace bude uvedena na faktuře pro vaše potřeby."
|
||||
|
||||
#: pretix/base/models/orders.py:3534
|
||||
msgid "Transmission type"
|
||||
@@ -6678,7 +6672,7 @@ msgstr ""
|
||||
#: pretix/control/templates/pretixcontrol/organizers/index.html:6
|
||||
#: pretix/control/templates/pretixcontrol/organizers/index.html:8
|
||||
msgid "Organizers"
|
||||
msgstr "Organizátor"
|
||||
msgstr "Pořadatelé"
|
||||
|
||||
#: pretix/base/models/organizer.py:350
|
||||
#: pretix/control/templates/pretixcontrol/organizers/teams.html:35
|
||||
@@ -6831,7 +6825,7 @@ msgstr "Řada {number}"
|
||||
#: pretix/base/models/seating.py:205
|
||||
#, python-brace-format
|
||||
msgid "Seat {number}"
|
||||
msgstr "Sedadlo {number}"
|
||||
msgstr "Místo {number}"
|
||||
|
||||
#: pretix/base/models/tax.py:143
|
||||
msgid "Standard rates"
|
||||
@@ -7273,7 +7267,7 @@ msgstr ""
|
||||
#: pretix/base/models/vouchers.py:507
|
||||
#, python-brace-format
|
||||
msgid "The specified seat ID \"{id}\" does not exist for this event."
|
||||
msgstr "Zadané ID sedadla \"{id}\" pro tuto událost neexistuje."
|
||||
msgstr "Zadané ID místa \"{id}\" pro tuto událost neexistuje."
|
||||
|
||||
#: pretix/base/models/vouchers.py:511
|
||||
#, python-brace-format
|
||||
@@ -7314,7 +7308,7 @@ msgstr "Tento produkt není v současné době k dispozici."
|
||||
|
||||
#: pretix/base/models/waitinglist.py:186
|
||||
msgid "No seat with this product is currently available."
|
||||
msgstr "K tomuto produktu není v současné době k dispozici žádné sedadlo."
|
||||
msgstr "K tomuto produktu nejsou v současné době k dispozici žádná místa."
|
||||
|
||||
#: pretix/base/models/waitinglist.py:189
|
||||
msgid "A voucher has already been sent to this person."
|
||||
@@ -8076,14 +8070,12 @@ msgid "Printing time"
|
||||
msgstr "Datum tisku"
|
||||
|
||||
#: pretix/base/pdf.py:422 pretix/control/forms/item.py:741
|
||||
#, fuzzy
|
||||
msgid "Purchase date"
|
||||
msgstr "Zakoupeno"
|
||||
msgstr "Zakoupeno dne"
|
||||
|
||||
#: pretix/base/pdf.py:430
|
||||
#, fuzzy
|
||||
msgid "Purchase date and time"
|
||||
msgstr "Zakoupeno"
|
||||
msgstr "Zakoupeno dne a v čase"
|
||||
|
||||
#: pretix/base/pdf.py:438
|
||||
#, fuzzy
|
||||
@@ -8133,20 +8125,20 @@ msgstr ""
|
||||
|
||||
#: pretix/base/pdf.py:505
|
||||
msgid "Seat: Full name"
|
||||
msgstr "Sedadlo: Celé jméno"
|
||||
msgstr "Místo: Celé jméno"
|
||||
|
||||
#: pretix/base/pdf.py:506
|
||||
msgid "Ground floor, Row 3, Seat 4"
|
||||
msgstr "Přízemí, řada 3, sedadlo 4"
|
||||
msgstr "Přízemí, řada 3, místo 4"
|
||||
|
||||
#: pretix/base/pdf.py:508 pretix/base/pdf.py:514
|
||||
#: pretix/control/forms/orders.py:344
|
||||
msgid "General admission"
|
||||
msgstr "včetně všech daní"
|
||||
msgstr "Základní vstupné"
|
||||
|
||||
#: pretix/base/pdf.py:511
|
||||
msgid "Seat: zone"
|
||||
msgstr "Sedadlo: zóna"
|
||||
msgstr "Místo: zóna"
|
||||
|
||||
#: pretix/base/pdf.py:512
|
||||
msgid "Ground floor"
|
||||
@@ -8154,11 +8146,11 @@ msgstr "parket"
|
||||
|
||||
#: pretix/base/pdf.py:517
|
||||
msgid "Seat: row"
|
||||
msgstr "sedadlo: řada"
|
||||
msgstr "Místo: řada"
|
||||
|
||||
#: pretix/base/pdf.py:522
|
||||
msgid "Seat: seat number"
|
||||
msgstr "sedadlo: číslo"
|
||||
msgstr "Místo: číslo"
|
||||
|
||||
#: pretix/base/pdf.py:527
|
||||
msgid "Date and time of first scan"
|
||||
@@ -8554,7 +8546,7 @@ msgstr "Tento poukaz není platný pro tento produkt."
|
||||
|
||||
#: pretix/base/services/cart.py:191
|
||||
msgid "This voucher is not valid for this seat."
|
||||
msgstr "Tento poukaz není platný pro toto sedadlo."
|
||||
msgstr "Tento poukaz není platný pro toto místo."
|
||||
|
||||
#: pretix/base/services/cart.py:193
|
||||
msgid ""
|
||||
@@ -10354,11 +10346,8 @@ msgid "Automatic, but prefer invoice date over event date"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/base/settings.py:1169 pretix/base/settings.py:1180
|
||||
#, fuzzy
|
||||
#| msgctxt "invoice"
|
||||
#| msgid "Invoice date"
|
||||
msgid "Invoice date"
|
||||
msgstr "Datum faktury"
|
||||
msgstr "Datum vystavení"
|
||||
|
||||
#: pretix/base/settings.py:1173
|
||||
#, fuzzy
|
||||
@@ -10411,11 +10400,11 @@ msgstr "ulice Alberta-Einstein 52"
|
||||
|
||||
#: pretix/base/settings.py:1299
|
||||
msgid "Domestic tax ID"
|
||||
msgstr "Domácí daňové identifikační číslo"
|
||||
msgstr "Lokální identifikační číslo"
|
||||
|
||||
#: pretix/base/settings.py:1300
|
||||
msgid "e.g. tax number in Germany, ABN in Australia, …"
|
||||
msgstr "např. daňové číslo v Německu, číslo ABN v Austrálii, …"
|
||||
msgstr "např. IČO v Česku, daňové číslo v Německu, číslo ABN v Austrálii, …"
|
||||
|
||||
#: pretix/base/settings.py:1310
|
||||
msgid "EU VAT ID"
|
||||
@@ -12707,7 +12696,7 @@ msgstr "Pan"
|
||||
#: pretix/base/settings.py:3873
|
||||
msgctxt "person_name"
|
||||
msgid "Degree (after name)"
|
||||
msgstr "titul (za jménem)"
|
||||
msgstr "Titul (za jménem)"
|
||||
|
||||
#: pretix/base/settings.py:3895
|
||||
msgctxt "person_name_sample"
|
||||
@@ -12922,7 +12911,7 @@ msgstr "Očekávaný název hostitele podle konfigurace"
|
||||
|
||||
#: pretix/base/templates/400_hostname.html:26
|
||||
msgid "Received headers"
|
||||
msgstr "Přijaté titulky"
|
||||
msgstr "Přijaté hlavičky"
|
||||
|
||||
#: pretix/base/templates/400_hostname.html:32
|
||||
msgid "ignored"
|
||||
@@ -15751,7 +15740,7 @@ msgstr "Doplňkový produkt k"
|
||||
#: pretix/presale/templates/pretixpresale/event/checkout_membership.html:23
|
||||
#: pretix/presale/templates/pretixpresale/event/checkout_questions.html:101
|
||||
msgid "Seat"
|
||||
msgstr "Sedadlo"
|
||||
msgstr "Místo"
|
||||
|
||||
#: pretix/control/forms/orders.py:348
|
||||
#: pretix/control/templates/pretixcontrol/order/change.html:182
|
||||
@@ -16557,7 +16546,7 @@ msgstr "Pozice #{posid}: Použité členství bylo změněno."
|
||||
#: pretix/control/logdisplay.py:117
|
||||
#, python-brace-format
|
||||
msgid "Position #{posid}: Seat \"{old_seat}\" changed to \"{new_seat}\"."
|
||||
msgstr "Pozice #{posid}: Sedadlo \" {old_seat}\" se změnilo na \"{new_seat}\"."
|
||||
msgstr "Pozice #{posid}: Místo \" {old_seat}\" se změnilo na \"{new_seat}\"."
|
||||
|
||||
#: pretix/control/logdisplay.py:127
|
||||
#, python-brace-format
|
||||
@@ -18641,7 +18630,7 @@ msgstr "běží v režimu vývoje"
|
||||
#: pretix/presale/templates/pretixpresale/postmessage.html:27
|
||||
#: pretix/presale/templates/pretixpresale/waiting.html:42
|
||||
msgid "If this takes longer than a few minutes, please contact us."
|
||||
msgstr "Pokud to trvá déle než několik minut, kontaktujte nás."
|
||||
msgstr "Pokud akce trvá déle než několik minut, kontaktujte nás."
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/boxoffice/payment.html:4
|
||||
#: pretix/control/templates/pretixcontrol/organizers/devices.html:71
|
||||
@@ -18759,7 +18748,7 @@ msgstr "ID transakce"
|
||||
#: pretix/plugins/banktransfer/templates/pretixplugins/banktransfer/control.html:32
|
||||
#: pretix/plugins/banktransfer/templates/pretixplugins/banktransfer/import_assign.html:33
|
||||
msgid "Reference"
|
||||
msgstr "Důvod převodu"
|
||||
msgstr "Zpráva pro příjemce"
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/boxoffice/payment.html:100
|
||||
msgid "Terminal ID"
|
||||
@@ -21587,9 +21576,8 @@ msgid "August"
|
||||
msgstr ""
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/global_sysreport.html:24
|
||||
#, fuzzy
|
||||
msgid "September"
|
||||
msgstr "Číslo sedadla"
|
||||
msgstr "Září"
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/global_sysreport.html:25
|
||||
msgid "October"
|
||||
@@ -23245,7 +23233,7 @@ msgstr ""
|
||||
#: pretix/control/templates/pretixcontrol/order/index.html:465
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_cart.html:55
|
||||
msgid "Voucher code used:"
|
||||
msgstr ""
|
||||
msgstr "Použitý poukaz:"
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/order/index.html:467
|
||||
#, python-format
|
||||
@@ -23309,12 +23297,12 @@ msgstr "Celkem"
|
||||
#: pretix/control/templates/pretixcontrol/order/index.html:789
|
||||
#: pretix/presale/templates/pretixpresale/event/order.html:210
|
||||
msgid "Successful payments"
|
||||
msgstr ""
|
||||
msgstr "Úspěšné platby"
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/order/index.html:798
|
||||
#: pretix/presale/templates/pretixpresale/event/order.html:219
|
||||
msgid "Pending total"
|
||||
msgstr ""
|
||||
msgstr "Čeká na platbu"
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/order/index.html:824
|
||||
#: pretix/control/templates/pretixcontrol/search/payments.html:88
|
||||
@@ -28356,7 +28344,7 @@ msgstr ""
|
||||
#: pretix/control/views/organizer.py:3483
|
||||
#: pretix/control/views/organizer.py:3527
|
||||
msgid "Your changes could not be saved."
|
||||
msgstr ""
|
||||
msgstr "Vaše změny nebyly uloženy."
|
||||
|
||||
#: pretix/control/views/organizer.py:982
|
||||
msgid "The selected team cannot be deleted."
|
||||
@@ -30853,7 +30841,7 @@ msgstr "Stránka %d z %d"
|
||||
#: pretix/plugins/reports/exporters.py:210
|
||||
#, python-format
|
||||
msgid "Page %d"
|
||||
msgstr "Strana %dd"
|
||||
msgstr "Stránka %dd"
|
||||
|
||||
#: pretix/plugins/reports/exporters.py:212
|
||||
#, python-format
|
||||
@@ -33199,7 +33187,7 @@ msgstr "Váš košík"
|
||||
#: pretix/presale/templates/pretixpresale/event/checkout_confirm.html:27
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_cart_box.html:18
|
||||
msgid "Cart expired"
|
||||
msgstr "Nákupní košík vypršel"
|
||||
msgstr "Rezervace košíku vypršela"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/checkout_base.html:36
|
||||
msgid "Show full cart"
|
||||
@@ -33430,7 +33418,7 @@ msgstr ""
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/checkout_questions.html:9
|
||||
msgid "Before we continue, we need you to answer some questions."
|
||||
msgstr "Před provedením objednávky prosím odpovězte na níže uvedené otázky."
|
||||
msgstr "Pro dokončení objednávky potřebujeme následující údaje."
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/checkout_questions.html:49
|
||||
msgid "Auto-fill with address"
|
||||
@@ -33444,7 +33432,7 @@ msgstr "Vyplnit formulář"
|
||||
#: pretix/presale/templates/pretixpresale/event/checkout_questions.html:93
|
||||
#: pretix/presale/templates/pretixpresale/event/checkout_questions.html:170
|
||||
msgid "Copy answers from above"
|
||||
msgstr "Zkopírujte odpovědi z výše uvedených položek"
|
||||
msgstr "Zkopírujte odpovědi z předchozího"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/checkout_questions.html:150
|
||||
msgid "Auto-fill with profile"
|
||||
@@ -33569,7 +33557,7 @@ msgstr "Zobrazit varianty"
|
||||
#: pretix/presale/templates/pretixpresale/event/voucher.html:147
|
||||
#: pretix/presale/templates/pretixpresale/event/voucher.html:304
|
||||
msgid "Original price:"
|
||||
msgstr "Originální cena:"
|
||||
msgstr "Původní cena:"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_addon_choice.html:136
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_addon_choice.html:278
|
||||
@@ -33717,7 +33705,7 @@ msgstr "Celková cena"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_cart.html:46
|
||||
msgid "Seat:"
|
||||
msgstr "Sedadlo:"
|
||||
msgstr "Místo:"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_cart.html:61
|
||||
msgctxt "subevent"
|
||||
@@ -33862,16 +33850,12 @@ msgstr ""
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_cart.html:514
|
||||
#: pretix/presale/templates/pretixpresale/fragment_modals.html:48
|
||||
#, fuzzy
|
||||
#| msgid "Event description"
|
||||
msgid "Renew reservation"
|
||||
msgstr "Popis akce"
|
||||
msgstr "Obnovit rezervaci"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_cart.html:526
|
||||
#, fuzzy
|
||||
#| msgid "Reservation period"
|
||||
msgid "Reservation renewed"
|
||||
msgstr "Doba rezervace"
|
||||
msgstr "Rezervace obnovena"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_cart.html:532
|
||||
msgid "Overview of your ordered products."
|
||||
@@ -34176,14 +34160,12 @@ msgstr "Zobrazit obraz %(item)s v celé velikosti"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_product_list.html:131
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_product_list.html:288
|
||||
#, fuzzy, python-format
|
||||
#| msgid "%(count)s event"
|
||||
#| msgid_plural "%(count)s events"
|
||||
#, python-format
|
||||
msgid "%(amount)s× in your cart"
|
||||
msgid_plural "%(amount)s× in your cart"
|
||||
msgstr[0] "%(count)s akce"
|
||||
msgstr[1] "%(count)s akce"
|
||||
msgstr[2] "%(count)s akcí"
|
||||
msgstr[0] "%(amount)s× ve vašem košíku"
|
||||
msgstr[1] "%(amount)s× ve vašem košíku"
|
||||
msgstr[2] "%(amount)s× ve vašem košíku"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_product_list.html:209
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_product_list.html:374
|
||||
@@ -34446,19 +34428,14 @@ msgid "Please note that we still await your payment to complete the process."
|
||||
msgstr "Upozorňujeme, že k dokončení procesu stále čekáme na vaši platbu."
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/order.html:56
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Please bookmark or save the link to this exact page if you want to access "
|
||||
#| "your order later. We also sent you an email containing the link to the "
|
||||
#| "address you specified."
|
||||
msgid ""
|
||||
"Please bookmark or save the link to this exact page if you want to access "
|
||||
"your order later. We also sent you an email to the address you specified "
|
||||
"containing the link to this page."
|
||||
msgstr ""
|
||||
"Pokud chcete mít přístup ke své objednávce později, přidejte si prosím odkaz "
|
||||
"na tuto stránku do záložek nebo si jej uložte. Na vaši zadanou adresu jsme "
|
||||
"vám také zaslali e-mail s odkazem."
|
||||
"Pokud chcete mít k objednávce přístup i později, přidejte si prosím tuto "
|
||||
"stránku do záložek. Na vámi zadanou adresu jsme vám také zaslali e-mail s "
|
||||
"odkazem na tuto stránku."
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/order.html:60
|
||||
msgid ""
|
||||
@@ -34567,7 +34544,7 @@ msgstr "Změňte své údaje"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/order.html:335
|
||||
msgid "Internal Reference"
|
||||
msgstr "Interní reference"
|
||||
msgstr "Interní označení"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/order.html:354
|
||||
msgctxt "action"
|
||||
@@ -34581,10 +34558,9 @@ msgid "Change your order"
|
||||
msgstr "Změnit objednávku"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/order.html:358
|
||||
#, fuzzy
|
||||
msgctxt "action"
|
||||
msgid "Cancel your order"
|
||||
msgstr "Zrušit objednávku"
|
||||
msgstr "Zrušení objednávky"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/order.html:366
|
||||
msgid ""
|
||||
@@ -34791,7 +34767,7 @@ msgid ""
|
||||
"Modifying your invoice address will not automatically generate a new "
|
||||
"invoice. Please contact us if you need a new invoice."
|
||||
msgstr ""
|
||||
"Úpravou adresy faktury se automaticky nevytvoří nová faktura. Pokud "
|
||||
"Úpravou fakturačních údajů se automaticky nevytvoří nová faktura. Pokud "
|
||||
"potřebujete novou fakturu, kontaktujte nás."
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/order_modify.html:88
|
||||
@@ -34839,7 +34815,7 @@ msgstr ""
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/payment_qr_codes.html:36
|
||||
msgid "Scan the QR code with your banking app"
|
||||
msgstr ""
|
||||
msgstr "Naskenujte QR kód svou bankovní aplikací"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/position.html:7
|
||||
msgid "Registration details"
|
||||
@@ -35631,12 +35607,12 @@ msgid ""
|
||||
"Your cart timeout was extended. Please note that some of the prices in your "
|
||||
"cart changed."
|
||||
msgstr ""
|
||||
"Platnost vašeho košíku byla prodloužena. Berte prosím na vědomí, že ceny "
|
||||
"některých položek ve vašem košíku se změnily."
|
||||
|
||||
#: pretix/presale/views/cart.py:573
|
||||
#, fuzzy
|
||||
#| msgid "Your cart has been updated."
|
||||
msgid "Your cart timeout was extended."
|
||||
msgstr "Váš košík byl aktualizován."
|
||||
msgstr "Platnost vašeho košíku byla prodloužena."
|
||||
|
||||
#: pretix/presale/views/cart.py:588
|
||||
msgid "The products have been successfully added to your cart."
|
||||
|
||||
@@ -8,8 +8,8 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-01-05 12:13+0000\n"
|
||||
"PO-Revision-Date: 2025-09-08 18:57+0000\n"
|
||||
"Last-Translator: Alois Pospíšil <alois.pospisil@gmail.com>\n"
|
||||
"PO-Revision-Date: 2026-01-08 04:00+0000\n"
|
||||
"Last-Translator: Jiří Pastrňák <jiri@pastrnak.email>\n"
|
||||
"Language-Team: Czech <https://translate.pretix.eu/projects/pretix/pretix-js/"
|
||||
"cs/>\n"
|
||||
"Language: cs\n"
|
||||
@@ -17,7 +17,7 @@ msgstr ""
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
|
||||
"X-Generator: Weblate 5.13\n"
|
||||
"X-Generator: Weblate 5.15.1\n"
|
||||
|
||||
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:56
|
||||
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:62
|
||||
@@ -416,7 +416,7 @@ msgstr ""
|
||||
|
||||
#: pretix/static/pretixbase/js/asynctask.js:276
|
||||
msgid "If this takes longer than a few minutes, please contact us."
|
||||
msgstr ""
|
||||
msgstr "Pokud akce trvá déle než několik minut, kontaktujte nás."
|
||||
|
||||
#: pretix/static/pretixbase/js/asynctask.js:331
|
||||
msgid "Close message"
|
||||
@@ -734,7 +734,7 @@ msgstr ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/cart.js:49
|
||||
msgid "Cart expired"
|
||||
msgstr "Nákupní košík vypršel"
|
||||
msgstr "Rezervace košíku vypršela"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/cart.js:58
|
||||
#: pretix/static/pretixpresale/js/ui/cart.js:84
|
||||
@@ -753,27 +753,23 @@ msgstr[2] ""
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/cart.js:83
|
||||
msgid "Your cart has expired."
|
||||
msgstr "Nákupní košík vypršel."
|
||||
msgstr "Platnost rezervace vašeho košíku vypršela."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/cart.js:86
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "The items in your cart are no longer reserved for you. You can still "
|
||||
#| "complete your order as long as they’re available."
|
||||
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 ""
|
||||
"Produkty v nákupním košíku již nejsou pro vás rezervovány. Pokud je lístek "
|
||||
"stále dostupný, můžete objednávku dokončit."
|
||||
"Produkty v nákupním košíku již nejsou rezervovány. Svou objednávku se přesto "
|
||||
"můžete pokusit dokončit, některé položky však už nemusí být dostupné."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/cart.js:87
|
||||
msgid "Do you want to renew the reservation period?"
|
||||
msgstr ""
|
||||
msgstr "Chcete obnovit rezervaci košíku?"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/cart.js:90
|
||||
msgid "Renew reservation"
|
||||
msgstr ""
|
||||
msgstr "Obnovit rezervaci"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:194
|
||||
msgid "The organizer keeps %(currency)s %(amount)s"
|
||||
|
||||
@@ -8,8 +8,8 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-01-05 12:12+0000\n"
|
||||
"PO-Revision-Date: 2025-11-22 23:00+0000\n"
|
||||
"Last-Translator: CVZ-es <damien.bremont@casadevelazquez.org>\n"
|
||||
"PO-Revision-Date: 2026-01-14 00:00+0000\n"
|
||||
"Last-Translator: Mario Montes <mario@t3chfest.es>\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.14.3\n"
|
||||
"X-Generator: Weblate 5.15.1\n"
|
||||
|
||||
#: pretix/_base_settings.py:87
|
||||
msgid "English"
|
||||
@@ -3870,7 +3870,7 @@ msgstr ""
|
||||
|
||||
#: pretix/base/invoicing/peppol.py:164
|
||||
msgid "The Peppol participant ID is not registered on the Peppol network."
|
||||
msgstr ""
|
||||
msgstr "El ID de participante de Peppol no está registrado en la red Peppol."
|
||||
|
||||
#: pretix/base/invoicing/peppol.py:184
|
||||
msgid "Peppol participant ID"
|
||||
@@ -8445,6 +8445,8 @@ msgid ""
|
||||
"Some products can no longer be purchased and have been removed from your "
|
||||
"cart for the following reason: %s"
|
||||
msgstr ""
|
||||
"Algunos productos ya no se pueden comprar y se han eliminado de su carrito "
|
||||
"por el siguiente motivo: %s"
|
||||
|
||||
#: pretix/base/services/cart.py:117
|
||||
msgid ""
|
||||
@@ -9626,21 +9628,15 @@ msgid "Uncategorized"
|
||||
msgstr "Sin categorías"
|
||||
|
||||
#: pretix/base/services/tax.py:43
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Your VAT ID could not be checked, as the VAT checking service of your "
|
||||
#| "country is currently not available. We will therefore need to charge VAT "
|
||||
#| "on your invoice. You can get the tax amount back via the VAT "
|
||||
#| "reimbursement process."
|
||||
msgid ""
|
||||
"Your VAT ID could not be checked, as the VAT checking service of your "
|
||||
"country is currently not available. We will therefore need to charge you the "
|
||||
"same tax rate as if you did not enter a VAT ID."
|
||||
msgstr ""
|
||||
"Tu Identificador IVA no puede ser chequeado, porque el verificador para tu "
|
||||
"país no está disponible actualmente. Nosotros deberemos de cargar el IVA en "
|
||||
"tu compra. Puedes obtener el total del impuesto mediante el proceso de "
|
||||
"reembolso de IVA."
|
||||
"No se ha podido verificar su número de identificación fiscal, ya que el "
|
||||
"servicio de verificación del IVA de su país no está disponible en este "
|
||||
"momento. Por lo tanto, tendremos que cobrarle el mismo tipo impositivo que "
|
||||
"si no hubiera introducido ningún número de identificación fiscal."
|
||||
|
||||
#: pretix/base/services/tax.py:47 pretix/base/services/tax.py:366
|
||||
#: pretix/base/services/tax.py:393
|
||||
@@ -10081,24 +10077,18 @@ msgid "Ask for VAT ID"
|
||||
msgstr "Solicitar ID de IVA"
|
||||
|
||||
#: pretix/base/settings.py:632
|
||||
#, 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 ""
|
||||
"Solo funciona si se solicita una dirección de factura. El ID de IVA nunca es "
|
||||
"obligatorio y solo se solicita a clientes comerciales en los siguientes "
|
||||
"países: {countries}"
|
||||
"Solo funciona si se solicita una dirección de facturación. El número de "
|
||||
"identificación fiscal solo se solicita a los clientes empresariales de los "
|
||||
"siguientes países: {countries}."
|
||||
|
||||
#: pretix/base/settings.py:651
|
||||
#, fuzzy
|
||||
#| msgid "Require name"
|
||||
msgid "Require VAT ID in"
|
||||
msgstr "Requerir nombre"
|
||||
msgstr "Solicitar número de identificación fiscal en"
|
||||
|
||||
#: pretix/base/settings.py:657
|
||||
msgid ""
|
||||
@@ -10106,6 +10096,10 @@ msgid ""
|
||||
"ID in all countries. VAT ID will be required for all business addresses in "
|
||||
"the selected countries."
|
||||
msgstr ""
|
||||
"El número de identificación fiscal es opcional por defecto, ya que no todas "
|
||||
"las empresas tienen asignado un número de identificación fiscal en todos los "
|
||||
"países. El número de identificación fiscal será obligatorio para todas las "
|
||||
"direcciones comerciales en los países seleccionados."
|
||||
|
||||
#: pretix/base/settings.py:672
|
||||
msgid "Invoice address explanation"
|
||||
@@ -13838,11 +13832,9 @@ msgstr ""
|
||||
"mismo origen\"."
|
||||
|
||||
#: pretix/base/views/js_helpers.py:41
|
||||
#, fuzzy
|
||||
#| msgid "ID"
|
||||
msgctxt "tax_id_swiss"
|
||||
msgid "UID"
|
||||
msgstr "ID"
|
||||
msgstr "UID"
|
||||
|
||||
#. Translators: Only translate to French (IDE) and Italien (IDI), otherwise keep the same
|
||||
#. Awareness around VAT IDs differes by EU country. For example, in Germany the VAT ID is assigned
|
||||
@@ -13852,35 +13844,27 @@ msgstr "ID"
|
||||
#. number (Partita IVA) and also used on domestic transactions. So someone who never purchased something international
|
||||
#. for their company, might still know the value, if we call it the right way and not just "VAT ID".
|
||||
#: pretix/base/views/js_helpers.py:49
|
||||
#, fuzzy
|
||||
#| msgid "VAT ID"
|
||||
msgctxt "tax_id_italy"
|
||||
msgid "VAT ID / P.IVA"
|
||||
msgstr "Identificador IVA"
|
||||
msgstr "Número de identificación fiscal / P.IVA"
|
||||
|
||||
#. Translators: Translate to only "P.IVA" in Italian, keep second part as-is in other languages
|
||||
#: pretix/base/views/js_helpers.py:50
|
||||
#, fuzzy
|
||||
#| msgid "VAT ID"
|
||||
msgctxt "tax_id_greece"
|
||||
msgid "VAT ID / TIN"
|
||||
msgstr "Identificador IVA"
|
||||
msgstr "Número de identificación fiscal / TIN"
|
||||
|
||||
#. Translators: Translate to only "ΑΦΜ" in Greek
|
||||
#: pretix/base/views/js_helpers.py:51
|
||||
#, fuzzy
|
||||
#| msgid "VAT ID"
|
||||
msgctxt "tax_id_spain"
|
||||
msgid "VAT ID / NIF"
|
||||
msgstr "Identificador IVA"
|
||||
msgstr "Número de identificación fiscal / NIF"
|
||||
|
||||
#. Translators: Translate to only "NIF" in Spanish
|
||||
#: pretix/base/views/js_helpers.py:52
|
||||
#, fuzzy
|
||||
#| msgid "VAT ID"
|
||||
msgctxt "tax_id_portugal"
|
||||
msgid "VAT ID / NIF"
|
||||
msgstr "Identificador IVA"
|
||||
msgstr "NIF"
|
||||
|
||||
#: pretix/base/views/tasks.py:185
|
||||
msgid "An unexpected error has occurred, please try again later."
|
||||
@@ -14436,6 +14420,9 @@ msgid ""
|
||||
"Formatting is not supported, as some accounting departments process mail "
|
||||
"automatically and do not handle formatted emails properly."
|
||||
msgstr ""
|
||||
"No se admite el formato, ya que algunos departamentos de contabilidad "
|
||||
"procesan el correo automáticamente y no gestionan correctamente los correos "
|
||||
"electrónicos con formato."
|
||||
|
||||
#: pretix/control/forms/event.py:1356
|
||||
msgid ""
|
||||
@@ -14889,7 +14876,7 @@ msgstr "Pagado"
|
||||
#: pretix/control/forms/filter.py:1304
|
||||
msgctxt "subevent"
|
||||
msgid "Date doesn't start in selected date range."
|
||||
msgstr ""
|
||||
msgstr "La fecha no comienza en el intervalo de fechas seleccionado."
|
||||
|
||||
#: pretix/control/forms/filter.py:1360 pretix/control/forms/filter.py:1827
|
||||
msgid "Shop live and presale running"
|
||||
@@ -28812,6 +28799,9 @@ msgid ""
|
||||
"automatically. We recommend that you rename these in your source file to "
|
||||
"avoid problems during import."
|
||||
msgstr ""
|
||||
"Varias columnas del archivo CSV tienen el mismo nombre y se han renombrado "
|
||||
"automáticamente. Le recomendamos que cambie el nombre de estas columnas en "
|
||||
"su archivo de origen para evitar problemas durante la importación."
|
||||
|
||||
#: pretix/control/views/modelimport.py:188
|
||||
msgid "The import was successful."
|
||||
@@ -30483,7 +30473,7 @@ msgstr ""
|
||||
|
||||
#: pretix/plugins/banktransfer/camtimport.py:33
|
||||
msgid "Empty file or unknown format."
|
||||
msgstr ""
|
||||
msgstr "Archivo vacío o formato desconocido."
|
||||
|
||||
#: pretix/plugins/banktransfer/payment.py:69
|
||||
msgid ""
|
||||
@@ -33053,16 +33043,17 @@ msgid "Przelewy24"
|
||||
msgstr "Przelewy24"
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:417 pretix/plugins/stripe/payment.py:1836
|
||||
#, fuzzy
|
||||
#| msgid "Payment by bank transfer"
|
||||
msgid "Pay by bank"
|
||||
msgstr "Pago por transferencia bancaria"
|
||||
msgstr "Pagar por transferencia bancaria"
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:422
|
||||
msgid ""
|
||||
"Currently only available for charges in GBP and customers with UK bank "
|
||||
"accounts, and in private preview for France and Germany."
|
||||
msgstr ""
|
||||
"Actualmente solo disponible para cargos en libra esterlina y clientes con "
|
||||
"cuentas bancarias en el Reino Unido, y en vista previa privada para Francia "
|
||||
"y Alemania."
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:429 pretix/plugins/stripe/payment.py:1789
|
||||
msgid "WeChat Pay"
|
||||
@@ -33374,16 +33365,17 @@ msgstr ""
|
||||
"favor, tenga a mano su información de acceso."
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:1835
|
||||
#, fuzzy
|
||||
#| msgid "PayPal via Stripe"
|
||||
msgid "Pay by bank via Stripe"
|
||||
msgstr "PayPal via Stripe"
|
||||
msgstr "Pagar por transferencia bancaria a través de Stripe"
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:1841
|
||||
msgid ""
|
||||
"Pay by bank allows you to authorize a secure Open Banking payment from your "
|
||||
"banking app. Currently available only with a UK bank account."
|
||||
msgstr ""
|
||||
"El pago por banco te permite autorizar un pago seguro de banca abierta desde "
|
||||
"tu aplicación bancaria. Actualmente solo disponible con una cuenta bancaria "
|
||||
"del Reino Unido."
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:1861
|
||||
msgid "PayPal via Stripe"
|
||||
@@ -33402,22 +33394,16 @@ msgstr ""
|
||||
"suecas Swish y BankID. Por favor, ten tu app preparada."
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:1893
|
||||
#, fuzzy
|
||||
#| msgid "giropay via Stripe"
|
||||
msgid "PromptPay via Stripe"
|
||||
msgstr "giropay via Stripe"
|
||||
msgstr "PromptPay a través de Stripe"
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:1898
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "This payment method is available to MobilePay app users in Denmark and "
|
||||
#| "Finland. Please have your app ready."
|
||||
msgid ""
|
||||
"This payment method is available to PromptPay users in Thailand. Please have "
|
||||
"your app ready."
|
||||
msgstr ""
|
||||
"Este modo de pago está disponible para los usuarios de la aplicación "
|
||||
"MobilePay en Dinamarca y Finlandia. Por favor, tenga su app preparada."
|
||||
"Este método de pago está disponible para los usuarios de PromptPay en "
|
||||
"Tailandia. Por favor, tenga su aplicación lista."
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:1917
|
||||
msgid "TWINT via Stripe"
|
||||
@@ -33728,22 +33714,16 @@ msgid "Confirm payment: %(code)s"
|
||||
msgstr "Confirmar pago: %(code)s"
|
||||
|
||||
#: pretix/plugins/stripe/templates/pretixplugins/stripe/sca.html:32
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Please scan the barcode below to complete your WeChat payment. Once you "
|
||||
#| "have completed your payment, you can refresh this page."
|
||||
msgid ""
|
||||
"Please scan the QR code below to complete your PromptPay payment. Once you "
|
||||
"have completed your payment, you can refresh this page."
|
||||
msgstr ""
|
||||
"Escanee el código de barras a continuación para completar su pago de WeChat. "
|
||||
"Una vez que haya completado su pago, puede actualizar esta página."
|
||||
"Escanee el código QR que aparece a continuación para completar su pago con "
|
||||
"PromptPay. Una vez que haya completado el pago, puede actualizar esta página."
|
||||
|
||||
#: pretix/plugins/stripe/templates/pretixplugins/stripe/sca.html:37
|
||||
#, fuzzy
|
||||
#| msgid "Create QR code"
|
||||
msgid "PromptPay QR code"
|
||||
msgstr "Crear código QR"
|
||||
msgstr "Código QR de PromptPay"
|
||||
|
||||
#: pretix/plugins/stripe/templates/pretixplugins/stripe/sca_return.html:20
|
||||
msgid "Confirming your payment…"
|
||||
@@ -34790,14 +34770,11 @@ msgstr[0] "Necesitas elegir exactamente una opción para esta categoría."
|
||||
msgstr[1] "Necesitas elegir %(min_count)s opciones para esta categoría."
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_addon_choice.html:26
|
||||
#, fuzzy, python-format
|
||||
#| msgid "You can choose at most one option from this category."
|
||||
#| msgid_plural ""
|
||||
#| "You can choose up to %(max_count)s options from this category."
|
||||
#, python-format
|
||||
msgid "You can choose one option from this category."
|
||||
msgid_plural "You can choose up to %(max_count)s options from this category."
|
||||
msgstr[0] "Puedes elegir como máximo una opción en esta categoría."
|
||||
msgstr[1] "Puedes elegir como máximo %(max_count)s opciones en esta categoría."
|
||||
msgstr[0] "Puede elegir una opción de esta categoría."
|
||||
msgstr[1] "Puede elegir hasta %(max_count)s opciones de esta categoría."
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_addon_choice.html:34
|
||||
#, python-format
|
||||
@@ -35611,7 +35588,8 @@ msgstr "El período de preventa para este evento ha terminado."
|
||||
#: pretix/presale/views/widget.py:807
|
||||
#, python-format
|
||||
msgid "The booking period for this event will start on %(date)s at %(time)s."
|
||||
msgstr "La preventa para este evento comenzará en %(date)s a %(time)s."
|
||||
msgstr ""
|
||||
"El periodo de reserva para este evento comenzará el %(date)s a las %(time)s."
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/index.html:185
|
||||
#: pretix/presale/templates/pretixpresale/event/seatingplan.html:23
|
||||
@@ -36874,17 +36852,19 @@ msgstr ""
|
||||
|
||||
#: pretix/presale/views/cart.py:520
|
||||
msgid "Your cart has been updated."
|
||||
msgstr "Su carrito ha sido actualizada."
|
||||
msgstr "Su carrito ha sido actualizado."
|
||||
|
||||
#: pretix/presale/views/cart.py:523 pretix/presale/views/cart.py:549
|
||||
msgid "Your cart is now empty."
|
||||
msgstr "Su carrito ha sido vaciada."
|
||||
msgstr "Su carrito está vacio."
|
||||
|
||||
#: pretix/presale/views/cart.py:570
|
||||
msgid ""
|
||||
"Your cart timeout was extended. Please note that some of the prices in your "
|
||||
"cart changed."
|
||||
msgstr ""
|
||||
"Se ha ampliado el tiempo de espera de su carrito. Tenga en cuenta que "
|
||||
"algunos de los precios de su carrito han cambiado."
|
||||
|
||||
#: pretix/presale/views/cart.py:573
|
||||
msgid "Your cart timeout was extended."
|
||||
|
||||
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-01-05 12:13+0000\n"
|
||||
"PO-Revision-Date: 2025-10-22 16:00+0000\n"
|
||||
"PO-Revision-Date: 2026-01-14 00:00+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.13.3\n"
|
||||
"X-Generator: Weblate 5.15.1\n"
|
||||
|
||||
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:56
|
||||
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:62
|
||||
@@ -738,11 +738,8 @@ msgstr "Su carrito está a punto de caducar."
|
||||
#: 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] ""
|
||||
"Los elementos en su carrito de compras se han reservado durante un minuto."
|
||||
msgstr[1] ""
|
||||
"Los elementos en su carrito de compras se han reservado durante {num} "
|
||||
"minutos."
|
||||
msgstr[0] "Los artículos de la cesta están reservados durante un minuto."
|
||||
msgstr[1] "Los artículos de la cesta están reservados durante {num} minutos."
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/cart.js:83
|
||||
msgid "Your cart has expired."
|
||||
@@ -766,11 +763,11 @@ msgstr "Renovar reserva"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:194
|
||||
msgid "The organizer keeps %(currency)s %(amount)s"
|
||||
msgstr "El organizador se queda %(currency)s %(price)s"
|
||||
msgstr "El organizador retiene %(currency)s %(amount)s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:202
|
||||
msgid "You get %(currency)s %(amount)s back"
|
||||
msgstr "Obtienes %(currency)s %(price)s de vuelta"
|
||||
msgstr "Se le devolverá %(moneda)s %(cantidad)s"
|
||||
|
||||
#: pretix/static/pretixpresale/js/ui/main.js:218
|
||||
msgid "Please enter the amount the organizer can keep."
|
||||
|
||||
@@ -4,7 +4,7 @@ msgstr ""
|
||||
"Project-Id-Version: 1\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-01-05 12:12+0000\n"
|
||||
"PO-Revision-Date: 2026-01-06 14:46+0000\n"
|
||||
"PO-Revision-Date: 2026-01-06 23:00+0000\n"
|
||||
"Last-Translator: CVZ-es <damien.bremont@casadevelazquez.org>\n"
|
||||
"Language-Team: French <https://translate.pretix.eu/projects/pretix/pretix/"
|
||||
"fr/>\n"
|
||||
@@ -13974,25 +13974,25 @@ msgstr "UID"
|
||||
#: pretix/base/views/js_helpers.py:49
|
||||
msgctxt "tax_id_italy"
|
||||
msgid "VAT ID / P.IVA"
|
||||
msgstr "Numéro d'identification TVA"
|
||||
msgstr "Numéro de TVA intracommunautaire"
|
||||
|
||||
#. Translators: Translate to only "P.IVA" in Italian, keep second part as-is in other languages
|
||||
#: pretix/base/views/js_helpers.py:50
|
||||
msgctxt "tax_id_greece"
|
||||
msgid "VAT ID / TIN"
|
||||
msgstr "Numéro d'identification TVA / TIN"
|
||||
msgstr "Numéro de TVA intracommunautaire / TIN"
|
||||
|
||||
#. Translators: Translate to only "ΑΦΜ" in Greek
|
||||
#: pretix/base/views/js_helpers.py:51
|
||||
msgctxt "tax_id_spain"
|
||||
msgid "VAT ID / NIF"
|
||||
msgstr "Numéro d'identification TVA"
|
||||
msgstr "Numéro de TVA intracommunautaire"
|
||||
|
||||
#. Translators: Translate to only "NIF" in Spanish
|
||||
#: pretix/base/views/js_helpers.py:52
|
||||
msgctxt "tax_id_portugal"
|
||||
msgid "VAT ID / NIF"
|
||||
msgstr "Numéro d'identification TVA / NIF"
|
||||
msgstr "Numéro de TVA intracommunautaire / NIF"
|
||||
|
||||
#: pretix/base/views/tasks.py:185
|
||||
msgid "An unexpected error has occurred, please try again later."
|
||||
@@ -29015,6 +29015,9 @@ msgid ""
|
||||
"automatically. We recommend that you rename these in your source file to "
|
||||
"avoid problems during import."
|
||||
msgstr ""
|
||||
"Plusieurs colonnes du fichier CSV portent le même nom et ont été renommées "
|
||||
"automatiquement. Nous vous recommandons de les renommer dans votre fichier "
|
||||
"source afin d'éviter tout problème lors de l'importation."
|
||||
|
||||
#: pretix/control/views/modelimport.py:188
|
||||
msgid "The import was successful."
|
||||
@@ -30705,7 +30708,7 @@ msgstr ""
|
||||
|
||||
#: pretix/plugins/banktransfer/camtimport.py:33
|
||||
msgid "Empty file or unknown format."
|
||||
msgstr ""
|
||||
msgstr "Fichier vide ou format inconnu."
|
||||
|
||||
#: pretix/plugins/banktransfer/payment.py:69
|
||||
msgid ""
|
||||
@@ -33300,16 +33303,17 @@ msgid "Przelewy24"
|
||||
msgstr "Przelewy24"
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:417 pretix/plugins/stripe/payment.py:1836
|
||||
#, fuzzy
|
||||
#| msgid "Payment by bank transfer"
|
||||
msgid "Pay by bank"
|
||||
msgstr "Paiement par virement bancaire"
|
||||
msgstr "Payer par virement bancaire"
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:422
|
||||
msgid ""
|
||||
"Currently only available for charges in GBP and customers with UK bank "
|
||||
"accounts, and in private preview for France and Germany."
|
||||
msgstr ""
|
||||
"Actuellement disponible uniquement pour les frais en livre sterling et les "
|
||||
"clients disposant d'un compte bancaire au Royaume-Uni, et pour les clients "
|
||||
"en test restreint pour la France et l'Allemagne."
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:429 pretix/plugins/stripe/payment.py:1789
|
||||
msgid "WeChat Pay"
|
||||
@@ -33626,16 +33630,17 @@ msgstr ""
|
||||
"connexion à porter de main."
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:1835
|
||||
#, fuzzy
|
||||
#| msgid "PayPal via Stripe"
|
||||
msgid "Pay by bank via Stripe"
|
||||
msgstr "PayPal via Stripe"
|
||||
msgstr "Payer par virement bancaire via Stripe"
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:1841
|
||||
msgid ""
|
||||
"Pay by bank allows you to authorize a secure Open Banking payment from your "
|
||||
"banking app. Currently available only with a UK bank account."
|
||||
msgstr ""
|
||||
"Le paiement par virement bancaire vous permet d'autoriser un paiement "
|
||||
"sécurisé via Open Banking depuis votre application bancaire. Actuellement "
|
||||
"disponible uniquement avec un compte bancaire britannique."
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:1861
|
||||
msgid "PayPal via Stripe"
|
||||
@@ -33654,22 +33659,16 @@ msgstr ""
|
||||
"suédoises Swish et BankID. Veuillez préparer votre application."
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:1893
|
||||
#, fuzzy
|
||||
#| msgid "giropay via Stripe"
|
||||
msgid "PromptPay via Stripe"
|
||||
msgstr "giropay via Stripe"
|
||||
msgstr "PromptPay via Stripe"
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:1898
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "This payment method is available to MobilePay app users in Denmark and "
|
||||
#| "Finland. Please have your app ready."
|
||||
msgid ""
|
||||
"This payment method is available to PromptPay users in Thailand. Please have "
|
||||
"your app ready."
|
||||
msgstr ""
|
||||
"Ce mode de paiement est disponible pour les utilisateurs de l'application "
|
||||
"MobilePay au Danemark et en Finlande. Veuillez préparer votre application."
|
||||
"Ce mode de paiement est disponible pour les utilisateurs de PromptPay en "
|
||||
"Thaïlande. Veuillez préparer votre application."
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:1917
|
||||
msgid "TWINT via Stripe"
|
||||
@@ -33984,23 +33983,17 @@ msgid "Confirm payment: %(code)s"
|
||||
msgstr "Confirmer le paiement : %(code)s"
|
||||
|
||||
#: pretix/plugins/stripe/templates/pretixplugins/stripe/sca.html:32
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Please scan the barcode below to complete your WeChat payment. Once you "
|
||||
#| "have completed your payment, you can refresh this page."
|
||||
msgid ""
|
||||
"Please scan the QR code below to complete your PromptPay payment. Once you "
|
||||
"have completed your payment, you can refresh this page."
|
||||
msgstr ""
|
||||
"Veuillez scanner le code-barres ci-dessous pour effectuer votre paiement "
|
||||
"WeChat. Une fois que vous avez effectué votre paiement, vous pouvez "
|
||||
"actualiser cette page."
|
||||
"Veuillez scanner le code QR ci-dessous pour effectuer votre paiement "
|
||||
"PromptPay. Une fois votre paiement effectué, vous pouvez actualiser cette "
|
||||
"page."
|
||||
|
||||
#: pretix/plugins/stripe/templates/pretixplugins/stripe/sca.html:37
|
||||
#, fuzzy
|
||||
#| msgid "Create QR code"
|
||||
msgid "PromptPay QR code"
|
||||
msgstr "Créer un code QR"
|
||||
msgstr "Code QR PromptPay"
|
||||
|
||||
#: pretix/plugins/stripe/templates/pretixplugins/stripe/sca_return.html:20
|
||||
msgid "Confirming your payment…"
|
||||
@@ -35057,14 +35050,11 @@ msgstr[0] "Vous devez choisir exactement une option de cette catégorie."
|
||||
msgstr[1] "Vous devez choisir les options %(min_count)s de cette catégorie."
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_addon_choice.html:26
|
||||
#, fuzzy, python-format
|
||||
#| msgid "You can choose at most one option from this category."
|
||||
#| msgid_plural ""
|
||||
#| "You can choose up to %(max_count)s options from this category."
|
||||
#, python-format
|
||||
msgid "You can choose one option from this category."
|
||||
msgid_plural "You can choose up to %(max_count)s options from this category."
|
||||
msgstr[0] "Vous pouvez choisir au plus une option de cette catégorie."
|
||||
msgstr[1] "Vous pouvez choisir jusqu' à %(max_count)s dans cette catégorie."
|
||||
msgstr[0] "Vous pouvez choisir une option dans cette catégorie."
|
||||
msgstr[1] "Vous pouvez choisir jusqu'à %(max_count)s options dans cette catégorie."
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_addon_choice.html:34
|
||||
#, python-format
|
||||
@@ -37195,6 +37185,8 @@ msgid ""
|
||||
"Your cart timeout was extended. Please note that some of the prices in your "
|
||||
"cart changed."
|
||||
msgstr ""
|
||||
"Le délai d'expiration de votre panier a été prolongé. Veuillez noter que "
|
||||
"certains prix dans votre panier ont changé."
|
||||
|
||||
#: pretix/presale/views/cart.py:573
|
||||
msgid "Your cart timeout was extended."
|
||||
|
||||
@@ -8,8 +8,8 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-01-05 12:12+0000\n"
|
||||
"PO-Revision-Date: 2025-12-15 20:00+0000\n"
|
||||
"Last-Translator: sandra r <sandrarial@gestiontickets.online>\n"
|
||||
"PO-Revision-Date: 2026-01-14 00:00+0000\n"
|
||||
"Last-Translator: Mario Montes <mario@t3chfest.es>\n"
|
||||
"Language-Team: Galician <https://translate.pretix.eu/projects/pretix/pretix/"
|
||||
"gl/>\n"
|
||||
"Language: gl\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.1\n"
|
||||
|
||||
#: pretix/_base_settings.py:87
|
||||
msgid "English"
|
||||
@@ -1149,7 +1149,7 @@ msgstr "Pregunta: {name}"
|
||||
#: pretix/base/settings.py:3775 pretix/base/settings.py:3828
|
||||
#: pretix/base/settings.py:3849 pretix/base/settings.py:3871
|
||||
msgid "Given name"
|
||||
msgstr "Nombre"
|
||||
msgstr "Nome"
|
||||
|
||||
#: pretix/base/datasync/sourcefields.py:628
|
||||
#: pretix/base/datasync/sourcefields.py:638 pretix/base/settings.py:3670
|
||||
@@ -18192,9 +18192,9 @@ msgstr ""
|
||||
"\"{new_email}\"."
|
||||
|
||||
#: pretix/control/logdisplay.py:673
|
||||
#, fuzzy, python-brace-format
|
||||
#, python-brace-format
|
||||
msgid "Your email address {email} has been confirmed."
|
||||
msgstr "Su carrito ha sido actualizado."
|
||||
msgstr "Tu email {email} ha sido confirmado."
|
||||
|
||||
#: pretix/control/logdisplay.py:685
|
||||
#, fuzzy, python-brace-format
|
||||
@@ -24293,7 +24293,7 @@ msgstr "Sí, aprobar la orden"
|
||||
#: pretix/presale/templates/pretixpresale/event/order.html:483
|
||||
#: pretix/presale/templates/pretixpresale/event/order_cancel.html:7
|
||||
msgid "Cancel order"
|
||||
msgstr "Cancelar a orde"
|
||||
msgstr "Cancelar o pedido"
|
||||
|
||||
#: pretix/control/templates/pretixcontrol/order/cancel.html:12
|
||||
#: pretix/control/templates/pretixcontrol/order/deny.html:11
|
||||
@@ -35952,10 +35952,9 @@ msgstr ""
|
||||
|
||||
#: pretix/presale/forms/renderers.py:66
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_voucher_form.html:14
|
||||
#, fuzzy
|
||||
msgctxt "form"
|
||||
msgid "required"
|
||||
msgstr "expirado"
|
||||
msgstr "obrigatorio"
|
||||
|
||||
#: pretix/presale/ical.py:87 pretix/presale/ical.py:146
|
||||
#: pretix/presale/ical.py:182
|
||||
@@ -37539,14 +37538,13 @@ msgid "A payment of %(total)s is still pending for this order."
|
||||
msgstr "Un pago de %(total)s aínda está pendente para esta orde."
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/order.html:97
|
||||
#, fuzzy, python-format
|
||||
#, python-format
|
||||
msgid "Please complete your payment before %(date)s"
|
||||
msgstr "Por favor complete su pago antes de %(date)s"
|
||||
msgstr "Por favor complete o seu pago antes de %(date)s"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/order.html:108
|
||||
#, fuzzy
|
||||
msgid "Re-try payment or choose another payment method"
|
||||
msgstr "Vuelva a intentar el pago o elija otro método de pago"
|
||||
msgstr "Volva tentar o pago ou escolla outro método de pago"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/order.html:126
|
||||
#, fuzzy
|
||||
|
||||
@@ -8,8 +8,8 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-01-05 12:12+0000\n"
|
||||
"PO-Revision-Date: 2026-01-05 10:00+0000\n"
|
||||
"Last-Translator: Yasunobu YesNo Kawaguchi <kawaguti@gmail.com>\n"
|
||||
"PO-Revision-Date: 2026-01-12 17:00+0000\n"
|
||||
"Last-Translator: Hijiri Umemoto <hijiri@umemoto.org>\n"
|
||||
"Language-Team: Japanese <https://translate.pretix.eu/projects/pretix/pretix/"
|
||||
"ja/>\n"
|
||||
"Language: ja\n"
|
||||
@@ -3831,7 +3831,7 @@ msgstr ""
|
||||
|
||||
#: pretix/base/invoicing/peppol.py:164
|
||||
msgid "The Peppol participant ID is not registered on the Peppol network."
|
||||
msgstr ""
|
||||
msgstr "Peppol参加者IDはPeppolネットワークに登録されていません。"
|
||||
|
||||
#: pretix/base/invoicing/peppol.py:184
|
||||
msgid "Peppol participant ID"
|
||||
@@ -8281,7 +8281,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 ""
|
||||
@@ -9400,20 +9400,14 @@ msgid "Uncategorized"
|
||||
msgstr "未分類"
|
||||
|
||||
#: pretix/base/services/tax.py:43
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Your VAT ID could not be checked, as the VAT checking service of your "
|
||||
#| "country is currently not available. We will therefore need to charge VAT "
|
||||
#| "on your invoice. You can get the tax amount back via the VAT "
|
||||
#| "reimbursement process."
|
||||
msgid ""
|
||||
"Your VAT ID could not be checked, as the VAT checking service of your "
|
||||
"country is currently not available. We will therefore need to charge you the "
|
||||
"same tax rate as if you did not enter a VAT ID."
|
||||
msgstr ""
|
||||
"お客様のVAT IDは確認できませんでした。お客様の国のVAT確認サービスが現在利用で"
|
||||
"きないため、請求書にVATを請求する必要があります。VAT払い戻し手続きを通じて税"
|
||||
"金を返金することができます。"
|
||||
"あなたの国のVATチェックサービスが現在利用できないため、VAT IDを確認できません"
|
||||
"でした。したがって、VAT IDを入力しなかった場合と同じ税率を請求する必要があり"
|
||||
"ます。"
|
||||
|
||||
#: pretix/base/services/tax.py:47 pretix/base/services/tax.py:366
|
||||
#: pretix/base/services/tax.py:393
|
||||
@@ -9828,23 +9822,17 @@ msgid "Ask for VAT ID"
|
||||
msgstr "VAT IDを尋ねる"
|
||||
|
||||
#: pretix/base/settings.py:632
|
||||
#, 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 ""
|
||||
"請求先の住所が要求された場合のみ機能します。消費税登録番号やVAT IDは必要な"
|
||||
"く、以下の国の法人顧客からのみ要求されます:{countries}"
|
||||
"請求書の住所が要求された場合のみ有効です。VAT ID は、{countries} の国の法人の"
|
||||
"お客様にのみ要求されます。"
|
||||
|
||||
#: pretix/base/settings.py:651
|
||||
#, fuzzy
|
||||
#| msgid "Require name"
|
||||
msgid "Require VAT ID in"
|
||||
msgstr "名前を要求"
|
||||
msgstr "VAT IDを要求"
|
||||
|
||||
#: pretix/base/settings.py:657
|
||||
msgid ""
|
||||
@@ -9852,6 +9840,9 @@ msgid ""
|
||||
"ID in all countries. VAT ID will be required for all business addresses in "
|
||||
"the selected countries."
|
||||
msgstr ""
|
||||
"VAT ID はデフォルトでオプションです。これは、すべての企業に VAT ID が割り当て"
|
||||
"られているわけではないためです。選択した国のすべてのビジネスアドレスには、"
|
||||
"VAT IDが必要です。"
|
||||
|
||||
#: pretix/base/settings.py:672
|
||||
msgid "Invoice address explanation"
|
||||
@@ -13442,11 +13433,9 @@ msgstr ""
|
||||
"リクエストのために再度有効にしてください。"
|
||||
|
||||
#: pretix/base/views/js_helpers.py:41
|
||||
#, fuzzy
|
||||
#| msgid "ID"
|
||||
msgctxt "tax_id_swiss"
|
||||
msgid "UID"
|
||||
msgstr "ID"
|
||||
msgstr "UID"
|
||||
|
||||
#. Translators: Only translate to French (IDE) and Italien (IDI), otherwise keep the same
|
||||
#. Awareness around VAT IDs differes by EU country. For example, in Germany the VAT ID is assigned
|
||||
@@ -13456,35 +13445,27 @@ msgstr "ID"
|
||||
#. number (Partita IVA) and also used on domestic transactions. So someone who never purchased something international
|
||||
#. for their company, might still know the value, if we call it the right way and not just "VAT ID".
|
||||
#: pretix/base/views/js_helpers.py:49
|
||||
#, fuzzy
|
||||
#| msgid "VAT ID"
|
||||
msgctxt "tax_id_italy"
|
||||
msgid "VAT ID / P.IVA"
|
||||
msgstr "消費税登録番号又はVAT ID"
|
||||
msgstr "VAT ID / P.IVA"
|
||||
|
||||
#. Translators: Translate to only "P.IVA" in Italian, keep second part as-is in other languages
|
||||
#: pretix/base/views/js_helpers.py:50
|
||||
#, fuzzy
|
||||
#| msgid "VAT ID"
|
||||
msgctxt "tax_id_greece"
|
||||
msgid "VAT ID / TIN"
|
||||
msgstr "消費税登録番号又はVAT ID"
|
||||
msgstr "VAT ID / TIN"
|
||||
|
||||
#. Translators: Translate to only "ΑΦΜ" in Greek
|
||||
#: pretix/base/views/js_helpers.py:51
|
||||
#, fuzzy
|
||||
#| msgid "VAT ID"
|
||||
msgctxt "tax_id_spain"
|
||||
msgid "VAT ID / NIF"
|
||||
msgstr "消費税登録番号又はVAT ID"
|
||||
msgstr "VAT ID / NIF"
|
||||
|
||||
#. Translators: Translate to only "NIF" in Spanish
|
||||
#: pretix/base/views/js_helpers.py:52
|
||||
#, fuzzy
|
||||
#| msgid "VAT ID"
|
||||
msgctxt "tax_id_portugal"
|
||||
msgid "VAT ID / NIF"
|
||||
msgstr "消費税登録番号又はVAT ID"
|
||||
msgstr "VAT ID / NIF"
|
||||
|
||||
#: pretix/base/views/tasks.py:185
|
||||
msgid "An unexpected error has occurred, please try again later."
|
||||
@@ -14021,6 +14002,8 @@ msgid ""
|
||||
"Formatting is not supported, as some accounting departments process mail "
|
||||
"automatically and do not handle formatted emails properly."
|
||||
msgstr ""
|
||||
"一部の経理部門はメールを自動的に処理し、フォーマットされたメールを適切に処理"
|
||||
"しないため、フォーマットはサポートされていません。"
|
||||
|
||||
#: pretix/control/forms/event.py:1356
|
||||
msgid ""
|
||||
@@ -14469,7 +14452,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"
|
||||
@@ -28007,6 +27990,9 @@ msgid ""
|
||||
"automatically. We recommend that you rename these in your source file to "
|
||||
"avoid problems during import."
|
||||
msgstr ""
|
||||
"CSVファイルの複数の列は同じ名前で、自動的に名前が変更されました。インポート中"
|
||||
"に問題が発生しないように、ソースファイルでこれらの名前を変更することをお勧め"
|
||||
"します。"
|
||||
|
||||
#: pretix/control/views/modelimport.py:188
|
||||
msgid "The import was successful."
|
||||
@@ -29637,7 +29623,7 @@ msgstr ""
|
||||
|
||||
#: pretix/plugins/banktransfer/camtimport.py:33
|
||||
msgid "Empty file or unknown format."
|
||||
msgstr ""
|
||||
msgstr "空のファイルまたは不明な形式。"
|
||||
|
||||
#: pretix/plugins/banktransfer/payment.py:69
|
||||
msgid ""
|
||||
@@ -32132,16 +32118,16 @@ msgid "Przelewy24"
|
||||
msgstr "Przelewy24"
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:417 pretix/plugins/stripe/payment.py:1836
|
||||
#, fuzzy
|
||||
#| msgid "Payment by bank transfer"
|
||||
msgid "Pay by bank"
|
||||
msgstr "銀行振込による支払い"
|
||||
msgstr "Pay by bank"
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:422
|
||||
msgid ""
|
||||
"Currently only available for charges in GBP and customers with UK bank "
|
||||
"accounts, and in private preview for France and Germany."
|
||||
msgstr ""
|
||||
"現在、英国ポンドでの請求と英国の銀行口座を持つ顧客、およびフランスとドイツの"
|
||||
"プライベートプレビューでのみ利用できます。"
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:429 pretix/plugins/stripe/payment.py:1789
|
||||
msgid "WeChat Pay"
|
||||
@@ -32446,16 +32432,16 @@ msgstr ""
|
||||
"いておいてください。"
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:1835
|
||||
#, fuzzy
|
||||
#| msgid "PayPal via Stripe"
|
||||
msgid "Pay by bank via Stripe"
|
||||
msgstr "Stripe経由でPayPal"
|
||||
msgstr "Stripe経由でPay by bank"
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:1841
|
||||
msgid ""
|
||||
"Pay by bank allows you to authorize a secure Open Banking payment from your "
|
||||
"banking app. Currently available only with a UK bank account."
|
||||
msgstr ""
|
||||
"Pay by bankを使用すると、銀行アプリから安全なオープンバンキングの支払いを承認"
|
||||
"できます。現在、英国の銀行口座でのみ利用できます。"
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:1861
|
||||
msgid "PayPal via Stripe"
|
||||
@@ -32474,22 +32460,16 @@ msgstr ""
|
||||
"能です。アプリを準備してください。"
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:1893
|
||||
#, fuzzy
|
||||
#| msgid "giropay via Stripe"
|
||||
msgid "PromptPay via Stripe"
|
||||
msgstr "Stripe経由でgiropay"
|
||||
msgstr "Stripe経由でPromptPay"
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:1898
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "This payment method is available to MobilePay app users in Denmark and "
|
||||
#| "Finland. Please have your app ready."
|
||||
msgid ""
|
||||
"This payment method is available to PromptPay users in Thailand. Please have "
|
||||
"your app ready."
|
||||
msgstr ""
|
||||
"この支払い方法は、デンマークとフィンランドのMobilePayアプリユーザーに利用可能"
|
||||
"です。アプリを準備してください。"
|
||||
"この支払い方法は、タイのPromptPayユーザーが利用できます。アプリを準備してくだ"
|
||||
"さい。"
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:1917
|
||||
msgid "TWINT via Stripe"
|
||||
@@ -32792,22 +32772,16 @@ msgid "Confirm payment: %(code)s"
|
||||
msgstr "支払いを確認: %(code)s"
|
||||
|
||||
#: pretix/plugins/stripe/templates/pretixplugins/stripe/sca.html:32
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Please scan the barcode below to complete your WeChat payment. Once you "
|
||||
#| "have completed your payment, you can refresh this page."
|
||||
msgid ""
|
||||
"Please scan the QR code below to complete your PromptPay payment. Once you "
|
||||
"have completed your payment, you can refresh this page."
|
||||
msgstr ""
|
||||
"下記のバーコードをスキャンしてWeChat支払いを完了してください。支払いが完了し"
|
||||
"たら、このページを更新してください。"
|
||||
"PromptPayの支払いを完了するには、以下のQRコードをスキャンしてください。支払い"
|
||||
"が完了したら、このページを更新できます。"
|
||||
|
||||
#: pretix/plugins/stripe/templates/pretixplugins/stripe/sca.html:37
|
||||
#, fuzzy
|
||||
#| msgid "Create QR code"
|
||||
msgid "PromptPay QR code"
|
||||
msgstr "注文番号"
|
||||
msgstr "PromptPay QRコード"
|
||||
|
||||
#: pretix/plugins/stripe/templates/pretixplugins/stripe/sca_return.html:20
|
||||
msgid "Confirming your payment…"
|
||||
@@ -33825,10 +33799,7 @@ msgstr[0] ""
|
||||
"このカテゴリから%(min_count)s個のオプションを選択する必要があります。"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_addon_choice.html:26
|
||||
#, fuzzy, python-format
|
||||
#| msgid "You can choose %(max_count)s option from this category."
|
||||
#| msgid_plural ""
|
||||
#| "You can choose up to %(max_count)s options from this category."
|
||||
#, python-format
|
||||
msgid "You can choose one option from this category."
|
||||
msgid_plural "You can choose up to %(max_count)s options from this category."
|
||||
msgstr[0] "このカテゴリから最大 %(max_count)s のオプションを選択できます。"
|
||||
@@ -35874,6 +35845,8 @@ msgid ""
|
||||
"Your cart timeout was extended. Please note that some of the prices in your "
|
||||
"cart changed."
|
||||
msgstr ""
|
||||
"カートのタイムアウトが延長されました。カートの価格の一部が変更されましたので"
|
||||
"ご注意ください。"
|
||||
|
||||
#: pretix/presale/views/cart.py:573
|
||||
msgid "Your cart timeout was extended."
|
||||
|
||||
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-01-05 12:12+0000\n"
|
||||
"PO-Revision-Date: 2025-12-22 20:00+0000\n"
|
||||
"PO-Revision-Date: 2026-01-12 17:00+0000\n"
|
||||
"Last-Translator: Ruud Hendrickx <ruud@leckxicon.eu>\n"
|
||||
"Language-Team: Dutch (informal) <https://translate.pretix.eu/projects/pretix/"
|
||||
"pretix/nl_Informal/>\n"
|
||||
@@ -4008,18 +4008,16 @@ msgstr ""
|
||||
|
||||
#: pretix/base/invoicing/peppol.py:164
|
||||
msgid "The Peppol participant ID is not registered on the Peppol network."
|
||||
msgstr ""
|
||||
msgstr "De Peppol-deelnemers-ID is niet geregistreerd op het Peppol-netwerk."
|
||||
|
||||
#: pretix/base/invoicing/peppol.py:184
|
||||
msgid "Peppol participant ID"
|
||||
msgstr "Peppol-deelnemers-ID"
|
||||
|
||||
#: pretix/base/invoicing/peppol.py:200
|
||||
#, fuzzy
|
||||
#| msgid "Gift card code"
|
||||
msgctxt "peppol_invoice"
|
||||
msgid "Visual copy"
|
||||
msgstr "Cadeauboncode"
|
||||
msgstr "Visuele kopie"
|
||||
|
||||
#: pretix/base/invoicing/peppol.py:205
|
||||
msgctxt "peppol_invoice"
|
||||
@@ -8769,6 +8767,8 @@ msgid ""
|
||||
"Some products can no longer be purchased and have been removed from your "
|
||||
"cart for the following reason: %s"
|
||||
msgstr ""
|
||||
"Sommige producten kunnen niet meer gekocht worden en zijn om de volgende "
|
||||
"reden uit je winkelwagen verwijderd: %s"
|
||||
|
||||
#: pretix/base/services/cart.py:117
|
||||
msgid ""
|
||||
@@ -10037,21 +10037,15 @@ msgid "Uncategorized"
|
||||
msgstr "Ongecategoriseerd"
|
||||
|
||||
#: pretix/base/services/tax.py:43
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Your VAT ID could not be checked, as the VAT checking service of your "
|
||||
#| "country is currently not available. We will therefore need to charge VAT "
|
||||
#| "on your invoice. You can get the tax amount back via the VAT "
|
||||
#| "reimbursement process."
|
||||
msgid ""
|
||||
"Your VAT ID could not be checked, as the VAT checking service of your "
|
||||
"country is currently not available. We will therefore need to charge you the "
|
||||
"same tax rate as if you did not enter a VAT ID."
|
||||
msgstr ""
|
||||
"Je btw-nummer kan niet worden gecontroleerd omdat de btw-controledienst van "
|
||||
"jouw land momenteel niet beschikbaar is. We zijn daarom genoodzaakt om de "
|
||||
"btw te factureren. Je kan het belastingbedrag terugkrijgen via het btw-"
|
||||
"terugbetalingsproces."
|
||||
"Je btw-nummer kon niet worden gecontroleerd, omdat de btw-controleservice "
|
||||
"van je land momenteel niet beschikbaar is. We zullen daarom hetzelfde "
|
||||
"belastingtarief in rekening moeten brengen als wanneer je geen btw-nummer "
|
||||
"had opgegeven."
|
||||
|
||||
#: pretix/base/services/tax.py:47 pretix/base/services/tax.py:366
|
||||
#: pretix/base/services/tax.py:393
|
||||
@@ -10506,21 +10500,17 @@ msgid "Ask for VAT ID"
|
||||
msgstr "Vraag om btw-nummer"
|
||||
|
||||
#: pretix/base/settings.py:632
|
||||
#, fuzzy, python-brace-format
|
||||
#| msgid ""
|
||||
#| "Does only work if an invoice address is asked for. VAT ID is not required."
|
||||
#, 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 ""
|
||||
"Werkt alleen als een factuuradres wordt gevraagd. Btw-nummer is niet "
|
||||
"verplicht."
|
||||
"Werkt alleen als een factuuradres wordt gevraagd. Btw-nummer is alleen "
|
||||
"vereist voor zakelijke klanten in de volgende landen: {countries}."
|
||||
|
||||
#: pretix/base/settings.py:651
|
||||
#, fuzzy
|
||||
#| msgid "Require name"
|
||||
msgid "Require VAT ID in"
|
||||
msgstr "Naam opgeven verplicht"
|
||||
msgstr "Btw-nummer verplicht in"
|
||||
|
||||
#: pretix/base/settings.py:657
|
||||
msgid ""
|
||||
@@ -10528,6 +10518,9 @@ msgid ""
|
||||
"ID in all countries. VAT ID will be required for all business addresses in "
|
||||
"the selected countries."
|
||||
msgstr ""
|
||||
"Het btw-nummer is standaard optioneel, omdat niet alle bedrijven in alle "
|
||||
"landen een btw-nummer toegewezen krijgen. Het btw-nummer is vereist voor "
|
||||
"alle bedrijfsadressen in de geselecteerde landen."
|
||||
|
||||
#: pretix/base/settings.py:672
|
||||
msgid "Invoice address explanation"
|
||||
@@ -14364,11 +14357,9 @@ msgstr ""
|
||||
"weer aan, ten minste voor deze site, of voor 'same-origin'-verzoeken."
|
||||
|
||||
#: pretix/base/views/js_helpers.py:41
|
||||
#, fuzzy
|
||||
#| msgid "ID"
|
||||
msgctxt "tax_id_swiss"
|
||||
msgid "UID"
|
||||
msgstr "ID"
|
||||
msgstr "UID"
|
||||
|
||||
#. Translators: Only translate to French (IDE) and Italien (IDI), otherwise keep the same
|
||||
#. Awareness around VAT IDs differes by EU country. For example, in Germany the VAT ID is assigned
|
||||
@@ -14974,6 +14965,8 @@ msgid ""
|
||||
"Formatting is not supported, as some accounting departments process mail "
|
||||
"automatically and do not handle formatted emails properly."
|
||||
msgstr ""
|
||||
"Opmaak wordt niet ondersteund, omdat sommige boekhoudafdelingen e-mails "
|
||||
"automatisch verwerken en opgemaakte e-mails niet goed kunnen verwerken."
|
||||
|
||||
#: pretix/control/forms/event.py:1356
|
||||
msgid ""
|
||||
@@ -14981,7 +14974,7 @@ msgid ""
|
||||
"the field is empty, the mail will never be sent."
|
||||
msgstr ""
|
||||
"Deze e-mail zal dit aantal dagen voor het evenement start worden verstuurd. "
|
||||
"Als dit veld leeg is zal de mail nooit worden verstuurd."
|
||||
"Als dit veld leeg is, zal de mail nooit worden verstuurd."
|
||||
|
||||
#: pretix/control/forms/event.py:1360
|
||||
#, fuzzy
|
||||
@@ -15472,7 +15465,7 @@ msgstr "Betaald"
|
||||
#: pretix/control/forms/filter.py:1304
|
||||
msgctxt "subevent"
|
||||
msgid "Date doesn't start in selected date range."
|
||||
msgstr ""
|
||||
msgstr "De datum valt niet binnen de geselecteerde datumrange."
|
||||
|
||||
#: pretix/control/forms/filter.py:1360 pretix/control/forms/filter.py:1827
|
||||
msgid "Shop live and presale running"
|
||||
@@ -29848,6 +29841,9 @@ msgid ""
|
||||
"automatically. We recommend that you rename these in your source file to "
|
||||
"avoid problems during import."
|
||||
msgstr ""
|
||||
"Meerdere kolommen van het CSV-bestand hebben dezelfde naam en zijn "
|
||||
"automatisch hernoemd. We raden aan deze in je bronbestand te hernoemen om "
|
||||
"problemen tijdens het importeren te voorkomen."
|
||||
|
||||
#: pretix/control/views/modelimport.py:188
|
||||
msgid "The import was successful."
|
||||
@@ -31611,7 +31607,7 @@ msgstr ""
|
||||
|
||||
#: pretix/plugins/banktransfer/camtimport.py:33
|
||||
msgid "Empty file or unknown format."
|
||||
msgstr ""
|
||||
msgstr "Leeg bestand of onbekend format."
|
||||
|
||||
#: pretix/plugins/banktransfer/payment.py:69
|
||||
msgid ""
|
||||
@@ -34206,6 +34202,9 @@ msgid ""
|
||||
"generate you API keys with the recommended permission level for optimal "
|
||||
"usage with pretix."
|
||||
msgstr ""
|
||||
"Met de bovenstaande knop installeer je onze Stripe-app op je account en "
|
||||
"genereer je API-sleutels met het aanbevolen machtigingsniveau voor optimaal "
|
||||
"gebruik met pretix."
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:291
|
||||
msgid "Secret key"
|
||||
@@ -34266,6 +34265,8 @@ msgid ""
|
||||
"Some payment methods might need to be enabled in the settings of your Stripe "
|
||||
"account before they work properly."
|
||||
msgstr ""
|
||||
"Sommige betaalmethoden moeten mogelijk eerst worden ingeschakeld in de "
|
||||
"instellingen van je Stripe-account voordat ze correct werken."
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:350 pretix/plugins/stripe/payment.py:1572
|
||||
msgid "Alipay"
|
||||
@@ -34326,16 +34327,16 @@ msgid "Przelewy24"
|
||||
msgstr "Przelewy24"
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:417 pretix/plugins/stripe/payment.py:1836
|
||||
#, fuzzy
|
||||
#| msgid "Payment by bank transfer"
|
||||
msgid "Pay by bank"
|
||||
msgstr "Betaling via bankoverschrijving"
|
||||
msgstr "Betaling via bank"
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:422
|
||||
msgid ""
|
||||
"Currently only available for charges in GBP and customers with UK bank "
|
||||
"accounts, and in private preview for France and Germany."
|
||||
msgstr ""
|
||||
"Momenteel alleen beschikbaar voor betalingen in GBP en klanten met een "
|
||||
"Britse bankrekening, en in privé-preview voor Frankrijk en Duitsland."
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:429 pretix/plugins/stripe/payment.py:1789
|
||||
msgid "WeChat Pay"
|
||||
@@ -34630,10 +34631,8 @@ msgid ""
|
||||
msgstr ""
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:1816
|
||||
#, fuzzy
|
||||
#| msgid "WeChat Pay via Stripe"
|
||||
msgid "Revolut Pay via Stripe"
|
||||
msgstr "WeChat Pay via Stripe"
|
||||
msgstr "Revolut Pay via Stripe"
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:1817
|
||||
msgid "Revolut Pay"
|
||||
@@ -34646,28 +34645,24 @@ msgid ""
|
||||
msgstr ""
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:1835
|
||||
#, fuzzy
|
||||
#| msgid "Payment via Stripe"
|
||||
msgid "Pay by bank via Stripe"
|
||||
msgstr "Betaling via Stripe"
|
||||
msgstr "Betaling door bank via Stripe"
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:1841
|
||||
msgid ""
|
||||
"Pay by bank allows you to authorize a secure Open Banking payment from your "
|
||||
"banking app. Currently available only with a UK bank account."
|
||||
msgstr ""
|
||||
"Met ‘Betalen door bank’ kun je een veilige Open Banking-betaling autoriseren "
|
||||
"vanuit je bankapp. Momenteel alleen beschikbaar met een Britse bankrekening."
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:1861
|
||||
#, fuzzy
|
||||
#| msgid "Payment via Stripe"
|
||||
msgid "PayPal via Stripe"
|
||||
msgstr "Betaling via Stripe"
|
||||
msgstr "PayPal via Stripe"
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:1869
|
||||
#, fuzzy
|
||||
#| msgid "EPS via Stripe"
|
||||
msgid "Swish via Stripe"
|
||||
msgstr "EPS via Stripe"
|
||||
msgstr "Swish via Stripe"
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:1874
|
||||
msgid ""
|
||||
@@ -34676,22 +34671,20 @@ msgid ""
|
||||
msgstr ""
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:1893
|
||||
#, fuzzy
|
||||
#| msgid "giropay via Stripe"
|
||||
msgid "PromptPay via Stripe"
|
||||
msgstr "giropay via Stripe"
|
||||
msgstr "PromptPay via Stripe"
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:1898
|
||||
msgid ""
|
||||
"This payment method is available to PromptPay users in Thailand. Please have "
|
||||
"your app ready."
|
||||
msgstr ""
|
||||
"Deze betaalmethode is beschikbaar voor PromptPay-gebruikers in Thailand. "
|
||||
"Zorg ervoor dat je de app bij de hand hebt."
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:1917
|
||||
#, fuzzy
|
||||
#| msgid "EPS via Stripe"
|
||||
msgid "TWINT via Stripe"
|
||||
msgstr "EPS via Stripe"
|
||||
msgstr "TWINT via Stripe"
|
||||
|
||||
#: pretix/plugins/stripe/payment.py:1922
|
||||
msgid ""
|
||||
@@ -35010,22 +35003,16 @@ msgid "Confirm payment: %(code)s"
|
||||
msgstr "Betaling bevestigen: %(code)s"
|
||||
|
||||
#: pretix/plugins/stripe/templates/pretixplugins/stripe/sca.html:32
|
||||
#, fuzzy
|
||||
#| msgid ""
|
||||
#| "Please scan the barcode below to complete your WeChat payment. Once you "
|
||||
#| "have completed your payment, you can refresh this page."
|
||||
msgid ""
|
||||
"Please scan the QR code below to complete your PromptPay payment. Once you "
|
||||
"have completed your payment, you can refresh this page."
|
||||
msgstr ""
|
||||
"Scan de QR-code hieronder om je WeChat-betaling uit te voeren. Als je de "
|
||||
"betaling hebt afgerond kan je deze pagina verversen."
|
||||
"Scan de QR-code hieronder om je PromptPay-betaling uit te voeren. Als je de "
|
||||
"betaling hebt afgerond, kan je deze pagina verversen."
|
||||
|
||||
#: pretix/plugins/stripe/templates/pretixplugins/stripe/sca.html:37
|
||||
#, fuzzy
|
||||
#| msgid "Order code"
|
||||
msgid "PromptPay QR code"
|
||||
msgstr "Bestelcode"
|
||||
msgstr "PromptPay-QR-code"
|
||||
|
||||
#: pretix/plugins/stripe/templates/pretixplugins/stripe/sca_return.html:20
|
||||
msgid "Confirming your payment…"
|
||||
@@ -36172,10 +36159,7 @@ msgstr[0] "Je moet precies één optie kiezen uit deze categorie."
|
||||
msgstr[1] "Je moet %(min_count)s opties kiezen uit deze categorie."
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/fragment_addon_choice.html:26
|
||||
#, fuzzy, python-format
|
||||
#| msgid "You can choose at most one option from this category."
|
||||
#| msgid_plural ""
|
||||
#| "You can choose up to %(max_count)s options from this category."
|
||||
#, python-format
|
||||
msgid "You can choose one option from this category."
|
||||
msgid_plural "You can choose up to %(max_count)s options from this category."
|
||||
msgstr[0] "Je kan maximaal één optie kiezen uit deze categorie."
|
||||
@@ -38526,12 +38510,12 @@ msgid ""
|
||||
"Your cart timeout was extended. Please note that some of the prices in your "
|
||||
"cart changed."
|
||||
msgstr ""
|
||||
"De time-out van je winkelwagen is verlengd. Merk op dat sommige prijzen in "
|
||||
"je winkelwagen gewijzigd zijn."
|
||||
|
||||
#: pretix/presale/views/cart.py:573
|
||||
#, fuzzy
|
||||
#| msgid "Your cart has been updated."
|
||||
msgid "Your cart timeout was extended."
|
||||
msgstr "Je winkelwagen is bijgewerkt."
|
||||
msgstr "De time-out van je winkelwagen is verlengd."
|
||||
|
||||
#: pretix/presale/views/cart.py:588
|
||||
msgid "The products have been successfully added to your cart."
|
||||
|
||||
@@ -8,8 +8,8 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-01-05 12:12+0000\n"
|
||||
"PO-Revision-Date: 2025-11-07 23:00+0000\n"
|
||||
"Last-Translator: Linnea Thelander <linnea@coeo.events>\n"
|
||||
"PO-Revision-Date: 2026-01-16 09:22+0000\n"
|
||||
"Last-Translator: Richard Schreiber <schreiber@rami.io>\n"
|
||||
"Language-Team: Swedish <https://translate.pretix.eu/projects/pretix/pretix/"
|
||||
"sv/>\n"
|
||||
"Language: sv\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.2\n"
|
||||
"X-Generator: Weblate 5.15.2\n"
|
||||
|
||||
#: pretix/_base_settings.py:87
|
||||
msgid "English"
|
||||
@@ -8993,10 +8993,12 @@ msgstr ""
|
||||
"exporter."
|
||||
|
||||
#: pretix/base/services/invoices.py:116
|
||||
#, python-brace-format
|
||||
#, fuzzy, python-brace-format
|
||||
msgctxt "invoice"
|
||||
msgid "Please complete your payment before {expire_date}."
|
||||
msgstr "{expire_date}."
|
||||
msgstr ""
|
||||
"Om din betalning inte gick igenom, se till att uppdatera din "
|
||||
"betalningsinformation innan {expire_date} via knappen nedan."
|
||||
|
||||
#: pretix/base/services/invoices.py:128
|
||||
#, python-brace-format
|
||||
@@ -35834,7 +35836,7 @@ msgstr "Visa i backend"
|
||||
#: pretix/presale/templates/pretixpresale/event/order.html:92
|
||||
#, python-format
|
||||
msgid "A payment of %(total)s is still pending for this order."
|
||||
msgstr "En faktura på totalt %(total)s kommer att skickas från Coeo."
|
||||
msgstr "Tack för din bokning på %(total)s."
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/order.html:97
|
||||
#, fuzzy, python-format
|
||||
@@ -35843,7 +35845,7 @@ msgstr "Tack för din bokning!"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/order.html:108
|
||||
msgid "Re-try payment or choose another payment method"
|
||||
msgstr "Tack"
|
||||
msgstr "Uppdatera eller ändra betalningsmetod"
|
||||
|
||||
#: pretix/presale/templates/pretixpresale/event/order.html:126
|
||||
msgid ""
|
||||
|
||||
@@ -8,16 +8,16 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-01-05 12:12+0000\n"
|
||||
"PO-Revision-Date: 2024-03-30 11:00+0000\n"
|
||||
"Last-Translator: Thatthep <amaudy@gmail.com>\n"
|
||||
"Language-Team: Thai <https://translate.pretix.eu/projects/pretix/pretix/th/"
|
||||
">\n"
|
||||
"PO-Revision-Date: 2026-01-12 17:00+0000\n"
|
||||
"Last-Translator: chondaen12 <chondaen12@gmail.com>\n"
|
||||
"Language-Team: Thai <https://translate.pretix.eu/projects/pretix/pretix/th/>"
|
||||
"\n"
|
||||
"Language: th\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.4.3\n"
|
||||
"X-Generator: Weblate 5.15.1\n"
|
||||
|
||||
#: pretix/_base_settings.py:87
|
||||
msgid "English"
|
||||
@@ -29,7 +29,7 @@ msgstr "เยอรมัน"
|
||||
|
||||
#: pretix/_base_settings.py:89
|
||||
msgid "German (informal)"
|
||||
msgstr "เยอรมัน"
|
||||
msgstr "เยอรมัน (ไม่เป็นทางการ)"
|
||||
|
||||
#: pretix/_base_settings.py:90
|
||||
msgid "Arabic"
|
||||
@@ -3567,7 +3567,7 @@ msgstr ""
|
||||
#: pretix/base/invoicing/pdf.py:732 pretix/base/invoicing/pdf.py:740
|
||||
msgctxt "invoice"
|
||||
msgid "Description"
|
||||
msgstr ""
|
||||
msgstr "คำอธิบาย"
|
||||
|
||||
#: pretix/base/invoicing/pdf.py:733 pretix/base/invoicing/pdf.py:741
|
||||
msgctxt "invoice"
|
||||
@@ -3577,7 +3577,7 @@ msgstr ""
|
||||
#: pretix/base/invoicing/pdf.py:734 pretix/base/invoicing/pdf.py:1038
|
||||
msgctxt "invoice"
|
||||
msgid "Tax rate"
|
||||
msgstr ""
|
||||
msgstr "อัตราภาษี"
|
||||
|
||||
#: pretix/base/invoicing/pdf.py:735
|
||||
msgctxt "invoice"
|
||||
@@ -3592,7 +3592,7 @@ msgstr ""
|
||||
#: pretix/base/invoicing/pdf.py:742
|
||||
msgctxt "invoice"
|
||||
msgid "Amount"
|
||||
msgstr ""
|
||||
msgstr "จำนวน"
|
||||
|
||||
#: pretix/base/invoicing/pdf.py:869
|
||||
#, python-brace-format
|
||||
@@ -3624,12 +3624,12 @@ msgstr ""
|
||||
#: pretix/base/invoicing/pdf.py:979
|
||||
msgctxt "invoice"
|
||||
msgid "Paid by gift card"
|
||||
msgstr ""
|
||||
msgstr "จ่ายโดยบัตรของขวัญ"
|
||||
|
||||
#: pretix/base/invoicing/pdf.py:984
|
||||
msgctxt "invoice"
|
||||
msgid "Remaining amount"
|
||||
msgstr ""
|
||||
msgstr "จำนวนคงเหลือ"
|
||||
|
||||
#: pretix/base/invoicing/pdf.py:1008
|
||||
#, python-brace-format
|
||||
@@ -3640,7 +3640,7 @@ msgstr ""
|
||||
#: pretix/base/invoicing/pdf.py:1039
|
||||
msgctxt "invoice"
|
||||
msgid "Net value"
|
||||
msgstr ""
|
||||
msgstr "ยอดสุทธิ"
|
||||
|
||||
#: pretix/base/invoicing/pdf.py:1040
|
||||
msgctxt "invoice"
|
||||
@@ -3650,7 +3650,7 @@ msgstr ""
|
||||
#: pretix/base/invoicing/pdf.py:1041
|
||||
msgctxt "invoice"
|
||||
msgid "Tax"
|
||||
msgstr ""
|
||||
msgstr "ภาษี"
|
||||
|
||||
#: pretix/base/invoicing/pdf.py:1071
|
||||
msgctxt "invoice"
|
||||
|
||||
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-01-05 12:12+0000\n"
|
||||
"PO-Revision-Date: 2025-12-22 20:00+0000\n"
|
||||
"PO-Revision-Date: 2026-01-12 17: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"
|
||||
@@ -288,39 +288,28 @@ 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:2321
|
||||
#, 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:2315
|
||||
#, 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
|
||||
#| msgid ""
|
||||
#| "Updating add-ons, bundles, or variations via PATCH/PUT is not supported. "
|
||||
#| "Please use the dedicated nested endpoint."
|
||||
msgid ""
|
||||
"Updating add-ons, bundles, program times or variations via PATCH/PUT is not "
|
||||
"supported. Please use the dedicated nested endpoint."
|
||||
msgstr ""
|
||||
"不支持通過 PATCH/PUT 更新附加組件、捆綁包或變體。 請使用專用的嵌套端點。"
|
||||
"不支援透過PATCH/PUT更新附加元件、捆綁包、程式時間或變體。 請使用專用的巢狀端"
|
||||
"點。"
|
||||
|
||||
#: pretix/api/serializers/item.py:345
|
||||
msgid "Only admission products can currently be personalized."
|
||||
@@ -570,10 +559,8 @@ 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
|
||||
msgid ""
|
||||
@@ -614,16 +601,12 @@ 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 ""
|
||||
|
||||
@@ -271,7 +271,8 @@ class BankTransfer(BasePaymentProvider):
|
||||
'request': request,
|
||||
'event': self.event,
|
||||
'settings': self.settings,
|
||||
'code': self._code(order) if order else None,
|
||||
'code': self._code(order, force=False) if order else None,
|
||||
'order': order,
|
||||
'details': self.settings.get('bank_details', as_type=LazyI18nString),
|
||||
}
|
||||
return template.render(ctx)
|
||||
@@ -295,7 +296,7 @@ class BankTransfer(BasePaymentProvider):
|
||||
md_nl2br = " \n"
|
||||
if self.settings.get('bank_details_type') == 'sepa':
|
||||
bankdetails = (
|
||||
(_("Reference"), self._code(order)),
|
||||
(_("Reference"), self._code(order, force=True)),
|
||||
(_("Amount"), money_filter(payment.amount, self.event.currency)),
|
||||
(_("Account holder"), self.settings.get('bank_details_sepa_name')),
|
||||
(_("IBAN"), ibanformat(self.settings.get('bank_details_sepa_iban'))),
|
||||
@@ -304,7 +305,7 @@ class BankTransfer(BasePaymentProvider):
|
||||
)
|
||||
else:
|
||||
bankdetails = (
|
||||
(_("Reference"), self._code(order)),
|
||||
(_("Reference"), self._code(order, force=True)),
|
||||
(_("Amount"), money_filter(payment.amount, self.event.currency)),
|
||||
)
|
||||
t += md_nl2br.join([f"**{k}:** {v}" for k, v in bankdetails])
|
||||
@@ -317,7 +318,7 @@ class BankTransfer(BasePaymentProvider):
|
||||
template = get_template('pretixplugins/banktransfer/pending.html')
|
||||
ctx = {
|
||||
'event': self.event,
|
||||
'code': self._code(payment.order),
|
||||
'code': self._code(payment.order, force=True),
|
||||
'order': payment.order,
|
||||
'amount': payment.amount,
|
||||
'payment_info': payment.info_data,
|
||||
@@ -345,16 +346,25 @@ class BankTransfer(BasePaymentProvider):
|
||||
def _render_control_info(self, request, order, info_data, **extra_context):
|
||||
template = get_template('pretixplugins/banktransfer/control.html')
|
||||
ctx = {'request': request, 'event': self.event,
|
||||
'code': self._code(order),
|
||||
'code': self._code(order, force=True),
|
||||
'payment_info': info_data, 'order': order,
|
||||
**extra_context}
|
||||
return template.render(ctx)
|
||||
|
||||
def _code(self, order):
|
||||
def _code(self, order, force=False):
|
||||
prefix = self.settings.get('prefix', default='')
|
||||
li = order.invoices.last()
|
||||
invoice_number = li.number if self.settings.get('include_invoice_number', as_type=bool) and li else ''
|
||||
|
||||
invoice_will_be_generated = (
|
||||
not li and
|
||||
self.settings.get('include_invoice_number', as_type=bool) and
|
||||
order.event.settings.get('invoice_generate') == 'paid' and
|
||||
self.requires_invoice_immediately
|
||||
)
|
||||
if invoice_will_be_generated and not force:
|
||||
return None
|
||||
|
||||
code = " ".join((prefix, order.full_code, invoice_number)).strip(" ")
|
||||
|
||||
if self.settings.get('omit_hyphen', as_type=bool):
|
||||
|
||||
@@ -24,7 +24,13 @@
|
||||
{{ details | rich_text }}
|
||||
{% if not code %}</div>{% endif %}
|
||||
|
||||
{% if not code %}
|
||||
{% if not code and order %}
|
||||
<p>
|
||||
<strong>
|
||||
{% trans "We will assign you a personal reference code in the next step." %}
|
||||
</strong>
|
||||
</p>
|
||||
{% elif not code %}
|
||||
<p>
|
||||
<strong>
|
||||
{% trans "We will assign you a personal reference code to use after you completed the order." %}
|
||||
|
||||
@@ -19,6 +19,30 @@ $(function () {
|
||||
fillOpacity: 0.3,
|
||||
behaveLikeLine: true
|
||||
});
|
||||
new Morris.Area({
|
||||
element: 'abd_chart',
|
||||
data: JSON.parse($("#abd-data").html()),
|
||||
xkey: 'date',
|
||||
ykeys: ['ordered', 'paid'],
|
||||
labels: [gettext('Attendees (ordered)'), gettext('Attendees (paid)')],
|
||||
lineColors: ['#3b1c4a', '#50a167'],
|
||||
smooth: false,
|
||||
resize: true,
|
||||
fillOpacity: 0.3,
|
||||
behaveLikeLine: true
|
||||
});
|
||||
new Morris.Area({
|
||||
element: 'abt_chart',
|
||||
data: JSON.parse($("#abt-data").html()),
|
||||
xkey: 'date',
|
||||
ykeys: ['ordered', 'paid'],
|
||||
labels: [gettext('Attendees (ordered)'), gettext('Attendees (paid)')],
|
||||
lineColors: ['#3b1c4a', '#50a167'],
|
||||
smooth: false,
|
||||
resize: true,
|
||||
fillOpacity: 0.3,
|
||||
behaveLikeLine: true
|
||||
});
|
||||
new Morris.Area({
|
||||
element: 'rev_chart',
|
||||
data: JSON.parse($("#rev-data").html()),
|
||||
|
||||
@@ -24,6 +24,48 @@
|
||||
<small>
|
||||
{% blocktrans trimmed %}
|
||||
Orders paid in multiple payments are shown with the date of their last payment.
|
||||
Placed orders include all orders (pending, paid, cancelled, and expired);
|
||||
paid orders include only paid orders and exclude all cancelled orders.
|
||||
{% endblocktrans %}
|
||||
</small>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">{% trans "Attendees by day" %}</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div id="abd_chart" class="chart"></div>
|
||||
<p class="help-block">
|
||||
<small>
|
||||
{% blocktrans trimmed %}
|
||||
Attendees in orders paid in multiple instalments are shown using the date of the
|
||||
final payment. Order dates reflect when the order was first placed; attendees added
|
||||
later via additional order positions still use the original order date. Attendees in
|
||||
placed orders include those from all order states (pending, paid, cancelled, and
|
||||
expired); attendees in paid orders include only those from paid orders and exclude
|
||||
those from cancelled orders.
|
||||
{% endblocktrans %}
|
||||
</small>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">{% trans "Attendees by time" %}</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div id="abt_chart" class="chart"></div>
|
||||
<p class="help-block">
|
||||
<small>
|
||||
{% blocktrans trimmed %}
|
||||
Attendees in orders paid in multiple instalments are shown using the date of the
|
||||
final payment. Order dates reflect when the order was first placed; attendees added
|
||||
later via additional order positions still use the original order date. Attendees in
|
||||
placed orders include those from all order states (pending, paid, cancelled, and
|
||||
expired); attendees in paid orders include only those from paid orders and exclude
|
||||
those from cancelled orders.
|
||||
{% endblocktrans %}
|
||||
</small>
|
||||
</p>
|
||||
@@ -45,10 +87,19 @@
|
||||
{% endif %}
|
||||
<p class="help-block">
|
||||
<small>
|
||||
{% blocktrans trimmed %}
|
||||
Only fully paid orders are counted.
|
||||
Orders paid in multiple payments are shown with the date of their last payment.
|
||||
{% endblocktrans %}
|
||||
{% if request.GET.subevent %}
|
||||
{% blocktrans trimmed %}
|
||||
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.
|
||||
{% endblocktrans %}
|
||||
{% else %}
|
||||
{% blocktrans trimmed %}
|
||||
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 cancelled orders.
|
||||
{% endblocktrans %}
|
||||
{% endif %}
|
||||
</small>
|
||||
</p>
|
||||
</div>
|
||||
@@ -59,6 +110,14 @@
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div id="obp_chart" class="chart"></div>
|
||||
<p class="help-block">
|
||||
<small>
|
||||
{% blocktrans trimmed %}
|
||||
Placed orders include all orders (pending, paid, cancelled, and expired);
|
||||
paid orders include only paid orders and exclude all cancelled orders.
|
||||
{% endblocktrans %}
|
||||
</small>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{% if seats %}
|
||||
@@ -158,6 +217,8 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
<script type="application/json" id="obd-data">{{ obd_data|escapejson }}</script>
|
||||
<script type="application/json" id="abd-data">{{ abd_data|escapejson }}</script>
|
||||
<script type="application/json" id="abt-data">{{ abt_data|escapejson }}</script>
|
||||
<script type="application/json" id="rev-data">{{ rev_data|escapejson }}</script>
|
||||
<script type="application/json" id="obp-data">{{ obp_data|escapejson }}</script>
|
||||
<script type="application/text" id="currency">{{ request.event.currency }}</script>
|
||||
|
||||
@@ -103,7 +103,10 @@ class IndexView(EventPermissionRequiredMixin, ChartContainingView, TemplateView)
|
||||
day = o['datetime'].astimezone(tz).date()
|
||||
ordered_by_day[day] = ordered_by_day.get(day, 0) + 1
|
||||
paid_by_day = {}
|
||||
for o in oqs.filter(event=self.request.event, payment_date__isnull=False).values('payment_date'):
|
||||
for o in oqs.filter(
|
||||
event=self.request.event, payment_date__isnull=False,
|
||||
status=Order.STATUS_PAID, all_positions__canceled=False
|
||||
).distinct().values('payment_date'):
|
||||
day = o['payment_date'].astimezone(tz).date()
|
||||
paid_by_day[day] = paid_by_day.get(day, 0) + 1
|
||||
|
||||
@@ -125,10 +128,56 @@ class IndexView(EventPermissionRequiredMixin, ChartContainingView, TemplateView)
|
||||
ctx['obd_data'] = json.dumps(data)
|
||||
cache.set('statistics_obd_data' + ckey, ctx['obd_data'])
|
||||
|
||||
# Attendees by day/time
|
||||
ctx['abd_data'] = cache.get('statistics_abd_data' + ckey)
|
||||
ctx['abt_data'] = cache.get('statistics_abt_data' + ckey)
|
||||
if not ctx['abd_data'] or not ctx['abt_data']:
|
||||
opqs = OrderPosition.all.filter(order__event=self.request.event, item__admission=True).annotate(
|
||||
payment_date=Subquery(op_date, output_field=DateTimeField())
|
||||
)
|
||||
if subevent:
|
||||
opqs = opqs.filter(subevent=subevent)
|
||||
|
||||
ordered_by_day = {}
|
||||
for p in opqs.values('order__datetime'):
|
||||
day = p['order__datetime'].astimezone(tz).date()
|
||||
ordered_by_day[day] = ordered_by_day.get(day, 0) + 1
|
||||
|
||||
paid_by_day = {}
|
||||
for p in opqs.filter(payment_date__isnull=False, canceled=False, order__status=Order.STATUS_PAID).values('payment_date'):
|
||||
day = p['payment_date'].astimezone(tz).date()
|
||||
paid_by_day[day] = paid_by_day.get(day, 0) + 1
|
||||
|
||||
day_data = []
|
||||
time_data = []
|
||||
for d in dateutil.rrule.rrule(
|
||||
dateutil.rrule.DAILY,
|
||||
dtstart=min(ordered_by_day.keys()) if ordered_by_day else datetime.date.today(),
|
||||
until=max(
|
||||
max(ordered_by_day.keys() if paid_by_day else [datetime.date.today()]),
|
||||
max(paid_by_day.keys() if paid_by_day else [datetime.date(1970, 1, 1)])
|
||||
)):
|
||||
d = d.date()
|
||||
day_data.append({
|
||||
'date': d.strftime('%Y-%m-%d'),
|
||||
'ordered': ordered_by_day.get(d, 0),
|
||||
'paid': paid_by_day.get(d, 0)
|
||||
})
|
||||
time_data.append({
|
||||
'date': d.strftime('%Y-%m-%d'),
|
||||
'ordered': (time_data[-1]["ordered"] if time_data else 0) + ordered_by_day.get(d, 0),
|
||||
'paid': (time_data[-1]["paid"] if time_data else 0) + paid_by_day.get(d, 0)
|
||||
})
|
||||
|
||||
ctx['abd_data'] = json.dumps(day_data)
|
||||
ctx['abt_data'] = json.dumps(time_data)
|
||||
cache.set('statistics_abd_data' + ckey, ctx['abd_data'])
|
||||
cache.set('statistics_abt_data' + ckey, ctx['abt_data'])
|
||||
|
||||
# Orders by product
|
||||
ctx['obp_data'] = cache.get('statistics_obp_data' + ckey)
|
||||
if not ctx['obp_data']:
|
||||
opqs = OrderPosition.objects
|
||||
opqs = OrderPosition.all
|
||||
if subevent:
|
||||
opqs = opqs.filter(subevent=subevent)
|
||||
num_ordered = {
|
||||
@@ -141,7 +190,7 @@ class IndexView(EventPermissionRequiredMixin, ChartContainingView, TemplateView)
|
||||
num_paid = {
|
||||
p['item']: p['cnt']
|
||||
for p in (opqs
|
||||
.filter(order__event=self.request.event, order__status=Order.STATUS_PAID)
|
||||
.filter(order__event=self.request.event, order__status=Order.STATUS_PAID, canceled=False)
|
||||
.values('item')
|
||||
.annotate(cnt=Count('id')).order_by())
|
||||
}
|
||||
|
||||
@@ -313,12 +313,12 @@
|
||||
<input type="hidden" name="variation_{{ line.item.id }}_{{ line.variation.id }}"
|
||||
value="1" />
|
||||
<input type="hidden" name="price_{{ line.item.id }}_{{ line.variation.id }}"
|
||||
value="{% if event.settings.display_net_prices %}{{ line.bundle_sum_net }}{% else %}{{ line.bundle_sum }}{% endif %}" />
|
||||
value="{% if event.settings.display_net_prices %}{{ line.price_for_input_net }}{% else %}{{ line.price_for_input }}{% endif %}" />
|
||||
{% else %}
|
||||
<input type="hidden" name="item_{{ line.item.id }}"
|
||||
value="1" />
|
||||
<input type="hidden" name="price_{{ line.item.id }}"
|
||||
value="{% if event.settings.display_net_prices %}{{ line.bundle_sum_net }}{% else %}{{ line.bundle_sum }}{% endif %}" />
|
||||
value="{% if event.settings.display_net_prices %}{{ line.price_for_input_net }}{% else %}{{ line.price_for_input }}{% endif %}" />
|
||||
{% endif %}
|
||||
<button class="btn btn-mini btn-link {% if line.seat %}btn-invisible{% endif %}" title="{% blocktrans with item=line.item.name %}Add one more {{item}} to your cart{% endblocktrans %}" {% if line.seat %}disabled{% endif %}>
|
||||
<i class="fa fa-plus" aria-hidden="true"></i>
|
||||
|
||||
@@ -48,7 +48,7 @@ from django.utils.timezone import now
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django_scopes import scopes_disabled
|
||||
|
||||
from pretix.base.i18n import get_language_without_region
|
||||
from pretix.base.i18n import get_language_without_region, set_region
|
||||
from pretix.base.middleware import get_supported_language
|
||||
from pretix.base.models import (
|
||||
CartPosition, Customer, InvoiceAddress, ItemAddOn, OrderFee, Question,
|
||||
@@ -209,6 +209,8 @@ class CartMixin:
|
||||
pos.valid_from,
|
||||
pos.valid_until,
|
||||
pos.used_membership_id,
|
||||
pos.gross_price_before_rounding,
|
||||
pos.tax_value_before_rounding,
|
||||
)
|
||||
|
||||
positions = []
|
||||
@@ -222,8 +224,8 @@ class CartMixin:
|
||||
if not hasattr(group, 'tax_rule'):
|
||||
group.tax_rule = group.item.tax_rule
|
||||
|
||||
group.bundle_sum = group.price + sum(a.price for a in has_addons[group.pk])
|
||||
group.bundle_sum_net = group.net_price + sum(a.net_price for a in has_addons[group.pk])
|
||||
group.price_for_input = group.gross_price_before_rounding + sum(a.gross_price_before_rounding for a in has_addons[group.pk])
|
||||
group.price_for_input_net = group.net_price_before_rounding + sum(a.net_price_before_rounding for a in has_addons[group.pk])
|
||||
|
||||
if answers:
|
||||
group.cache_answers(all=False)
|
||||
@@ -264,7 +266,7 @@ class CartMixin:
|
||||
'itemcount': sum(c.count for c in positions if not c.addon_to),
|
||||
'itemvarsums': itemvarsums,
|
||||
'current_selected_payments': [
|
||||
p for p in self.current_selected_payments(positions, fees, self.invoice_address)
|
||||
p for p in self.current_selected_payments(lcp, fees, self.invoice_address)
|
||||
if p.get('multi_use_supported')
|
||||
]
|
||||
}
|
||||
@@ -542,6 +544,7 @@ def iframe_entry_view_wrapper(view_func):
|
||||
region = request.event.settings.region
|
||||
if '-' not in lng and region:
|
||||
lng += '-' + region.lower()
|
||||
set_region(region)
|
||||
|
||||
# with language() is not good enough here – we really need to take the role of LocaleMiddleware and modify
|
||||
# global state, because template rendering might be happening lazily.
|
||||
|
||||
@@ -42,6 +42,7 @@ import os
|
||||
import re
|
||||
from collections import OrderedDict, defaultdict
|
||||
from decimal import Decimal
|
||||
from urllib.parse import quote
|
||||
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
@@ -103,13 +104,55 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class OrderDetailMixin(NoSearchIndexViewMixin):
|
||||
def _allow_anonymous_access(self):
|
||||
return not (self.request.organizer.settings.customer_accounts and
|
||||
self.request.organizer.settings.customer_accounts_require_login_for_order_access)
|
||||
|
||||
def verify_order_access(self):
|
||||
o = self.order
|
||||
|
||||
if o is None:
|
||||
raise Http404(_('Unknown order code or not authorized to access this order.'))
|
||||
|
||||
if o is False:
|
||||
login_url = eventreverse(self.request.organizer, 'presale:organizer.customer.login', kwargs={})
|
||||
|
||||
if hasattr(self.request, "event_domain") and self.request.event_domain:
|
||||
next_url = quote(self.request.scheme + "://" + self.request.get_host() + self.request.get_full_path())
|
||||
return redirect_to_url(f'{login_url}?next={next_url}&request_cross_domain_customer_auth=true')
|
||||
|
||||
else:
|
||||
next_url = quote(self.request.get_full_path())
|
||||
return redirect_to_url(f'{login_url}?next={next_url}')
|
||||
|
||||
return None
|
||||
|
||||
@cached_property
|
||||
def order(self):
|
||||
"""
|
||||
Returns the order object when access is permitted, returns `False` when the
|
||||
order exists but requires authentication, and returns `None` when the order
|
||||
does not exist or access is denied entirely.
|
||||
"""
|
||||
try:
|
||||
return self.request.event.orders.filter().select_related('event').get_with_secret_check(
|
||||
order = self.request.event.orders.filter().select_related('event').get_with_secret_check(
|
||||
code=self.kwargs['order'], received_secret=self.kwargs['secret'], tag=None,
|
||||
)
|
||||
|
||||
if has_event_access_permission(self.request, 'can_view_orders'):
|
||||
return order
|
||||
|
||||
if order.customer is None or not order.customer.is_verified or self._allow_anonymous_access():
|
||||
return order
|
||||
|
||||
if not self.request.customer:
|
||||
return False
|
||||
|
||||
if order.customer_id == self.request.customer.pk:
|
||||
return order
|
||||
|
||||
return None
|
||||
|
||||
except Order.DoesNotExist:
|
||||
return None
|
||||
|
||||
@@ -119,6 +162,13 @@ class OrderDetailMixin(NoSearchIndexViewMixin):
|
||||
'secret': self.order.secret
|
||||
})
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
resp = self.verify_order_access()
|
||||
if resp:
|
||||
return resp
|
||||
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
|
||||
class OrderPositionDetailMixin(NoSearchIndexViewMixin):
|
||||
@cached_property
|
||||
@@ -157,8 +207,6 @@ class OrderPositionDetailMixin(NoSearchIndexViewMixin):
|
||||
@method_decorator(xframe_options_exempt, 'dispatch')
|
||||
class OrderOpen(EventViewMixin, OrderDetailMixin, View):
|
||||
def get(self, request, *args, **kwargs):
|
||||
if not self.order:
|
||||
raise Http404(_('Unknown order code or not authorized to access this order.'))
|
||||
if self.order.check_email_confirm_secret(kwargs.get('hash')) and not self.order.email_known_to_work:
|
||||
self.order.log_action('pretix.event.order.contact.confirmed')
|
||||
self.order.email_known_to_work = True
|
||||
@@ -239,8 +287,6 @@ class OrderDetails(EventViewMixin, OrderDetailMixin, CartMixin, TicketPageMixin,
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
self.kwargs = kwargs
|
||||
if not self.order:
|
||||
raise Http404(_('Unknown order code or not authorized to access this order.'))
|
||||
if self.order.status == Order.STATUS_PENDING:
|
||||
payment_to_complete = self.order.payments.filter(state=OrderPayment.PAYMENT_STATE_CREATED, process_initiated=False).first()
|
||||
if payment_to_complete:
|
||||
@@ -360,8 +406,11 @@ class OrderPaymentStart(EventViewMixin, OrderDetailMixin, TemplateView):
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.request = request
|
||||
self.request.pci_dss_payment_page = True
|
||||
if not self.order:
|
||||
raise Http404(_('Unknown order code or not authorized to access this order.'))
|
||||
|
||||
resp = self.verify_order_access()
|
||||
if resp:
|
||||
return resp
|
||||
|
||||
if (self.order.status not in (Order.STATUS_PENDING, Order.STATUS_EXPIRED)
|
||||
or self.payment.state != OrderPayment.PAYMENT_STATE_CREATED
|
||||
or not self.payment.payment_provider.is_enabled
|
||||
@@ -428,8 +477,11 @@ class OrderPaymentConfirm(EventViewMixin, OrderDetailMixin, TemplateView):
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.request = request
|
||||
if not self.order:
|
||||
raise Http404(_('Unknown order code or not authorized to access this order.'))
|
||||
|
||||
resp = self.verify_order_access()
|
||||
if resp:
|
||||
return resp
|
||||
|
||||
if self.payment.state != OrderPayment.PAYMENT_STATE_CREATED or self.order._can_be_paid() is not True:
|
||||
messages.error(request, _('The payment for this order cannot be continued.'))
|
||||
return redirect(self.get_order_url())
|
||||
@@ -495,8 +547,11 @@ class OrderPaymentComplete(EventViewMixin, OrderDetailMixin, View):
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.request = request
|
||||
if not self.order:
|
||||
raise Http404(_('Unknown order code or not authorized to access this order.'))
|
||||
|
||||
resp = self.verify_order_access()
|
||||
if resp:
|
||||
return resp
|
||||
|
||||
if self.payment.state != OrderPayment.PAYMENT_STATE_CREATED or self.order._can_be_paid() is not True:
|
||||
messages.error(request, _('The payment for this order cannot be continued.'))
|
||||
return redirect(self.get_order_url())
|
||||
@@ -541,8 +596,11 @@ class OrderPayChangeMethod(EventViewMixin, OrderDetailMixin, TemplateView):
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.request = request
|
||||
self.request.pci_dss_payment_page = True
|
||||
if not self.order:
|
||||
raise Http404(_('Unknown order code or not authorized to access this order.'))
|
||||
|
||||
resp = self.verify_order_access()
|
||||
if resp:
|
||||
return resp
|
||||
|
||||
if self.order.status not in (Order.STATUS_PENDING, Order.STATUS_EXPIRED) or self.order._can_be_paid() is not True:
|
||||
messages.error(request, _('The payment method for this order cannot be changed.'))
|
||||
return redirect(self.get_order_url())
|
||||
@@ -727,8 +785,6 @@ class OrderInvoiceCreate(EventViewMixin, OrderDetailMixin, View):
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.request = request
|
||||
if not self.order:
|
||||
raise Http404(_('Unknown order code or not authorized to access this order.'))
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
@@ -860,8 +916,11 @@ class OrderModify(EventViewMixin, OrderDetailMixin, OrderQuestionsViewMixin, Tem
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.request = request
|
||||
self.kwargs = kwargs
|
||||
if not self.order:
|
||||
raise Http404(_('Unknown order code or not authorized to access this order.'))
|
||||
|
||||
resp = self.verify_order_access()
|
||||
if resp:
|
||||
return resp
|
||||
|
||||
if not self.order.can_modify_answers:
|
||||
messages.error(request, _('You cannot modify this order'))
|
||||
return redirect(self.get_order_url())
|
||||
@@ -947,8 +1006,11 @@ class OrderCancel(EventViewMixin, OrderDetailMixin, TemplateView):
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.request = request
|
||||
self.kwargs = kwargs
|
||||
if not self.order:
|
||||
raise Http404(_('Unknown order code or not authorized to access this order.'))
|
||||
|
||||
resp = self.verify_order_access()
|
||||
if resp:
|
||||
return resp
|
||||
|
||||
if not self.order.user_cancel_allowed:
|
||||
messages.error(request, _('You cannot cancel this order.'))
|
||||
return redirect(self.get_order_url())
|
||||
@@ -995,14 +1057,7 @@ class OrderCancelDo(EventViewMixin, OrderDetailMixin, AsyncAction, View):
|
||||
def get_error_url(self):
|
||||
return self.get_order_url()
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
if not self.order:
|
||||
raise Http404(_('Unknown order code or not authorized to access this order.'))
|
||||
return super().get(request, *args, **kwargs)
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
if not self.order:
|
||||
raise Http404(_('Unknown order code or not authorized to access this order.'))
|
||||
if not self.order.user_cancel_allowed:
|
||||
messages.error(request, _('You cannot cancel this order.'))
|
||||
return redirect(self.get_order_url())
|
||||
@@ -1293,9 +1348,6 @@ class OrderPositionDownload(OrderDownloadMixin, EventViewMixin, OrderPositionDet
|
||||
class InvoiceDownload(EventViewMixin, OrderDetailMixin, View):
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
if not self.order:
|
||||
raise Http404(_('Unknown order code or not authorized to access this order.'))
|
||||
|
||||
try:
|
||||
invoice = Invoice.objects.get(
|
||||
event=self.request.event,
|
||||
@@ -1688,8 +1740,11 @@ class OrderChange(OrderChangeMixin, EventViewMixin, OrderDetailMixin, TemplateVi
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
self.request = request
|
||||
self.kwargs = kwargs
|
||||
if not self.order:
|
||||
raise Http404(_('Unknown order code or not authorized to access this order.'))
|
||||
|
||||
resp = self.verify_order_access()
|
||||
if resp:
|
||||
return resp
|
||||
|
||||
if not self.order.user_change_allowed:
|
||||
messages.error(request, _('You cannot change this order.'))
|
||||
return redirect(self.get_order_url())
|
||||
|
||||
@@ -656,6 +656,11 @@ LOGGING = {
|
||||
'handlers': ['null'],
|
||||
'propagate': False,
|
||||
},
|
||||
'celery.utils.functional': {
|
||||
'handlers': ['file', 'console'],
|
||||
'level': 'INFO', # Do not output all the queries
|
||||
'propagate': False,
|
||||
},
|
||||
'django.db.backends': {
|
||||
'handlers': ['file', 'console'],
|
||||
'level': 'INFO', # Do not output all the queries
|
||||
|
||||
@@ -50,6 +50,7 @@ from pretix.base.models import (
|
||||
QuestionOption, Quota,
|
||||
)
|
||||
from pretix.base.models.orders import OrderFee
|
||||
from pretix.testutils.queries import assert_num_queries
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -422,6 +423,13 @@ def test_item_list(token_client, organizer, event, team, item):
|
||||
assert [] == resp.data['results']
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_item_list_queries(token_client, organizer, event, team, item, item3):
|
||||
with assert_num_queries(18):
|
||||
resp = token_client.get('/api/v1/organizers/{}/events/{}/items/'.format(organizer.slug, event.slug))
|
||||
assert resp.status_code == 200
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_item_detail(token_client, organizer, event, team, item):
|
||||
res = dict(TEST_ITEM_RES)
|
||||
|
||||
@@ -227,7 +227,9 @@ def test_placeholder_html_rendering_from_string(env):
|
||||
"Event website: [{event}](https://example.org/{event_slug})\n\n"
|
||||
"Other website: [{event}]({meta_Website})\n\n"
|
||||
"URL: {url}\n\n"
|
||||
"URL with text: <a href=\"{url}\">Test</a>"
|
||||
"URL with text: <a href=\"{url}\">Test</a>\n\n"
|
||||
"URL with params: https://example.com/form?action=foo&eventid={event_slug}\n\n"
|
||||
"URL with params and text: [Link & Text](https://example.com/form?action=foo&eventid={event_slug})\n\n"
|
||||
})
|
||||
djmail.outbox = []
|
||||
event, user, organizer = env
|
||||
@@ -249,6 +251,8 @@ def test_placeholder_html_rendering_from_string(env):
|
||||
assert '**Meta**: *Beep*' in djmail.outbox[0].body
|
||||
assert 'URL: https://google.com' in djmail.outbox[0].body
|
||||
assert 'URL with text: <a href="https://google.com">Test</a>' in djmail.outbox[0].body
|
||||
assert 'URL with params: https://example.com/form?action=foo&eventid=dummy' in djmail.outbox[0].body
|
||||
assert 'URL with params and text: [Link & Text](https://example.com/form?action=foo&eventid=dummy)' in djmail.outbox[0].body
|
||||
assert '<' not in djmail.outbox[0].body
|
||||
assert '&' not in djmail.outbox[0].body
|
||||
html = _extract_html(djmail.outbox[0])
|
||||
@@ -272,3 +276,13 @@ def test_placeholder_html_rendering_from_string(env):
|
||||
r'URL with text: <a href="https://google.com" rel="noopener" style="[^"]+" target="_blank">Test</a>',
|
||||
html
|
||||
)
|
||||
assert re.search(
|
||||
r'URL with params: <a href="https://example.com/form\?action=foo&eventid=dummy" rel="noopener" '
|
||||
r'style="[^"]+" target="_blank">https://example.com/form\?action=foo&eventid=dummy</a>',
|
||||
html
|
||||
)
|
||||
assert re.search(
|
||||
r'URL with params and text: <a href="https://example.com/form\?action=foo&eventid=dummy" rel="noopener" '
|
||||
r'style="[^"]+" target="_blank">Link & Text</a>',
|
||||
html
|
||||
)
|
||||
|
||||
@@ -781,6 +781,39 @@ testcases_single_rule = [
|
||||
)
|
||||
),
|
||||
|
||||
# Distribute discounts somewhat equally over addon groups
|
||||
(
|
||||
(
|
||||
Discount(
|
||||
condition_min_count=3,
|
||||
benefit_discount_matching_percent=20,
|
||||
condition_apply_to_addons=True,
|
||||
benefit_only_apply_to_cheapest_n_matches=1,
|
||||
condition_ignore_voucher_discounted=True,
|
||||
),
|
||||
),
|
||||
(
|
||||
(2, 1, now(), Decimal('0.00'), None, False, Decimal('10.00')), # Main product
|
||||
(1, 1, now(), Decimal('100.00'), 1, False, Decimal('0.00')),
|
||||
(1, 1, now(), Decimal('100.00'), 1, False, Decimal('0.00')),
|
||||
(1, 1, now(), Decimal('100.00'), 1, False, Decimal('0.00')),
|
||||
(2, 1, now(), Decimal('0.00'), None, False, Decimal('10.00')), # Main product
|
||||
(1, 1, now(), Decimal('100.00'), 2, False, Decimal('0.00')),
|
||||
(1, 1, now(), Decimal('100.00'), 2, False, Decimal('0.00')),
|
||||
(1, 1, now(), Decimal('100.00'), 2, False, Decimal('0.00')),
|
||||
),
|
||||
(
|
||||
Decimal('0.00'),
|
||||
Decimal('100.00'),
|
||||
Decimal('100.00'),
|
||||
Decimal('80.00'),
|
||||
Decimal('0.00'),
|
||||
Decimal('100.00'),
|
||||
Decimal('100.00'),
|
||||
Decimal('80.00'),
|
||||
)
|
||||
),
|
||||
|
||||
# Ignore bundled
|
||||
(
|
||||
(
|
||||
|
||||
@@ -68,9 +68,6 @@ def test_urlreplace_replace_parameter():
|
||||
|
||||
("en", Decimal("1023"), "JPY", "¥1,023"),
|
||||
|
||||
("pt-pt", Decimal("10.00"), "EUR", "10,00" + NBSP + "€"),
|
||||
("pt-br", Decimal("10.00"), "EUR", "€" + NBSP + "10,00"),
|
||||
|
||||
# unknown currency
|
||||
("de", Decimal("1234.56"), "FOO", "1.234,56" + NBSP + "FOO"),
|
||||
("de", Decimal("1234.567"), "FOO", "1.234,57" + NBSP + "FOO"),
|
||||
|
||||
@@ -2611,3 +2611,11 @@ def test_approve_cancellation_request(client, env):
|
||||
doc = BeautifulSoup(response.content.decode(), "lxml")
|
||||
assert doc.select('input[name=refund-new-giftcard]')[0]['value'] == '10.00'
|
||||
assert not env[2].cancellation_requests.exists()
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_view_as_user(client, env):
|
||||
client.login(email='dummy@dummy.dummy', password='dummy')
|
||||
response = client.get('/%s/%s/order/%s/%s/' % (env[0].organizer.slug, env[0].slug, env[2].code, env[2].secret))
|
||||
assert response.status_code == 200
|
||||
assert env[2].code in response.content.decode()
|
||||
|
||||
@@ -19,9 +19,12 @@
|
||||
# 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 pytest
|
||||
from django.utils.translation import get_language
|
||||
|
||||
from pretix.base.i18n import get_language_without_region, language
|
||||
from pretix.base.i18n import (
|
||||
get_babel_locale, get_language_without_region, language,
|
||||
)
|
||||
from pretix.helpers.i18n import get_javascript_format, get_moment_locale
|
||||
|
||||
|
||||
@@ -42,22 +45,26 @@ def test_get_locale():
|
||||
assert get_moment_locale('en-CA') == 'en-ca'
|
||||
|
||||
|
||||
def test_set_region():
|
||||
with language('de'):
|
||||
assert get_language() == 'de'
|
||||
assert get_language_without_region() == 'de'
|
||||
with language('de', 'US'):
|
||||
assert get_language() == 'de-us'
|
||||
assert get_language_without_region() == 'de'
|
||||
with language('de', 'DE'):
|
||||
assert get_language() == 'de-de'
|
||||
assert get_language_without_region() == 'de'
|
||||
with language('de-informal', 'DE'):
|
||||
assert get_language() == 'de-informal'
|
||||
assert get_language_without_region() == 'de-informal'
|
||||
with language('pt', 'PT'):
|
||||
assert get_language() == 'pt-pt'
|
||||
assert get_language_without_region() == 'pt-pt'
|
||||
with language('pt-pt', 'BR'):
|
||||
assert get_language() == 'pt-pt'
|
||||
assert get_language_without_region() == 'pt-pt'
|
||||
@pytest.mark.parametrize(
|
||||
["lng_in", "region_in", "lng_out", "lng_without_region_out", "babel_out"],
|
||||
[
|
||||
("en", None, "en", "en", "en"),
|
||||
("en-us", None, "en-us", "en", "en_US"),
|
||||
("en", "US", "en-us", "en", "en_US"),
|
||||
("de", None, "de", "de", "de"),
|
||||
("de", "US", "de-us", "de", "de"),
|
||||
("de", "DE", "de-de", "de", "de_DE"),
|
||||
("de-informal", "DE", "de-informal", "de-informal", "de_DE"),
|
||||
("de-informal", "CH", "de-informal", "de-informal", "de_CH"),
|
||||
("pt-pt", "PT", "pt-pt", "pt-pt", "pt_PT"),
|
||||
("es", "MX", "es-mx", "es", "es_MX"),
|
||||
("es-419", "MX", "es-419", "es-419", "es_MX"),
|
||||
("zh-hans", "CN", "zh-hans", "zh-hans", "zh_Hans_CN"),
|
||||
("zh-hant", "TW", "zh-hant", "zh-hant", "zh_Hant_TW"),
|
||||
],
|
||||
)
|
||||
def test_set_region(lng_in, region_in, lng_out, lng_without_region_out, babel_out):
|
||||
with language(lng_in, region_in):
|
||||
assert get_language() == lng_out
|
||||
assert get_language_without_region() == lng_without_region_out
|
||||
assert str(get_babel_locale()) == babel_out
|
||||
|
||||
@@ -1738,3 +1738,222 @@ class OrdersTest(BaseOrdersTest):
|
||||
self.order.secret, a.pk, match.group(1))
|
||||
)
|
||||
assert response.status_code == 404
|
||||
|
||||
def test_require_login_for_order_access_disabled_unauth(self):
|
||||
self.orga.settings.customer_accounts = True
|
||||
|
||||
with scopes_disabled():
|
||||
customer = self.orga.customers.create(email='john@example.org', is_verified=True)
|
||||
customer.set_password("foo")
|
||||
customer.save()
|
||||
|
||||
self.order.customer = customer
|
||||
self.order.save()
|
||||
|
||||
self.orga.settings.customer_accounts_require_login_for_order_access = False
|
||||
|
||||
response = self.client.get(
|
||||
'/%s/%s/order/%s/%s/' % (self.orga.slug, self.event.slug, self.order.code, self.order.secret)
|
||||
)
|
||||
assert response.status_code == 200
|
||||
doc = BeautifulSoup(response.content.decode(), "lxml")
|
||||
assert len(doc.select(".cart-row")) > 0
|
||||
assert "pending" in doc.select(".order-details")[0].text.lower()
|
||||
assert "Peter" in response.content.decode()
|
||||
assert "Lukas" not in response.content.decode()
|
||||
|
||||
response = self.client.get(
|
||||
'/%s/%s/ticket/%s/%s/%s/' % (self.orga.slug, self.event.slug, self.order.code,
|
||||
self.ticket_pos.positionid, self.ticket_pos.web_secret)
|
||||
)
|
||||
assert response.status_code == 200
|
||||
doc = BeautifulSoup(response.content.decode(), "lxml")
|
||||
assert len(doc.select(".cart-row")) > 0
|
||||
assert "pending" in doc.select(".order-details")[0].text.lower()
|
||||
assert "Peter" in response.content.decode()
|
||||
assert "Lukas" not in response.content.decode()
|
||||
|
||||
def test_require_login_for_order_access_enabled_unauth(self):
|
||||
self.orga.settings.customer_accounts = True
|
||||
|
||||
with scopes_disabled():
|
||||
customer = self.orga.customers.create(email='john@example.org', is_verified=True)
|
||||
customer.set_password("foo")
|
||||
customer.save()
|
||||
|
||||
self.order.customer = customer
|
||||
self.order.save()
|
||||
|
||||
self.orga.settings.customer_accounts_require_login_for_order_access = True
|
||||
|
||||
response = self.client.get(
|
||||
'/%s/%s/order/%s/%s/' % (self.orga.slug, self.event.slug, self.order.code, self.order.secret)
|
||||
)
|
||||
assert response.status_code == 302
|
||||
|
||||
response = self.client.get(
|
||||
'/%s/%s/ticket/%s/%s/%s/' % (self.orga.slug, self.event.slug, self.order.code,
|
||||
self.ticket_pos.positionid, self.ticket_pos.web_secret)
|
||||
)
|
||||
assert response.status_code == 200
|
||||
doc = BeautifulSoup(response.content.decode(), "lxml")
|
||||
assert len(doc.select(".cart-row")) > 0
|
||||
assert "pending" in doc.select(".order-details")[0].text.lower()
|
||||
assert "Peter" in response.content.decode()
|
||||
assert "Lukas" not in response.content.decode()
|
||||
|
||||
def test_require_login_for_order_access_disabled_auth(self):
|
||||
self.orga.settings.customer_accounts = True
|
||||
|
||||
with scopes_disabled():
|
||||
customer = self.orga.customers.create(email='john@example.org', is_verified=True)
|
||||
customer.set_password("foo")
|
||||
customer.save()
|
||||
|
||||
self.order.customer = customer
|
||||
self.order.save()
|
||||
|
||||
self.orga.settings.customer_accounts_require_login_for_order_access = False
|
||||
|
||||
response = self.client.post('/%s/account/login' % (self.orga.slug), {
|
||||
'email': 'john@example.org',
|
||||
'password': 'foo',
|
||||
})
|
||||
assert response.status_code == 302
|
||||
|
||||
response = self.client.get(
|
||||
'/%s/%s/order/%s/%s/' % (self.orga.slug, self.event.slug, self.order.code, self.order.secret)
|
||||
)
|
||||
assert response.status_code == 200
|
||||
doc = BeautifulSoup(response.content.decode(), "lxml")
|
||||
assert len(doc.select(".cart-row")) > 0
|
||||
assert "pending" in doc.select(".order-details")[0].text.lower()
|
||||
assert "Peter" in response.content.decode()
|
||||
assert "Lukas" not in response.content.decode()
|
||||
|
||||
response = self.client.get(
|
||||
'/%s/%s/ticket/%s/%s/%s/' % (self.orga.slug, self.event.slug, self.order.code,
|
||||
self.ticket_pos.positionid, self.ticket_pos.web_secret)
|
||||
)
|
||||
assert response.status_code == 200
|
||||
doc = BeautifulSoup(response.content.decode(), "lxml")
|
||||
assert len(doc.select(".cart-row")) > 0
|
||||
assert "pending" in doc.select(".order-details")[0].text.lower()
|
||||
assert "Peter" in response.content.decode()
|
||||
assert "Lukas" not in response.content.decode()
|
||||
|
||||
def test_require_login_for_order_access_enabled_auth(self):
|
||||
self.orga.settings.customer_accounts = True
|
||||
|
||||
with scopes_disabled():
|
||||
customer = self.orga.customers.create(email='john@example.org', is_verified=True)
|
||||
customer.set_password("foo")
|
||||
customer.save()
|
||||
|
||||
self.order.customer = customer
|
||||
self.order.save()
|
||||
|
||||
self.orga.settings.customer_accounts_require_login_for_order_access = True
|
||||
|
||||
response = self.client.post('/%s/account/login' % (self.orga.slug), {
|
||||
'email': 'john@example.org',
|
||||
'password': 'foo',
|
||||
})
|
||||
assert response.status_code == 302
|
||||
|
||||
response = self.client.get(
|
||||
'/%s/%s/order/%s/%s/' % (self.orga.slug, self.event.slug, self.order.code, self.order.secret)
|
||||
)
|
||||
assert response.status_code == 200
|
||||
doc = BeautifulSoup(response.content.decode(), "lxml")
|
||||
assert len(doc.select(".cart-row")) > 0
|
||||
assert "pending" in doc.select(".order-details")[0].text.lower()
|
||||
assert "Peter" in response.content.decode()
|
||||
assert "Lukas" not in response.content.decode()
|
||||
|
||||
response = self.client.get(
|
||||
'/%s/%s/ticket/%s/%s/%s/' % (self.orga.slug, self.event.slug, self.order.code,
|
||||
self.ticket_pos.positionid, self.ticket_pos.web_secret)
|
||||
)
|
||||
assert response.status_code == 200
|
||||
doc = BeautifulSoup(response.content.decode(), "lxml")
|
||||
assert len(doc.select(".cart-row")) > 0
|
||||
assert "pending" in doc.select(".order-details")[0].text.lower()
|
||||
assert "Peter" in response.content.decode()
|
||||
assert "Lukas" not in response.content.decode()
|
||||
|
||||
def test_require_login_for_order_access_accounts_disabled(self):
|
||||
self.orga.settings.customer_accounts = True
|
||||
|
||||
with scopes_disabled():
|
||||
customer = self.orga.customers.create(email='john@example.org', is_verified=True)
|
||||
customer.set_password("foo")
|
||||
customer.save()
|
||||
|
||||
self.order.customer = customer
|
||||
self.order.save()
|
||||
|
||||
self.orga.settings.customer_accounts = False
|
||||
self.orga.settings.customer_accounts_require_login_for_order_access = True
|
||||
|
||||
response = self.client.get(
|
||||
'/%s/%s/order/%s/%s/' % (self.orga.slug, self.event.slug, self.order.code, self.order.secret)
|
||||
)
|
||||
assert response.status_code == 200
|
||||
doc = BeautifulSoup(response.content.decode(), "lxml")
|
||||
assert len(doc.select(".cart-row")) > 0
|
||||
assert "pending" in doc.select(".order-details")[0].text.lower()
|
||||
assert "Peter" in response.content.decode()
|
||||
assert "Lukas" not in response.content.decode()
|
||||
|
||||
def test_require_login_for_order_access_enabled_wrong_customer(self):
|
||||
self.orga.settings.customer_accounts = True
|
||||
|
||||
with scopes_disabled():
|
||||
customer = self.orga.customers.create(email='john@example.org', is_verified=True)
|
||||
customer.set_password("foo")
|
||||
customer.save()
|
||||
|
||||
self.order.customer = customer
|
||||
self.order.save()
|
||||
|
||||
with scopes_disabled():
|
||||
customer = self.orga.customers.create(email='jill@example.org', is_verified=True)
|
||||
customer.set_password("bar")
|
||||
customer.save()
|
||||
|
||||
self.orga.settings.customer_accounts_require_login_for_order_access = True
|
||||
|
||||
response = self.client.post('/%s/account/login' % (self.orga.slug), {
|
||||
'email': 'jill@example.org',
|
||||
'password': 'bar',
|
||||
})
|
||||
assert response.status_code == 302
|
||||
|
||||
response = self.client.get(
|
||||
'/%s/%s/order/%s/%s/' % (self.orga.slug, self.event.slug, self.order.code, self.order.secret)
|
||||
)
|
||||
assert response.status_code == 404
|
||||
|
||||
def test_require_login_for_order_access_enabled_unverified_account(self):
|
||||
self.orga.settings.customer_accounts = True
|
||||
|
||||
with scopes_disabled():
|
||||
customer = self.orga.customers.create(email='john@example.org', is_verified=False)
|
||||
customer.set_password("foo")
|
||||
customer.save()
|
||||
|
||||
self.order.customer = customer
|
||||
self.order.save()
|
||||
|
||||
self.orga.settings.customer_accounts_require_login_for_order_access = True
|
||||
|
||||
response = self.client.get(
|
||||
'/%s/%s/order/%s/%s/' % (self.orga.slug, self.event.slug, self.order.code, self.order.secret)
|
||||
)
|
||||
assert response.status_code == 200
|
||||
doc = BeautifulSoup(response.content.decode(), "lxml")
|
||||
assert len(doc.select(".cart-row")) > 0
|
||||
assert "pending" in doc.select(".order-details")[0].text.lower()
|
||||
assert "Peter" in response.content.decode()
|
||||
assert "Lukas" not in response.content.decode()
|
||||
|
||||
Reference in New Issue
Block a user