Compare commits

...
Author SHA1 Message Date
Raphael Michel a362f4ad3b Revert "Redesign of email settings (#2426)"
This reverts commit e3c7cd7c6d.
2022-01-26 15:50:41 +01:00
Raphael Michel 6f30c347c0 [SECURITY] Make redirect view dependent on referer 2022-01-26 13:41:02 +01:00
Raphael Michel 3596fa9c5a [SECURITY] Fix (non-exploitable) XSS issue 2022-01-26 13:41:02 +01:00
Raphael MichelandFelix Rindt e3c7cd7c6d Redesign of email settings (#2426)
Co-authored-by: Felix Rindt <felix@rindt.me>
2022-01-26 12:47:58 +01:00
Raphael Michel 194042dca5 Add-on selection: Fix incorrect pre-selection across multiple base positions 2022-01-26 09:45:44 +01:00
Raphael Michel 3be6e83f33 Add missing license header 2022-01-25 21:08:28 +01:00
Raphael Michel 4262bce2b5 Limit maximum length of passwords to 4096 characters 2022-01-25 17:24:48 +01:00
Raphael Michel 73ab962e16 Respect language headers on error 400/404/500 pages 2022-01-25 16:59:30 +01:00
Raphael Michel 13a86fc6f3 Event ical feed: Do not show events more than 31 days in the past 2022-01-24 15:47:04 +01:00
Raphael Michel 9d6f11718a Work around performance issue in vobject library 2022-01-24 15:46:48 +01:00
Raphael Michel c9d3428996 Extend check_order_transactions by number of tickets 2022-01-22 22:00:35 +01:00
Felix Schäfer d4ef16b31a Fix #2320 - Move file upload "required" attrs manipulation from init to rendering (#2399) 2022-01-21 15:49:24 +01:00
Yuriko Matsunami 6a35e7d3cd Translated on translate.pretix.eu (Japanese)
Currently translated at 97.0% (167 of 172 strings)

Translation: pretix/pretix (frontend)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/ja/

powered by weblate
2022-01-21 15:49:03 +01:00
DJG Bayern 463443d606 Translations: Update Japanese
Currently translated at 0.1% (8 of 4582 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/ja/

powered by weblate
2022-01-21 15:49:03 +01:00
Raphael Michelandser8phin 6f0da5c2ca TaxRules: Add internal_name and keep_gross_if_rate_changes (#2422)
Co-authored-by: ser8phin <eva.wolkwitz@gmx.de>
2022-01-21 15:39:27 +01:00
ser8phinandRaphael Michel c1344422a5 Remove disabled attribute on checkbox (#2423)
Co-authored-by: Raphael Michel <michel@rami.io>
2022-01-19 21:38:14 +01:00
Raphael Michel c2bd3dde44 GitHub actions: Do not run on 3.10 yet (too many warnings) 2022-01-19 17:12:15 +01:00
Raphael Michel 9e51736232 Fix GitHub actions scripts (No YAML, Python 3.10 is not 3.1) 2022-01-19 17:01:42 +01:00
Raphael Michel 5b27ce1265 Stop testing Python 3.6 on CI 2022-01-19 17:00:24 +01:00
Raphael Michel 0757542f4f Drop Python 3.6 compatibility 2022-01-19 16:49:19 +01:00
Raphael Michel 12be98c888 Update Pillow to 9.* 2022-01-19 16:46:43 +01:00
Raphael Michel 51e6b02aa9 Docs: Remove mention of local cache backend 2022-01-19 15:24:44 +01:00
Raphael Michel acc4a167b1 Event series calendar: Fix incorrect show_names heuristic 2022-01-19 14:58:30 +01:00
Richard Schreiber dd9429bbfa Fix: phone being "None" or format not recognized in checkout (#2420) 2022-01-18 12:27:57 +01:00
Richard Schreiber 768bb8c106 Add phone number to customer profile (Z#178346) (#2414) 2022-01-18 11:38:32 +01:00
Raphael Michel cbdafac999 Web check-in: Fix search 2022-01-17 14:55:16 +01:00
Raphael Michel 96f694cf61 Translations: Update German (informal) (de_Informal)
Currently translated at 99.9% (4580 of 4582 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de_Informal/

powered by weblate
2022-01-14 16:12:13 +01:00
Raphael Michel 5576829ebf Translations: Update German
Currently translated at 100.0% (4582 of 4582 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/de/

powered by weblate
2022-01-14 16:12:13 +01:00
Raphael Michel b0d67e92ac Update po files
[CI skip]

Signed-off-by: Raphael Michel <michel@rami.io>
2022-01-14 15:33:22 +01:00
Yuriko Matsunami 63e28723d2 Translated on translate.pretix.eu (Japanese)
Currently translated at 73.2% (126 of 172 strings)

Translation: pretix/pretix (frontend)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/ja/

powered by weblate
2022-01-14 14:51:58 +01:00
Mikkel Ricky cc0656f169 Translations: Update Danish
Currently translated at 35.3% (1613 of 4565 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/da/

powered by weblate
2022-01-14 14:51:58 +01:00
ser8phin 849c8e719a Fix #555 -- Preselect a single required add-on (#2395) 2022-01-14 14:46:04 +01:00
Raphael Michel a3ec2a4061 Clarify help text of invoice_address_custom_field 2022-01-14 14:42:42 +01:00
Raphael Michel 00a7187a7a Duplicate line break before invoice deadline 2022-01-13 16:45:15 +01:00
Richard Schreiber 701c4f768e Improve add-to-cart checkbox for items with max. 1 per order (Z#178704) (#2413) 2022-01-12 17:10:00 +01:00
Aya Yabuki cf751d38d2 Translated on translate.pretix.eu (Japanese)
Currently translated at 16.8% (29 of 172 strings)

Translation: pretix/pretix (frontend)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/ja/

powered by weblate
2022-01-12 16:21:14 +01:00
Aya Yabuki 888402a4bf Translated on translate.pretix.eu (Japanese)
Currently translated at 16.8% (29 of 172 strings)

Translation: pretix/pretix (frontend)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/ja/

powered by weblate
2022-01-12 16:21:14 +01:00
Aya Yabuki 1134f610fd Translated on translate.pretix.eu (Japanese)
Currently translated at 8.7% (15 of 172 strings)

Translation: pretix/pretix (frontend)
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix-js/ja/

powered by weblate
2022-01-12 16:21:14 +01:00
Raphael Michel 8ae4304c7d Add workaround for https://github.com/getsentry/responses/issues/464 2022-01-12 10:19:02 +01:00
Raphael Michel 357092ec44 API: Add InvoiceLine.subevent (#2411) 2022-01-10 14:11:06 +01:00
Raphael Michel 70a5c76d79 Allow tax rules to trigger approval requirement (#2409) 2022-01-10 14:10:51 +01:00
ser8phin 7a4db8ea23 Add approval requirement option to product variations (#2381) 2022-01-05 18:04:12 +01:00
Raphael Michel 223b160c0c Fix booked add-ons being hidden in order change due to hide_sold_out 2022-01-05 17:58:21 +01:00
Raphael Michel 30c1771d29 Thumbnail: Support for paletted PNG files 2022-01-04 16:26:13 +01:00
Raphael Michel b3b7b9bbab Optimize rendering of very large calendars (#2406) 2022-01-04 10:48:48 +01:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> be040cd6ea Bump @babel/core from 7.16.0 to 7.16.7 in /src/pretix/static/npm_dir (#2401)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-04 10:33:51 +01:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> c6665ec2e6 Bump @rollup/plugin-node-resolve from 13.0.6 to 13.1.2 in /src/pretix/static/npm_dir (#2403)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-04 10:30:57 +01:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> fd16ef1e4d Bump rollup from 2.60.2 to 2.62.0 in /src/pretix/static/npm_dir (#2402)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-04 10:30:51 +01:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 39557fc452 Bump @babel/preset-env from 7.16.4 to 7.16.7 in /src/pretix/static/npm_dir (#2404)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-04 10:30:44 +01:00
cpoisnel 408397a639 Translations: Update French
Currently translated at 48.8% (2229 of 4565 strings)

Translation: pretix/pretix
Translate-URL: https://translate.pretix.eu/projects/pretix/pretix/fr/

powered by weblate
2022-01-04 10:30:34 +01:00
Raphael Michel d4a2500204 Check-in list PDF: Escape HTML tags in names 2022-01-03 12:41:37 +01:00
Raphael Michel e74d9e56cf Waiting list: Explain that you only get one ticket 2022-01-03 10:43:13 +01:00
Raphael Michel f3767ab4ac Gift card: Log user who triggered reversal of transaction 2022-01-03 10:39:05 +01:00
Raphael Michel 5d13f5f885 Gift cards: Fix incorrect handling of return key 2022-01-03 10:38:54 +01:00
Raphael Michel 451d3fce05 Cookie consent: Fix crash without localStorage again 2021-12-22 10:29:27 +01:00
Raphael Michel ccb61e0f56 Docs: Fix dead external link 2021-12-21 11:45:34 +01:00
Richard Schreiber b6273adc57 Calendar-View: add short_month_day_format for week-views (#2392) 2021-12-21 11:19:58 +01:00
155 changed files with 57144 additions and 51801 deletions
+6 -6
View File
@@ -18,17 +18,17 @@ jobs:
name: Tests
strategy:
matrix:
python-version: [3.6, 3.7, 3.8]
python-version: ["3.7", "3.8", "3.9"]
database: [sqlite, postgres, mysql]
exclude:
- database: mysql
python-version: 3.7
- database: sqlite
python-version: 3.7
python-version: "3.8"
- database: mysql
python-version: 3.6
python-version: "3.9"
- database: sqlite
python-version: 3.6
python-version: "3.7"
- database: sqlite
python-version: "3.8"
steps:
- uses: actions/checkout@v2
- uses: getong/mariadb-action@v1.1
+1 -1
View File
@@ -282,7 +282,7 @@ You can use an existing memcached server as pretix's caching backend::
``location``
The location of memcached, either a host:port combination or a socket file.
If no memcached is configured, pretix will use Django's built-in local-memory caching method.
If no memcached is configured, pretix will use redis for caching. If neither is configured, pretix will not use any caching.
.. note:: If you use memcached and you deploy pretix across multiple servers, you should use *one*
shared memcached instance, not multiple ones, because cache invalidations would not be
+3 -3
View File
@@ -142,7 +142,7 @@ If you're running MySQL, also install the client library::
(venv)$ pip3 install mysqlclient
Note that you need Python 3.6 or newer. You can find out your Python version using ``python -V``.
Note that you need Python 3.7 or newer. You can find out your Python version using ``python -V``.
We also need to create a data directory::
@@ -259,14 +259,14 @@ The following snippet is an example on how to configure a nginx proxy for pretix
}
location /static/ {
alias /var/pretix/venv/lib/python3.7/site-packages/pretix/static.dist/;
alias /var/pretix/venv/lib/python3.10/site-packages/pretix/static.dist/;
access_log off;
expires 365d;
add_header Cache-Control "public";
}
}
.. note:: Remember to replace the ``python3.7`` in the ``/static/`` path in the config
.. note:: Remember to replace the ``python3.10`` in the ``/static/`` path in the config
above with your python version.
We recommend reading about setting `strong encryption settings`_ for your web server.
+12
View File
@@ -58,6 +58,12 @@ lines list of objects The actual invo
created before this field was introduced as well as for
all lines not created by a product (e.g. a shipping or
cancellation fee).
├ subevent integer Event series date ID used to create this line. Note that everything
about the subevent might have changed since the creation
of the invoice. Can be ``null`` for all invoice lines
created before this field was introduced as well as for
all lines not created by a product (e.g. a shipping or
cancellation fee) as well as for all events that are not a series.
├ fee_type string Fee type, e.g. ``shipping``, ``service``, ``payment``,
``cancellation``, ``giftcard``, or ``other. Can be ``null`` for
all invoice lines
@@ -120,6 +126,10 @@ internal_reference string Customer's refe
The attribute ``lines.event_location`` has been added.
.. versionchanged:: 4.6
The attribute ``lines.subevent`` has been added.
Endpoints
---------
@@ -185,6 +195,7 @@ Endpoints
"description": "Budget Ticket",
"item": 1234,
"variation": 245,
"subevent": null,
"fee_type": null,
"fee_internal_type": null,
"event_date_from": "2017-12-27T10:00:00Z",
@@ -274,6 +285,7 @@ Endpoints
"description": "Budget Ticket",
"item": 1234,
"variation": 245,
"subevent": null,
"fee_type": null,
"fee_internal_type": null,
"event_date_from": "2017-12-27T10:00:00Z",
+9
View File
@@ -24,6 +24,9 @@ active boolean If ``false``, t
description multi-lingual string A public description of the variation. May contain
Markdown syntax or can be ``null``.
position integer An integer, used for sorting
require_approval boolean If ``true``, orders with this variation will need to be
approved by the event organizer before they can be
paid.
require_membership boolean If ``true``, booking this variation requires an active membership.
require_membership_hidden boolean If ``true`` and ``require_membership`` is set, this variation will
be hidden from users without a valid membership.
@@ -76,6 +79,7 @@ Endpoints
"en": "S"
},
"active": true,
"require_approval": false,
"require_membership": false,
"require_membership_hidden": false,
"require_membership_types": [],
@@ -97,6 +101,7 @@ Endpoints
"en": "L"
},
"active": true,
"require_approval": false,
"require_membership": false,
"require_membership_hidden": false,
"require_membership_types": [],
@@ -147,6 +152,7 @@ Endpoints
"price": "10.00",
"original_price": null,
"active": true,
"require_approval": false,
"require_membership": false,
"require_membership_hidden": false,
"require_membership_types": [],
@@ -183,6 +189,7 @@ Endpoints
"value": {"en": "Student"},
"default_price": "10.00",
"active": true,
"require_approval": false,
"require_membership": false,
"require_membership_hidden": false,
"require_membership_types": [],
@@ -209,6 +216,7 @@ Endpoints
"price": "10.00",
"original_price": null,
"active": true,
"require_approval": false,
"require_membership": false,
"require_membership_hidden": false,
"require_membership_types": [],
@@ -266,6 +274,7 @@ Endpoints
"price": "10.00",
"original_price": null,
"active": false,
"require_approval": false,
"require_membership": false,
"require_membership_hidden": false,
"require_membership_types": [],
+15
View File
@@ -16,15 +16,22 @@ Field Type Description
===================================== ========================== =======================================================
id integer Internal ID of the tax rule
name multi-lingual string The tax rules' name
internal_name string An optional name that is only used in the backend
rate decimal (string) Tax rate in percent
price_includes_tax boolean If ``true`` (default), tax is assumed to be included in
the specified product price
eu_reverse_charge boolean If ``true``, EU reverse charge rules are applied
home_country string Merchant country (required for reverse charge), can be
``null`` or empty string
keep_gross_if_rate_changes boolean If ``true``, changes of the tax rate based on custom
rules keep the gross price constant (default is ``false``)
===================================== ========================== =======================================================
.. versionchanged:: 4.6
The ``internal_name`` and ``keep_gross_if_rate_changes`` attributes have been added.
Endpoints
---------
@@ -56,9 +63,11 @@ Endpoints
{
"id": 1,
"name": {"en": "VAT"},
"internal_name": "VAT",
"rate": "19.00",
"price_includes_tax": true,
"eu_reverse_charge": false,
"keep_gross_if_rate_changes": false,
"home_country": "DE"
}
]
@@ -94,9 +103,11 @@ Endpoints
{
"id": 1,
"name": {"en": "VAT"},
"internal_name": "VAT",
"rate": "19.00",
"price_includes_tax": true,
"eu_reverse_charge": false,
"keep_gross_if_rate_changes": false,
"home_country": "DE"
}
@@ -140,9 +151,11 @@ Endpoints
{
"id": 1,
"name": {"en": "VAT"},
"internal_name": "VAT",
"rate": "19.00",
"price_includes_tax": true,
"eu_reverse_charge": false,
"keep_gross_if_rate_changes": false,
"home_country": "DE"
}
@@ -185,9 +198,11 @@ Endpoints
{
"id": 1,
"name": {"en": "VAT"},
"internal_name": "VAT",
"rate": "20.00",
"price_includes_tax": true,
"eu_reverse_charge": false,
"keep_gross_if_rate_changes": false,
"home_country": "DE"
}
+1 -1
View File
@@ -203,4 +203,4 @@ Then, please contact support@pretix.eu and we will enable DKIM for your domain o
.. _Sender Policy Framework: https://en.wikipedia.org/wiki/Sender_Policy_Framework
.. _SPF specification: http://www.openspf.org/SPF_Record_Syntax
.. _SPF specification: http://www.open-spf.org/SPF_Record_Syntax
+1 -1
View File
@@ -637,7 +637,7 @@ class SubEventSerializer(I18nAwareModelSerializer):
class TaxRuleSerializer(CountryFieldMixin, I18nAwareModelSerializer):
class Meta:
model = TaxRule
fields = ('id', 'name', 'rate', 'price_includes_tax', 'eu_reverse_charge', 'home_country')
fields = ('id', 'name', 'rate', 'price_includes_tax', 'eu_reverse_charge', 'home_country', 'internal_name', 'keep_gross_if_rate_changes')
class EventSettingsSerializer(SettingsSerializer):
+6 -4
View File
@@ -58,8 +58,9 @@ class InlineItemVariationSerializer(I18nAwareModelSerializer):
class Meta:
model = ItemVariation
fields = ('id', 'value', 'active', 'description',
'position', 'default_price', 'price', 'original_price',
'require_membership', 'require_membership_types', 'require_membership_hidden', 'available_from', 'available_until',
'position', 'default_price', 'price', 'original_price', 'require_approval',
'require_membership', 'require_membership_types',
'require_membership_hidden', 'available_from', 'available_until',
'sales_channels', 'hide_without_voucher',)
def __init__(self, *args, **kwargs):
@@ -74,8 +75,9 @@ class ItemVariationSerializer(I18nAwareModelSerializer):
class Meta:
model = ItemVariation
fields = ('id', 'value', 'active', 'description',
'position', 'default_price', 'price', 'original_price',
'require_membership', 'require_membership_types', 'require_membership_hidden', 'available_from', 'available_until',
'position', 'default_price', 'price', 'original_price', 'require_approval',
'require_membership', 'require_membership_types',
'require_membership_hidden', 'available_from', 'available_until',
'sales_channels', 'hide_without_voucher',)
def __init__(self, *args, **kwargs):
+1 -1
View File
@@ -1426,7 +1426,7 @@ class InlineInvoiceLineSerializer(I18nAwareModelSerializer):
class Meta:
model = InvoiceLine
fields = ('position', 'description', 'item', 'variation', 'attendee_name', 'event_date_from',
fields = ('position', 'description', 'item', 'variation', 'subevent', 'attendee_name', 'event_date_from',
'event_date_to', 'gross_value', 'tax_value', 'tax_rate', 'tax_name', 'fee_type',
'fee_internal_type', 'event_location')
+2 -1
View File
@@ -146,7 +146,8 @@ class NativeAuthBackend(BaseAuthBackend):
d = OrderedDict([
('email', forms.EmailField(label=_("E-mail"), max_length=254,
widget=forms.EmailInput(attrs={'autofocus': 'autofocus'}))),
('password', forms.CharField(label=_("Password"), widget=forms.PasswordInput)),
('password', forms.CharField(label=_("Password"), widget=forms.PasswordInput,
max_length=4096)),
])
return d
+5 -1
View File
@@ -154,6 +154,7 @@ class RegistrationForm(forms.Form):
widget=forms.PasswordInput(attrs={
'autocomplete': 'new-password' # see https://bugs.chromium.org/p/chromium/issues/detail?id=370363#c7
}),
max_length=4096,
required=True
)
password_repeat = forms.CharField(
@@ -161,6 +162,7 @@ class RegistrationForm(forms.Form):
widget=forms.PasswordInput(attrs={
'autocomplete': 'new-password' # see https://bugs.chromium.org/p/chromium/issues/detail?id=370363#c7
}),
max_length=4096,
required=True
)
keep_logged_in = forms.BooleanField(label=_("Keep me logged in"), required=False)
@@ -204,11 +206,13 @@ class PasswordRecoverForm(forms.Form):
password = forms.CharField(
label=_('Password'),
widget=forms.PasswordInput,
max_length=4096,
required=True
)
password_repeat = forms.CharField(
label=_('Repeat password'),
widget=forms.PasswordInput
widget=forms.PasswordInput,
max_length=4096,
)
def __init__(self, user_id=None, *args, **kwargs):
+47 -28
View File
@@ -333,23 +333,41 @@ class WrappedPhoneNumberPrefixWidget(PhoneNumberPrefixWidget):
def guess_country(event):
# Try to guess the initial country from either the country of the merchant
# or the locale. This will hopefully save at least some users some scrolling :)
locale = get_language_without_region()
country = event.settings.region or event.settings.invoice_address_from_country
if not country:
valid_countries = countries.countries
if '-' in locale:
parts = locale.split('-')
# TODO: does this actually work?
if parts[1].upper() in valid_countries:
country = Country(parts[1].upper())
elif parts[0].upper() in valid_countries:
country = Country(parts[0].upper())
else:
if locale.upper() in valid_countries:
country = Country(locale.upper())
country = get_country_by_locale(get_language_without_region())
return country
def get_country_by_locale(locale):
country = None
valid_countries = countries.countries
if '-' in locale:
parts = locale.split('-')
# TODO: does this actually work?
if parts[1].upper() in valid_countries:
country = Country(parts[1].upper())
elif parts[0].upper() in valid_countries:
country = Country(parts[0].upper())
else:
if locale.upper() in valid_countries:
country = Country(locale.upper())
return country
def guess_phone_prefix(event):
with language(get_babel_locale()):
country = str(guess_country(event))
return get_phone_prefix(country)
def get_phone_prefix(country):
for prefix, values in _COUNTRY_CODE_TO_REGION_CODE.items():
if country in values:
return prefix
return None
class QuestionCheckboxSelectMultiple(forms.CheckboxSelectMultiple):
option_template_name = 'pretixbase/forms/widgets/checkbox_option_with_links.html'
@@ -780,25 +798,26 @@ class BaseQuestionsForm(forms.Form):
if q.valid_datetime_max:
field.validators.append(MaxDateTimeValidator(q.valid_datetime_max))
elif q.type == Question.TYPE_PHONENUMBER:
with language(get_babel_locale()):
default_country = guess_country(event)
default_prefix = None
for prefix, values in _COUNTRY_CODE_TO_REGION_CODE.items():
if str(default_country) in values:
default_prefix = prefix
if initial:
try:
initial = PhoneNumber().from_string(initial.answer) if initial else "+{}.".format(default_prefix)
initial = PhoneNumber().from_string(initial.answer)
except NumberParseException:
initial = None
field = PhoneNumberField(
label=label, required=required,
help_text=help_text,
# We now exploit an implementation detail in PhoneNumberPrefixWidget to allow us to pass just
# a country code but no number as an initial value. It's a bit hacky, but should be stable for
# the future.
initial=initial,
widget=WrappedPhoneNumberPrefixWidget()
)
if not initial:
phone_prefix = guess_phone_prefix(event)
if phone_prefix:
initial = "+{}.".format(phone_prefix)
field = PhoneNumberField(
label=label, required=required,
help_text=help_text,
# We now exploit an implementation detail in PhoneNumberPrefixWidget to allow us to pass just
# a country code but no number as an initial value. It's a bit hacky, but should be stable for
# the future.
initial=initial,
widget=WrappedPhoneNumberPrefixWidget()
)
field.question = q
if answers:
# Cache the answer object for later use
+9 -8
View File
@@ -86,14 +86,6 @@ class TimePickerWidget(forms.TimeInput):
class UploadedFileWidget(forms.ClearableFileInput):
def __init__(self, *args, **kwargs):
# Browsers can't recognize that the server already has a file uploaded
# Don't mark this input as being required if we already have an answer
# (this needs to be done via the attrs, otherwise we wouldn't get the "required" star on the field label)
attrs = kwargs.get('attrs', {})
if kwargs.get('required') and kwargs.get('initial'):
attrs.update({'required': None})
kwargs.update({'attrs': attrs})
self.position = kwargs.pop('position')
self.event = kwargs.pop('event')
self.answer = kwargs.pop('answer')
@@ -125,6 +117,15 @@ class UploadedFileWidget(forms.ClearableFileInput):
'answer': self.answer.pk,
})
def get_context(self, name, value, attrs):
# Browsers can't recognize that the server already has a file uploaded
# Don't mark this input as being required if we already have an answer
# (this needs to be done via the attrs, otherwise we wouldn't get the "required" star on the field label)
ctx = super().get_context(name, value, attrs)
if ctx['widget']['is_initial']:
ctx['widget']['attrs']['required'] = False
return ctx
def format_value(self, value):
if self.is_initial(value):
return self.FakeFile(value, self.position, self.event, self.answer)
@@ -23,7 +23,9 @@ from decimal import Decimal
from django.core.management.base import BaseCommand
from django.db import models
from django.db.models import Case, F, OuterRef, Q, Subquery, Sum, Value, When
from django.db.models import (
Case, Count, F, OuterRef, Q, Subquery, Sum, Value, When,
)
from django.db.models.functions import Coalesce
from django_scopes import scopes_disabled
@@ -45,6 +47,18 @@ class Command(BaseCommand):
output_field=models.DecimalField(decimal_places=2, max_digits=10)
), Value(0), output_field=models.DecimalField(decimal_places=2, max_digits=10)
),
position_cnt=Case(
When(Q(status__in=('e', 'c')) | Q(require_approval=True), then=Value(0)),
default=Coalesce(
Subquery(
OrderPosition.objects.filter(
order=OuterRef('pk')
).order_by().values('order').annotate(p=Count('*')).values('p'),
output_field=models.IntegerField()
), Value(0), output_field=models.IntegerField()
),
output_field=models.IntegerField()
),
fee_total=Coalesce(
Subquery(
OrderFee.objects.filter(
@@ -61,6 +75,15 @@ class Command(BaseCommand):
output_field=models.DecimalField(decimal_places=2, max_digits=10)
), Value(0), output_field=models.DecimalField(decimal_places=2, max_digits=10)
),
tx_cnt=Coalesce(
Subquery(
Transaction.objects.filter(
order=OuterRef('pk'),
item__isnull=False,
).order_by().values('order').annotate(p=Sum(F('count'))).values('p'),
output_field=models.DecimalField(decimal_places=2, max_digits=10)
), Value(0), output_field=models.DecimalField(decimal_places=2, max_digits=10)
),
).annotate(
correct_total=Case(
When(Q(status=Order.STATUS_CANCELED) | Q(status=Order.STATUS_EXPIRED) | Q(require_approval=True),
@@ -70,13 +93,15 @@ class Command(BaseCommand):
),
).exclude(
total=F('position_total') + F('fee_total'),
tx_total=F('correct_total')
tx_total=F('correct_total'),
tx_cnt=F('position_cnt')
).select_related('event')
for o in qs:
if abs(o.tx_total - o.correct_total) < Decimal('0.00001') and abs(o.position_total + o.fee_total - o.total) < Decimal('0.00001'):
if abs(o.tx_total - o.correct_total) < Decimal('0.00001') and abs(o.position_total + o.fee_total - o.total) < Decimal('0.00001') \
and o.tx_cnt == o.position_cnt:
# Ignore SQLite which treats Decimals like floats…
continue
print(f"Error in order {o.full_code}: status={o.status}, sum(positions)+sum(fees)={o.position_total + o.fee_total}, "
f"order.total={o.total}, sum(transactions)={o.tx_total}, expected={o.correct_total}")
f"order.total={o.total}, sum(transactions)={o.tx_total}, expected={o.correct_total}, pos_cnt={o.position_cnt}, tx_pos_cnt={o.tx_cnt}")
self.stderr.write(self.style.SUCCESS(f'Check completed.'))
@@ -0,0 +1,18 @@
# Generated by Django 3.2.9 on 2021-12-13 14:21
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('pretixbase', '0204_orderposition_backfill_is_bundled'),
]
operations = [
migrations.AddField(
model_name='itemvariation',
name='require_approval',
field=models.BooleanField(default=False),
),
]
@@ -0,0 +1,19 @@
# Generated by Django 3.2.9 on 2022-01-12 10:59
import phonenumber_field.modelfields
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('pretixbase', '0205_itemvariation_require_approval'),
]
operations = [
migrations.AddField(
model_name='customer',
name='phone',
field=phonenumber_field.modelfields.PhoneNumberField(max_length=128, null=True, region=None),
),
]
@@ -0,0 +1,23 @@
# Generated by Django 3.2.4 on 2022-01-19 14:27
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('pretixbase', '0206_customer_phone'),
]
operations = [
migrations.AddField(
model_name='taxrule',
name='internal_name',
field=models.CharField(max_length=190, null=True),
),
migrations.AddField(
model_name='taxrule',
name='keep_gross_if_rate_changes',
field=models.BooleanField(default=False),
),
]
+3
View File
@@ -29,6 +29,7 @@ from django.db.models import F, Q
from django.utils.crypto import get_random_string, salted_hmac
from django.utils.translation import gettext_lazy as _, pgettext_lazy
from django_scopes import ScopedManager, scopes_disabled
from phonenumber_field.modelfields import PhoneNumberField
from pretix.base.banlist import banned
from pretix.base.models.base import LoggedModel
@@ -45,6 +46,7 @@ class Customer(LoggedModel):
organizer = models.ForeignKey(Organizer, related_name='customers', on_delete=models.CASCADE)
identifier = models.CharField(max_length=190, db_index=True, unique=True)
email = models.EmailField(db_index=True, null=True, blank=False, verbose_name=_('E-mail'), max_length=190)
phone = PhoneNumberField(null=True, blank=True, verbose_name=_('Phone number'))
password = models.CharField(verbose_name=_('Password'), max_length=128)
name_cached = models.CharField(max_length=255, verbose_name=_('Full name'), blank=True)
name_parts = models.JSONField(default=dict)
@@ -87,6 +89,7 @@ class Customer(LoggedModel):
self.name_parts = {}
self.name_cached = ''
self.email = None
self.phone = None
self.save()
self.all_logentries().update(data={}, shredded=True)
self.orders.all().update(customer=None)
+11 -1
View File
@@ -764,6 +764,9 @@ class ItemVariation(models.Model):
:type default_price: decimal.Decimal
:param original_price: The item's "original" price. Will not be used for any calculations, will just be shown.
:type original_price: decimal.Decimal
:param require_approval: If set to ``True``, orders containing this variation can only be processed and paid after
approval by an administrator
:type require_approval: bool
"""
item = models.ForeignKey(
Item,
@@ -799,6 +802,13 @@ class ItemVariation(models.Model):
help_text=_('If set, this will be displayed next to the current price to show that the current price is a '
'discounted one. This is just a cosmetic setting and will not actually impact pricing.')
)
require_approval = models.BooleanField(
verbose_name=_('Require approval'),
default=False,
help_text=_('If this variation is part of an order, the order will be put into an "approval" state and '
'will need to be confirmed by you before it can be paid and completed. You can use this e.g. for '
'discounted tickets that are only available to specific groups.'),
)
require_membership = models.BooleanField(
verbose_name=_('Require a valid membership'),
default=False,
@@ -832,7 +842,7 @@ class ItemVariation(models.Model):
blank=True,
)
hide_without_voucher = models.BooleanField(
verbose_name=_('This variation will only be shown if a voucher matching the product is redeemed.'),
verbose_name=_('Show only if a matching voucher is redeemed.'),
default=False,
help_text=_('This variation will be hidden from the event page until the user enters a voucher '
'that unlocks this variation.')
+9
View File
@@ -1442,6 +1442,15 @@ class AbstractPosition(models.Model):
lines = [r.strip() for r in lines if r]
return '\n'.join(lines).strip()
def requires_approval(self, invoice_address=None):
if self.item.require_approval:
return True
if self.variation and self.variation.require_approval:
return True
if self.item.tax_rule and self.item.tax_rule._require_approval(invoice_address):
return True
return False
class OrderPayment(models.Model):
"""
+41 -8
View File
@@ -81,6 +81,15 @@ class TaxedPrice:
name=self.name,
)
def __eq__(self, other):
return (
self.gross == other.gross and
self.net == other.net and
self.tax == other.tax and
self.rate == other.rate and
self.name == other.name
)
TAXED_ZERO = TaxedPrice(
gross=Decimal('0.00'),
@@ -127,8 +136,13 @@ def cc_to_vat_prefix(country_code):
class TaxRule(LoggedModel):
event = models.ForeignKey('Event', related_name='tax_rules', on_delete=models.CASCADE)
internal_name = models.CharField(
verbose_name=_('Internal name'),
max_length=190,
null=True, blank=True,
)
name = I18nCharField(
verbose_name=_('Name'),
verbose_name=_('Official name'),
help_text=_('Should be short, e.g. "VAT"'),
max_length=190,
)
@@ -141,6 +155,10 @@ class TaxRule(LoggedModel):
verbose_name=_("The configured product prices include the tax amount"),
default=True,
)
keep_gross_if_rate_changes = models.BooleanField(
verbose_name=_("Keep gross amount constant if the tax rate changes based on the invoice address"),
default=False,
)
eu_reverse_charge = models.BooleanField(
verbose_name=_("Use EU reverse charge taxation rules"),
default=False,
@@ -198,6 +216,8 @@ class TaxRule(LoggedModel):
s = _('plus {rate}% {name}').format(rate=self.rate, name=self.name)
if self.eu_reverse_charge:
s += ' ({})'.format(_('reverse charge enabled'))
if self.internal_name:
return f'{self.internal_name} ({s})'
return str(s)
@property
@@ -211,7 +231,7 @@ class TaxRule(LoggedModel):
rule = self.get_matching_rule(invoice_address)
if rule.get('action', 'vat') == 'block':
raise self.SaleNotAllowed()
if rule.get('action', 'vat') == 'vat' and rule.get('rate') is not None:
if rule.get('action', 'vat') in ('vat', 'require_approval') and rule.get('rate') is not None:
return Decimal(rule.get('rate'))
return Decimal(self.rate)
@@ -228,13 +248,19 @@ class TaxRule(LoggedModel):
rate = override_tax_rate
elif invoice_address:
adjust_rate = self.tax_rate_for(invoice_address)
if (adjust_rate == gross_price_is_tax_rate or force_fixed_gross_price) and base_price_is == 'gross':
if (adjust_rate == gross_price_is_tax_rate or force_fixed_gross_price or self.keep_gross_if_rate_changes) and base_price_is == 'gross':
rate = adjust_rate
elif adjust_rate != rate:
normal_price = self.tax(base_price, base_price_is, currency, subtract_from_gross=subtract_from_gross)
base_price = normal_price.net
base_price_is = 'net'
subtract_from_gross = Decimal('0.00')
if self.keep_gross_if_rate_changes:
normal_price = self.tax(base_price, base_price_is, currency, subtract_from_gross=subtract_from_gross)
base_price = normal_price.gross
base_price_is = 'gross'
subtract_from_gross = Decimal('0.00')
else:
normal_price = self.tax(base_price, base_price_is, currency, subtract_from_gross=subtract_from_gross)
base_price = normal_price.net
base_price_is = 'net'
subtract_from_gross = Decimal('0.00')
rate = adjust_rate
if rate == Decimal('0.00'):
@@ -337,12 +363,19 @@ class TaxRule(LoggedModel):
return False
def _require_approval(self, invoice_address):
if self._custom_rules:
rule = self.get_matching_rule(invoice_address)
if rule.get('action', 'vat') == 'require_approval':
return True
return False
def _tax_applicable(self, invoice_address):
if self._custom_rules:
rule = self.get_matching_rule(invoice_address)
if rule.get('action', 'vat') == 'block':
raise self.SaleNotAllowed()
return rule.get('action', 'vat') == 'vat'
return rule.get('action', 'vat') in ('vat', 'require_approval')
if not self.eu_reverse_charge:
# No reverse charge rules? Always apply VAT!
+7 -6
View File
@@ -426,10 +426,10 @@ class CartManager:
if not cp.includes_tax:
price = self._get_price(cp.item, cp.variation, cp.voucher, cp.price, cp.subevent,
cp_is_net=True, bundled_sum=bundled_sum)
price = TaxedPrice(net=price.net, gross=price.net, rate=0, tax=0, name='')
price = TaxedPrice(net=price.net, gross=price.net, rate=Decimal('0'), tax=Decimal('0'), name='')
pbv = self._get_price(cp.item, cp.variation, None, cp.price, cp.subevent,
cp_is_net=True, bundled_sum=bundled_sum)
pbv = TaxedPrice(net=pbv.net, gross=pbv.net, rate=0, tax=0, name='')
pbv = TaxedPrice(net=pbv.net, gross=pbv.net, rate=Decimal('0'), tax=Decimal('0'), name='')
else:
price = self._get_price(cp.item, cp.variation, cp.voucher, cp.price, cp.subevent,
bundled_sum=bundled_sum)
@@ -1106,10 +1106,11 @@ def update_tax_rates(event: Event, cart_id: str, invoice_address: InvoiceAddress
rate = pos.item.tax_rule.tax_rate_for(invoice_address)
if pos.tax_rate != rate:
current_net = pos.price - pos.tax_value
new_gross = pos.item.tax(current_net, base_price_is='net', invoice_address=invoice_address).gross
totaldiff += new_gross - pos.price
pos.price = new_gross
if not pos.item.tax_rule.keep_gross_if_rate_changes:
current_net = pos.price - pos.tax_value
new_gross = pos.item.tax(current_net, base_price_is='net', invoice_address=invoice_address).gross
totaldiff += new_gross - pos.price
pos.price = new_gross
pos.includes_tax = rate != Decimal('0.00')
pos.override_tax_rate = rate
pos.save(update_fields=['price', 'includes_tax', 'override_tax_rate'])
+1 -1
View File
@@ -102,7 +102,7 @@ def build_invoice(invoice: Invoice) -> Invoice:
payment = ""
if invoice.event.settings.invoice_include_expire_date and invoice.order.status == Order.STATUS_PENDING:
if payment:
payment += "<br />"
payment += "<br /><br />"
payment += pgettext("invoice", "Please complete your payment before {expire_date}.").format(
expire_date=date_format(invoice.order.expires, "SHORT_DATE_FORMAT")
)
+3 -3
View File
@@ -700,7 +700,7 @@ def _check_positions(event: Event, now_dt: datetime, positions: List[CartPositio
invoice_address=address, force_custom_price=True, max_discount=max_discount)
changed_prices[cp.pk] = bprice
else:
bundled_sum = 0
bundled_sum = Decimal('0.00')
if not cp.addon_to_id:
for bundledp in cp.addons.all():
if bundledp.is_bundled:
@@ -856,7 +856,7 @@ def _create_order(event: Event, email: str, positions: List[CartPosition], now_d
total=total,
testmode=True if sales_channel.testmode_supported and event.testmode else False,
meta_info=json.dumps(meta_info or {}),
require_approval=any(p.item.require_approval for p in positions),
require_approval=any(p.requires_approval(invoice_address=address) for p in positions),
sales_channel=sales_channel.identifier,
customer=customer,
)
@@ -2071,7 +2071,7 @@ class OrderChangeManager:
split_order.code = None
split_order.datetime = now()
split_order.secret = generate_secret()
split_order.require_approval = self.order.require_approval and any(p.item.require_approval for p in split_positions)
split_order.require_approval = self.order.require_approval and any(p.requires_approval(invoice_address=self._invoice_address) for p in split_positions)
split_order.save()
split_order.log_action('pretix.event.order.changed.split_from', user=self.user, auth=self.auth, data={
'original_order': self.order.code
+21 -18
View File
@@ -113,10 +113,8 @@ class QuotaAvailability:
be a few minutes outdated. In this case, you may not rely on the results in the ``count_*`` properties.
"""
now_dt = now_dt or now()
quotas = list(set(self._queue))
quotas_original = list(self._queue)
self._queue.clear()
if not quotas:
quota_ids_set = {q.id for q in self._queue}
if not quota_ids_set:
return
if allow_cache:
@@ -129,7 +127,7 @@ class QuotaAvailability:
elif settings.HAS_REDIS:
rc = get_redis_connection("redis")
quotas_by_event = defaultdict(list)
for q in quotas_original:
for q in [_q for _q in self._queue if _q.id in quota_ids_set]:
quotas_by_event[q.event_id].append(q)
for eventid, evquotas in quotas_by_event.items():
@@ -139,16 +137,19 @@ class QuotaAvailability:
data = [rv for rv in redisval.decode().split(',')]
# Except for some rare situations, we don't want to use cache entries older than 2 minutes
if time.time() - int(data[2]) < 120 or allow_cache_stale:
quotas_original.remove(q)
quotas.remove(q)
quota_ids_set.remove(q.id)
if data[1] == "None":
self.results[q] = int(data[0]), None
else:
self.results[q] = int(data[0]), int(data[1])
if not quotas:
if not quota_ids_set:
return
quotas = [_q for _q in self._queue if _q.id in quota_ids_set]
quotas_original = list(quotas)
self._queue.clear()
self._compute(quotas, now_dt)
for q in quotas_original:
@@ -284,15 +285,16 @@ class QuotaAvailability:
seq = Q(subevent_id__in=subevents)
if None in subevents:
seq |= Q(subevent__isnull=True)
quota_ids = {q.pk for q in quotas}
op_lookup = OrderPosition.objects.filter(
order__status__in=[Order.STATUS_PAID, Order.STATUS_PENDING],
order__event_id__in=events,
).filter(seq).filter(
Q(
Q(variation_id__isnull=True) &
Q(item_id__in={i['item_id'] for i in q_items if self._quota_objects[i['quota_id']] in quotas})
Q(item_id__in={i['item_id'] for i in q_items if i['quota_id'] in quota_ids})
) | Q(
variation_id__in={i['itemvariation_id'] for i in q_vars if self._quota_objects[i['quota_id']] in quotas})
variation_id__in={i['itemvariation_id'] for i in q_vars if i['quota_id'] in quota_ids})
).order_by()
if any(q.release_after_exit for q in quotas):
op_lookup = op_lookup.annotate(
@@ -359,6 +361,7 @@ class QuotaAvailability:
func = 'GREATEST'
subevents = {q.subevent_id for q in quotas}
quota_ids = {q.pk for q in quotas}
seq = Q(subevent_id__in=subevents)
if None in subevents:
seq |= Q(subevent__isnull=True)
@@ -370,10 +373,9 @@ class QuotaAvailability:
Q(
Q(
Q(variation_id__isnull=True) &
Q(item_id__in={i['item_id'] for i in q_items if self._quota_objects[i['quota_id']] in quotas})
Q(item_id__in={i['item_id'] for i in q_items if i['quota_id'] in quota_ids})
) | Q(
variation_id__in={i['itemvariation_id'] for i in q_vars if
self._quota_objects[i['quota_id']] in quotas}
variation_id__in={i['itemvariation_id'] for i in q_vars if i['quota_id'] in quota_ids}
) | Q(
quota_id__in=[q.pk for q in quotas]
)
@@ -398,6 +400,7 @@ class QuotaAvailability:
def _compute_carts(self, quotas, q_items, q_vars, size_left, now_dt):
events = {q.event_id for q in quotas}
subevents = {q.subevent_id for q in quotas}
quota_ids = {q.pk for q in quotas}
seq = Q(subevent_id__in=subevents)
if None in subevents:
seq |= Q(subevent__isnull=True)
@@ -413,9 +416,9 @@ class QuotaAvailability:
Q(
Q(
Q(variation_id__isnull=True) &
Q(item_id__in={i['item_id'] for i in q_items if self._quota_objects[i['quota_id']] in quotas})
Q(item_id__in={i['item_id'] for i in q_items if i['quota_id'] in quota_ids})
) | Q(
variation_id__in={i['itemvariation_id'] for i in q_vars if self._quota_objects[i['quota_id']] in quotas}
variation_id__in={i['itemvariation_id'] for i in q_vars if i['quota_id'] in quota_ids}
)
)
).order_by().values('item_id', 'subevent_id', 'variation_id').annotate(c=Count('*'))
@@ -434,6 +437,7 @@ class QuotaAvailability:
def _compute_waitinglist(self, quotas, q_items, q_vars, size_left):
events = {q.event_id for q in quotas}
subevents = {q.subevent_id for q in quotas}
quota_ids = {q.pk for q in quotas}
seq = Q(subevent_id__in=subevents)
if None in subevents:
seq |= Q(subevent__isnull=True)
@@ -444,9 +448,8 @@ class QuotaAvailability:
Q(
Q(
Q(variation_id__isnull=True) &
Q(item_id__in={i['item_id'] for i in q_items if self._quota_objects[i['quota_id']] in quotas})
) | Q(variation_id__in={i['itemvariation_id'] for i in q_vars if
self._quota_objects[i['quota_id']] in quotas})
Q(item_id__in={i['item_id'] for i in q_items if i['quota_id'] in quota_ids})
) | Q(variation_id__in={i['itemvariation_id'] for i in q_vars if i['quota_id'] in quota_ids})
)
).order_by().values('item_id', 'subevent_id', 'variation_id').annotate(c=Count('*'))
for line in w_lookup:
+3 -2
View File
@@ -372,11 +372,12 @@ DEFAULTS = {
'form_class': I18nFormField,
'serializer_class': I18nField,
'form_kwargs': dict(
label=_("Custom address field"),
label=_("Custom recipient field"),
widget=I18nTextInput,
help_text=_("If you want to add a custom text field, e.g. for a country-specific registration number, to "
"your invoice address form, please fill in the label here. This label will both be used for "
"asking the user to input their details as well as for displaying the value on the invoice. "
"asking the user to input their details as well as for displaying the value on the invoice. It will "
"be shown on the invoice below the headline. "
"The field will not be required.")
)
},
@@ -0,0 +1,26 @@
{% extends "error.html" %}
{% load i18n %}
{% load rich_text %}
{% load static %}
{% block title %}{% trans "Redirect" %}{% endblock %}
{% block content %}
<i class="fa fa-link fa-fw big-icon"></i>
<div class="error-details">
<h1>{% trans "Redirect" %}</h1>
<h3>
{% blocktrans trimmed with host="<strong>"|add:hostname|add:"</strong>"|safe %}
The link you clicked on wants to redirect you to a destination on the website {{ host }}.
{% endblocktrans %}
{% blocktrans trimmed %}
Please only proceed if you trust this website to be safe.
{% endblocktrans %}
</h3>
<p>
<a href="{{ url }}" class="btn btn-primary btn-lg">
{% blocktrans trimmed with host=hostname %}
Proceed to {{ host }}
{% endblocktrans %}
</a>
</p>
</div>
{% endblock %}
+70 -52
View File
@@ -30,67 +30,85 @@ from django.utils.translation import gettext as _
from django.views.decorators.csrf import requires_csrf_token
from sentry_sdk import last_event_id
from pretix.base.i18n import language
from pretix.base.middleware import get_language_from_request
def csrf_failure(request, reason=""):
t = get_template('csrffail.html')
c = {
'reason': reason,
'no_referer': reason == REASON_NO_REFERER,
'no_referer1': _(
"You are seeing this message because this HTTPS site requires a "
"'Referer header' to be sent by your Web browser, but none was "
"sent. This header is required for security reasons, to ensure "
"that your browser is not being hijacked by third parties."),
'no_referer2': _(
"If you have configured your browser to disable 'Referer' headers, "
"please re-enable them, at least for this site, or for HTTPS "
"connections, or for 'same-origin' requests."),
'no_cookie': reason == REASON_NO_CSRF_COOKIE,
'no_cookie1': _(
"You are seeing this message because this site requires a CSRF "
"cookie when submitting forms. This cookie is required for "
"security reasons, to ensure that your browser is not being "
"hijacked by third parties."),
'no_cookie2': _(
"If you have configured your browser to disable cookies, please "
"re-enable them, at least for this site, or for 'same-origin' "
"requests."),
}
return HttpResponseForbidden(t.render(c), content_type='text/html')
try:
locale = get_language_from_request(request)
except:
locale = "en"
with language(locale): # Middleware might not have run, need to do this manually
t = get_template('csrffail.html')
c = {
'reason': reason,
'no_referer': reason == REASON_NO_REFERER,
'no_referer1': _(
"You are seeing this message because this HTTPS site requires a "
"'Referer header' to be sent by your Web browser, but none was "
"sent. This header is required for security reasons, to ensure "
"that your browser is not being hijacked by third parties."),
'no_referer2': _(
"If you have configured your browser to disable 'Referer' headers, "
"please re-enable them, at least for this site, or for HTTPS "
"connections, or for 'same-origin' requests."),
'no_cookie': reason == REASON_NO_CSRF_COOKIE,
'no_cookie1': _(
"You are seeing this message because this site requires a CSRF "
"cookie when submitting forms. This cookie is required for "
"security reasons, to ensure that your browser is not being "
"hijacked by third parties."),
'no_cookie2': _(
"If you have configured your browser to disable cookies, please "
"re-enable them, at least for this site, or for 'same-origin' "
"requests."),
}
return HttpResponseForbidden(t.render(c), content_type='text/html')
@requires_csrf_token
def page_not_found(request, exception):
exception_repr = exception.__class__.__name__
# Try to get an "interesting" exception message, if any (and not the ugly
# Resolver404 dictionary)
try:
message = exception.args[0]
except (AttributeError, IndexError):
pass
else:
if isinstance(message, (str, Promise)):
exception_repr = str(message)
context = {
'request_path': request.path,
'exception': exception_repr,
}
template = get_template('404.html')
body = template.render(context, request)
r = HttpResponseNotFound(body)
r.xframe_options_exempt = True
return r
locale = get_language_from_request(request)
except:
locale = "en"
with language(locale): # Middleware might not have run, need to do this manually
exception_repr = exception.__class__.__name__
# Try to get an "interesting" exception message, if any (and not the ugly
# Resolver404 dictionary)
try:
message = exception.args[0]
except (AttributeError, IndexError):
pass
else:
if isinstance(message, (str, Promise)):
exception_repr = str(message)
context = {
'request_path': request.path,
'exception': exception_repr,
}
template = get_template('404.html')
body = template.render(context, request)
r = HttpResponseNotFound(body)
r.xframe_options_exempt = True
return r
@requires_csrf_token
def server_error(request):
try:
template = loader.get_template('500.html')
except TemplateDoesNotExist:
return HttpResponseServerError('<h1>Server Error (500)</h1>', content_type='text/html')
r = HttpResponseServerError(template.render({
'request': request,
'sentry_event_id': last_event_id(),
}))
r.xframe_options_exempt = True
return r
locale = get_language_from_request(request)
except:
locale = "en"
with language(locale): # Middleware might not have run, need to do this manually
try:
template = loader.get_template('500.html')
except TemplateDoesNotExist:
return HttpResponseServerError('<h1>Server Error (500)</h1>', content_type='text/html')
r = HttpResponseServerError(template.render({
'request': request,
'sentry_event_id': last_event_id(),
}))
r.xframe_options_exempt = True
return r
+23
View File
@@ -24,6 +24,21 @@ import urllib.parse
from django.core import signing
from django.http import HttpResponseBadRequest, HttpResponseRedirect
from django.urls import reverse
from django.shortcuts import render
def _is_samesite_referer(request):
referer = request.META.get('HTTP_REFERER')
if referer is None:
return False
referer = urllib.parse.urlparse(referer)
# Make sure we have a valid URL for Referer.
if '' in (referer.scheme, referer.netloc):
return False
return (referer.scheme, referer.netloc) == (request.scheme, request.get_host())
def redir_view(request):
@@ -32,6 +47,14 @@ def redir_view(request):
url = signer.unsign(request.GET.get('url', ''))
except signing.BadSignature:
return HttpResponseBadRequest('Invalid parameter')
if not _is_samesite_referer(request):
u = urllib.parse.urlparse(url)
return render(request, 'pretixbase/redirect.html', {
'hostname': u.hostname,
'url': url,
})
r = HttpResponseRedirect(url)
r['X-Robots-Tag'] = 'noindex'
return r
+2 -1
View File
@@ -1215,6 +1215,7 @@ class TaxRuleLineForm(I18nForm):
('reverse', _('Reverse charge')),
('no', _('No VAT')),
('block', _('Sale not allowed')),
('require_approval', _('Order requires approval')),
],
)
rate = forms.DecimalField(
@@ -1248,7 +1249,7 @@ TaxRuleLineFormSet = formset_factory(
class TaxRuleForm(I18nModelForm):
class Meta:
model = TaxRule
fields = ['name', 'rate', 'price_includes_tax', 'eu_reverse_charge', 'home_country']
fields = ['name', 'rate', 'price_includes_tax', 'eu_reverse_charge', 'home_country', 'internal_name', 'keep_gross_if_rate_changes']
class WidgetCodeForm(forms.Form):
+1
View File
@@ -713,6 +713,7 @@ class ItemVariationForm(I18nModelForm):
'default_price',
'original_price',
'description',
'require_approval',
'require_membership',
'require_membership_hidden',
'require_membership_types',
+1 -1
View File
@@ -452,7 +452,7 @@ class OrderPositionChangeForm(forms.Form):
@staticmethod
def taxrule_label_from_instance(obj):
return f"{obj.name} ({obj.rate} %)"
return f"{obj.internal_name or obj.name} ({obj.rate} %)"
def __init__(self, *args, **kwargs):
instance = kwargs.pop('instance')
+16 -2
View File
@@ -44,12 +44,16 @@ from django.utils.safestring import mark_safe
from django.utils.translation import gettext_lazy as _, pgettext_lazy
from django_scopes.forms import SafeModelMultipleChoiceField
from i18nfield.forms import I18nFormField, I18nTextarea
from phonenumber_field.formfields import PhoneNumberField
from pytz import common_timezones
from pretix.api.models import WebHook
from pretix.api.webhooks import get_all_webhook_events
from pretix.base.forms import I18nModelForm, PlaceholderValidator, SettingsForm
from pretix.base.forms.questions import NamePartsFormField
from pretix.base.forms.questions import (
NamePartsFormField, WrappedPhoneNumberPrefixWidget, get_country_by_locale,
get_phone_prefix,
)
from pretix.base.forms.widgets import SplitDateTimePickerWidget
from pretix.base.models import (
Customer, Device, EventMetaProperty, Gate, GiftCard, Membership,
@@ -535,11 +539,21 @@ class CustomerUpdateForm(forms.ModelForm):
class Meta:
model = Customer
fields = ['is_active', 'name_parts', 'email', 'is_verified', 'locale']
fields = ['is_active', 'name_parts', 'email', 'is_verified', 'phone', 'locale']
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if not self.instance.phone and (self.instance.organizer.settings.region or self.instance.locale):
country_code = self.instance.organizer.settings.region or get_country_by_locale(self.instance.locale)
phone_prefix = get_phone_prefix(country_code)
if phone_prefix:
self.initial['phone'] = "+{}.".format(phone_prefix)
self.fields['phone'] = PhoneNumberField(
label=_('Phone'),
required=False,
widget=WrappedPhoneNumberPrefixWidget()
)
self.fields['name_parts'] = NamePartsFormField(
max_length=255,
required=False,
@@ -74,17 +74,17 @@
{{ c.datetime|date:"SHORT_DATETIME_FORMAT" }}
{% if c.type == "exit" %}
{% if c.auto_checked_in %}
<span class="fa fa-fw fa-hourglass-end" data-toggle="tooltip_html"
<span class="fa fa-fw fa-hourglass-end" data-toggle="tooltip"
title="{% blocktrans trimmed with date=c.datetime|date:'SHORT_DATETIME_FORMAT' %}Automatically marked not present: {{ date }}{% endblocktrans %}"></span>
{% endif %}
{% elif c.forced and c.successful %}
<span class="fa fa-fw fa-warning" data-toggle="tooltip_html"
<span class="fa fa-fw fa-warning" data-toggle="tooltip"
title="{% blocktrans trimmed with date=c.datetime|date:'SHORT_DATETIME_FORMAT' %}Additional entry scan: {{ date }}{% endblocktrans %}"></span>
{% elif c.forced and not c.successful %}
<br>
<small class="text-muted">{% trans "Failed in offline mode" %}</small>
{% elif c.auto_checked_in %}
<span class="fa fa-fw fa-magic" data-toggle="tooltip_html"
<span class="fa fa-fw fa-magic" data-toggle="tooltip"
title="{% blocktrans trimmed with date=c.datetime|date:'SHORT_DATETIME_FORMAT' %}Automatically checked in: {{ date }}{% endblocktrans %}"></span>
{% endif %}
</td>
@@ -24,6 +24,7 @@
<fieldset>
<legend>{% trans "General" %}</legend>
{% bootstrap_field form.name layout="control" %}
{% bootstrap_field form.internal_name layout="control" %}
{% bootstrap_field form.rate addon_after="%" layout="control" %}
{% bootstrap_field form.price_includes_tax layout="control" %}
</fieldset>
@@ -39,6 +40,7 @@
</div>
{% bootstrap_field form.eu_reverse_charge layout="control" %}
{% bootstrap_field form.home_country layout="control" %}
{% bootstrap_field form.keep_gross_if_rate_changes layout="control" %}
<h3>{% trans "Custom taxation rules" %}</h3>
<div class="alert alert-warning">
{% blocktrans trimmed %}
@@ -33,7 +33,7 @@
<tr>
<td>
<strong><a href="{% url "control:event.settings.tax.edit" organizer=request.event.organizer.slug event=request.event.slug rule=tr.id %}">
{{ tr.name }}
{{ tr.internal_name|default:tr.name }}
</a></strong>
</td>
<td>
@@ -1,6 +1,6 @@
{% load i18n %}
<div class="quotabox availability" data-toggle="tooltip_html" data-placement="top"
title="{% trans "Quota:" %} {{ q.name }}<br>{% blocktrans with date=q.cached_availability_time|date:"SHORT_DATETIME_FORMAT" %}Numbers as of {{ date }}{% endblocktrans %}">
title="{% trans "Quota:" %} {{ q.name|force_escape|force_escape }}<br>{% blocktrans with date=q.cached_availability_time|date:"SHORT_DATETIME_FORMAT" %}Numbers as of {{ date }}{% endblocktrans %}">
{% if q.size|default_if_none:"NONE" == "NONE" %}
<div class="progress">
<div class="progress-bar progress-bar-success progress-bar-100">
@@ -1,6 +1,6 @@
{% load i18n %}
<a class="quotabox" data-toggle="tooltip_html" data-placement="top"
title="{% trans "Quota:" %} {{ q.name }}{% if q.cached_avail.1 is not None %}<br>{% blocktrans with num=q.cached_avail.1 %}Currently available: {{ num }}{% endblocktrans %}{% endif %}"
title="{% trans "Quota:" %} {{ q.name|force_escape|force_escape }}{% if q.cached_avail.1 is not None %}<br>{% blocktrans with num=q.cached_avail.1 %}Currently available: {{ num }}{% endblocktrans %}{% endif %}"
href="{% url "control:event.items.quotas.show" event=q.event.slug organizer=q.event.organizer.slug quota=q.pk %}">
{% if q.size|default_if_none:"NONE" == "NONE" %}
<div class="progress">
@@ -73,6 +73,7 @@
{% bootstrap_field form.available_until layout="control" %}
{% bootstrap_field form.sales_channels layout="control" %}
{% bootstrap_field form.hide_without_voucher layout="control" %}
{% bootstrap_field form.require_approval layout="control" %}
{% if form.require_membership %}
{% bootstrap_field form.require_membership layout="control" %}
<div data-display-dependency="#{{ form.require_membership.id_for_label }}">
@@ -144,6 +145,7 @@
{% bootstrap_field formset.empty_form.available_until layout="control" %}
{% bootstrap_field formset.empty_form.sales_channels layout="control" %}
{% bootstrap_field formset.empty_form.hide_without_voucher layout="control" %}
{% bootstrap_field formset.empty_form.require_approval layout="control" %}
{% if formset.empty_form.require_membership %}
{% bootstrap_field formset.empty_form.require_membership layout="control" %}
<div data-display-dependency="#{{ formset.empty_form.require_membership.id_for_label }}">
@@ -145,7 +145,12 @@
<strong>{% trans "Tax rule" %}</strong>
</div>
<div class="col-sm-5">
{{ position.tax_rule.name }} ({{ position.tax_rule.rate }} %)
{% if position.tax_rule.internal_name %}
{{ position.tax_rule.internal_name }}
{% else %}
{{ position.tax_rule.name }}
{% endif %}
({{ position.tax_rule.rate }} %)
</div>
<div class="col-sm-4 field-container">
{% bootstrap_field position.form.tax_rule layout='inline' %}
@@ -360,19 +360,19 @@
{% if line.checkins.all %}
{% for c in line.all_checkins.all %}
{% if not c.successful %}
<span class="fa fa-fw fa-exclamation-circle text-danger" data-toggle="tooltip_html" title="{{ c.list.name }}<br>{% blocktrans trimmed with date=c.datetime|date:'SHORT_DATETIME_FORMAT' %}Denied scan: {{ date }}{% endblocktrans %}<br>{{ c.get_error_reason_display }}{% if c.gate %}<br>{{ c.gate }}{% endif %}"></span>
<span class="fa fa-fw fa-exclamation-circle text-danger" data-toggle="tooltip_html" title="{{ c.list.name|force_escape|force_escape }}<br>{% blocktrans trimmed with date=c.datetime|date:'SHORT_DATETIME_FORMAT' %}Denied scan: {{ date }}{% endblocktrans %}<br>{{ c.get_error_reason_display }}{% if c.gate %}<br>{{ c.gate }}{% endif %}"></span>
{% elif c.type == "exit" %}
{% if c.auto_checked_in %}
<span class="fa fa-fw text-success fa-hourglass-end" data-toggle="tooltip_html" title="{{ c.list.name }}<br>{% blocktrans trimmed with date=c.datetime|date:'SHORT_DATETIME_FORMAT' %}Automatically marked not present: {{ date }}{% endblocktrans %}"></span>
<span class="fa fa-fw text-success fa-hourglass-end" data-toggle="tooltip_html" title="{{ c.list.name|force_escape|force_escape }}<br>{% blocktrans trimmed with date=c.datetime|date:'SHORT_DATETIME_FORMAT' %}Automatically marked not present: {{ date }}{% endblocktrans %}"></span>
{% else %}
<span class="fa fa-fw text-success fa-sign-out" data-toggle="tooltip_html" title="{{ c.list.name }}<br>{% blocktrans trimmed with date=c.datetime|date:'SHORT_DATETIME_FORMAT' %}Exit scan: {{ date }}{% endblocktrans %}{% if c.gate %}<br>{{ c.gate }}{% endif %}"></span>
<span class="fa fa-fw text-success fa-sign-out" data-toggle="tooltip_html" title="{{ c.list.name|force_escape|force_escape }}<br>{% blocktrans trimmed with date=c.datetime|date:'SHORT_DATETIME_FORMAT' %}Exit scan: {{ date }}{% endblocktrans %}{% if c.gate %}<br>{{ c.gate }}{% endif %}"></span>
{% endif %}
{% elif c.forced %}
<span class="fa fa-fw fa-warning text-warning" data-toggle="tooltip_html" title="{{ c.list.name }}<br>{% blocktrans trimmed with date=c.datetime|date:'SHORT_DATETIME_FORMAT' %}Additional entry scan: {{ date }}{% endblocktrans %}{% if c.gate %}<br>{{ c.gate }}{% endif %}"></span>
<span class="fa fa-fw fa-warning text-warning" data-toggle="tooltip_html" title="{{ c.list.name|force_escape|force_escape }}<br>{% blocktrans trimmed with date=c.datetime|date:'SHORT_DATETIME_FORMAT' %}Additional entry scan: {{ date }}{% endblocktrans %}{% if c.gate %}<br>{{ c.gate }}{% endif %}"></span>
{% elif c.auto_checked_in %}
<span class="fa fa-fw fa-magic text-success" data-toggle="tooltip_html" title="{{ c.list.name }}<br>{% blocktrans trimmed with date=c.datetime|date:'SHORT_DATETIME_FORMAT' %}Automatically checked in: {{ date }}{% endblocktrans %}{% if c.gate %}<br>{{ c.gate }}{% endif %}"></span>
<span class="fa fa-fw fa-magic text-success" data-toggle="tooltip_html" title="{{ c.list.name|force_escape|force_escape }}<br>{% blocktrans trimmed with date=c.datetime|date:'SHORT_DATETIME_FORMAT' %}Automatically checked in: {{ date }}{% endblocktrans %}{% if c.gate %}<br>{{ c.gate }}{% endif %}"></span>
{% else %}
<span class="fa fa-fw fa-check text-success" data-toggle="tooltip_html" title="{{ c.list.name }}<br>{% blocktrans trimmed with date=c.datetime|date:'SHORT_DATETIME_FORMAT' %}Entry scan: {{ date }}{% endblocktrans %}{% if c.gate %}<br>{{ c.gate }}{% endif %}"></span>
<span class="fa fa-fw fa-check text-success" data-toggle="tooltip_html" title="{{ c.list.name|force_escape|force_escape }}<br>{% blocktrans trimmed with date=c.datetime|date:'SHORT_DATETIME_FORMAT' %}Entry scan: {{ date }}{% endblocktrans %}{% if c.gate %}<br>{{ c.gate }}{% endif %}"></span>
{% endif %}
{% endfor %}
{% endif %}
@@ -48,6 +48,10 @@
</dd>
<dt>{% trans "Name" %}</dt>
<dd>{{ customer.name }}</dd>
{% if customer.phone %}
<dt>{% trans "Phone" %}</dt>
<dd>{{ customer.phone }}</dd>
{% endif %}
<dt>{% trans "Locale" %}</dt>
<dd>{{ display_locale }}</dd>
<dt>{% trans "Registration date" %}</dt>
@@ -57,6 +57,7 @@
</div>
<form class="" method="post" action="">
{% csrf_token %}
<button type="submit" class="hidden">Add</button> <!-- Required because pressing enter in the text fields will submit the first button -->
<table class="panel-body table">
<thead>
<tr>
@@ -101,7 +102,7 @@
</td>
<td class="text-right form-inline">
<input type="text" class="form-control input-sm" placeholder="{% trans "Value" %}" name="value">
<button class="btn btn-primary">
<button type="submit" class="btn btn-primary">
<span class="fa fa-plus"></span>
</button>
</td>
+5
View File
@@ -490,6 +490,7 @@ class OrganizerCreate(CreateView):
organizer=form.instance, name=_('Administrators'),
all_events=True, can_create_events=True, can_change_teams=True, can_manage_gift_cards=True,
can_change_organizer_settings=True, can_change_event_settings=True, can_change_items=True,
can_manage_customers=True,
can_view_orders=True, can_change_orders=True, can_view_vouchers=True, can_change_vouchers=True
)
t.members.add(self.request.user)
@@ -1195,6 +1196,10 @@ class GiftCardDetailView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMi
'retry': True,
})
)
t.order.log_action('pretix.event.order.payment.started', {
'local_id': r.local_id,
'provider': r.provider
}, user=request.user)
try:
r.payment_provider.execute_payment(request, r)
except PaymentException as e:
+4
View File
@@ -25,3 +25,7 @@ from django.apps import AppConfig
class PretixHelpersConfig(AppConfig):
name = 'pretix.helpers'
label = 'pretixhelpers'
def ready(self):
from .monkeypatching import monkeypatch_all_at_ready
monkeypatch_all_at_ready()
+2 -1
View File
@@ -32,10 +32,11 @@
# 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.
from django.template.defaultfilters import date as _date
from django.utils.html import format_html
from django.utils.translation import get_language, gettext_lazy as _
from pretix.helpers.templatetags.date_fast import date_fast as _date
def daterange(df, dt, as_html=False):
lng = get_language()
+1
View File
@@ -39,3 +39,4 @@ SHORT_DATETIME_FORMAT = 'Y-m-d H:i'
TIME_FORMAT = 'H:i'
WEEK_FORMAT = '\\W W, o'
WEEK_DAY_FORMAT = 'D, M jS'
SHORT_MONTH_DAY_FORMAT = 'd.m.'
@@ -26,6 +26,7 @@ SHORT_DATETIME_FORMAT = 'm/d/Y P'
TIME_FORMAT = 'P'
WEEK_FORMAT = '\\W W, o'
WEEK_DAY_FORMAT = 'D, M jS'
SHORT_MONTH_DAY_FORMAT = 'm/d'
DATE_INPUT_FORMATS = [
'%m/%d/%Y',
+56
View File
@@ -0,0 +1,56 @@
#
# This file is part of pretix (Community Edition).
#
# Copyright (C) 2014-2020 Raphael Michel and contributors
# Copyright (C) 2020-2021 rami.io GmbH and contributors
#
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
# Public License as published by the Free Software Foundation in version 3 of the License.
#
# ADDITIONAL TERMS APPLY: Pursuant to Section 7 of the GNU Affero General Public License, additional terms are
# applicable granting you additional permissions and placing additional restrictions on your usage of this software.
# Please refer to the pretix LICENSE file to obtain the full terms applicable to this work. If you did not receive
# this file, see <https://pretix.eu/about/en/license>.
#
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
# <https://www.gnu.org/licenses/>.
#
from datetime import datetime
def monkeypatch_vobject_performance():
"""
This works around a performance issue in the unmaintained vobject library which calls
a very expensive function for every event in a calendar. Since the slow function is
mostly used to compare timezones to UTC, not to arbitrary other timezones, we can
add a few early-out optimizations.
"""
from vobject import icalendar
old_tzinfo_eq = icalendar.tzinfo_eq
test_date = datetime(2000, 1, 1)
def new_tzinfo_eq(tzinfo1, tzinfo2, *args, **kwargs):
if tzinfo1 is None:
return tzinfo2 is None
if tzinfo2 is None:
return tzinfo1 is None
n1 = tzinfo1.tzname(test_date)
n2 = tzinfo2.tzname(test_date)
if n1 == "UTC" and n2 == "UTC":
return True
if n1 == "UTC" or n2 == "UTC":
return False
return old_tzinfo_eq(tzinfo1, tzinfo2, *args, **kwargs)
icalendar.tzinfo_eq = new_tzinfo_eq
def monkeypatch_all_at_ready():
monkeypatch_vobject_performance()
@@ -0,0 +1,61 @@
#
# This file is part of pretix (Community Edition).
#
# Copyright (C) 2014-2020 Raphael Michel and contributors
# Copyright (C) 2020-2021 rami.io GmbH and contributors
#
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General
# Public License as published by the Free Software Foundation in version 3 of the License.
#
# ADDITIONAL TERMS APPLY: Pursuant to Section 7 of the GNU Affero General Public License, additional terms are
# applicable granting you additional permissions and placing additional restrictions on your usage of this software.
# Please refer to the pretix LICENSE file to obtain the full terms applicable to this work. If you did not receive
# this file, see <https://pretix.eu/about/en/license>.
#
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
# <https://www.gnu.org/licenses/>.
#
import functools
from django import template
from django.utils import dateformat
from django.utils.formats import get_format
from django.utils.translation import get_language
register = template.Library()
@functools.lru_cache(maxsize=32)
def _get_format(format_type, lang):
return get_format(format_type, lang)
@register.filter(expects_localtime=True, is_safe=False)
def date_fast(value, arg=None):
"""
Slightly quicker version of |date if the filter is called a lot. The speedup is achieved through
LRU caching for formats.
Django's built-in |date filter has a caching mechanism if you call it with a named format,
i.e. ``|date_fast:"SHORT_DATE_FORMAT"`` will only be ~6% faster than ``|date:"SHORT_DATE_FORMAT"``.
However, Django's built-in caching has a flaw with unnamed formats, therefore ``|date_fast:"Y-m-d"``
will be ~12% faster than ``|date:"Y-m-d"``.
"""
if value in (None, ''):
return ''
lang = get_language()
format = _get_format(arg, lang)
try:
return dateformat.format(value, format)
except AttributeError:
try:
return format(value, arg)
except AttributeError:
return ''
+3 -1
View File
@@ -173,7 +173,7 @@ def create_thumbnail(sourcename, size):
image = resize_image(image, size)
if source.name.endswith('.jpg') or source.name.endswith('.jpeg'):
if source.name.lower().endswith('.jpg') or source.name.lower().endswith('.jpeg'):
# Yields better file sizes for photos
target_ext = 'jpeg'
quality = 95
@@ -184,6 +184,8 @@ def create_thumbnail(sourcename, size):
checksum = hashlib.md5(image.tobytes()).hexdigest()
name = checksum + '.' + size.replace('^', 'c') + '.' + target_ext
buffer = BytesIO()
if image.mode == "P" and source.name.lower().endswith('.png'):
image = image.convert('RGBA')
if image.mode not in ("1", "L", "RGB", "RGBA"):
image = image.convert('RGB')
image.save(fp=buffer, format=target_ext.upper(), quality=quality)
File diff suppressed because it is too large Load Diff
+6 -6
View File
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-30 16:13+0000\n"
"POT-Creation-Date: 2022-01-14 14:33+0000\n"
"PO-Revision-Date: 2021-09-15 11:22+0000\n"
"Last-Translator: Mohamed Tawfiq <mtawfiq@wafyapp.com>\n"
"Language-Team: Arabic <https://translate.pretix.eu/projects/pretix/pretix-js/"
@@ -535,20 +535,20 @@ msgstr "ستسترد %(currency)%(amount)"
msgid "Please enter the amount the organizer can keep."
msgstr "الرجاء إدخال المبلغ الذي يمكن للمنظم الاحتفاظ به."
#: pretix/static/pretixpresale/js/ui/main.js:349
#: pretix/static/pretixpresale/js/ui/main.js:361
msgid "Please enter a quantity for one of the ticket types."
msgstr "الرجاء إدخال عدد لأحد أنواع التذاكر."
#: pretix/static/pretixpresale/js/ui/main.js:385
#: pretix/static/pretixpresale/js/ui/main.js:397
msgid "required"
msgstr "مطلوب"
#: pretix/static/pretixpresale/js/ui/main.js:488
#: pretix/static/pretixpresale/js/ui/main.js:507
#: pretix/static/pretixpresale/js/ui/main.js:500
#: pretix/static/pretixpresale/js/ui/main.js:519
msgid "Time zone:"
msgstr "المنطقة الزمنية:"
#: pretix/static/pretixpresale/js/ui/main.js:498
#: pretix/static/pretixpresale/js/ui/main.js:510
msgid "Your local time:"
msgstr "التوقيت المحلي:"
File diff suppressed because it is too large Load Diff
+6 -6
View File
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-30 16:13+0000\n"
"POT-Creation-Date: 2022-01-14 14:33+0000\n"
"PO-Revision-Date: 2020-12-19 07:00+0000\n"
"Last-Translator: albert <albert.serra.monner@gmail.com>\n"
"Language-Team: Catalan <https://translate.pretix.eu/projects/pretix/pretix-"
@@ -510,22 +510,22 @@ msgstr ""
msgid "Please enter the amount the organizer can keep."
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:349
#: pretix/static/pretixpresale/js/ui/main.js:361
msgid "Please enter a quantity for one of the ticket types."
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:385
#: pretix/static/pretixpresale/js/ui/main.js:397
#, fuzzy
#| msgid "Cart expired"
msgid "required"
msgstr "Cistella expirada"
#: pretix/static/pretixpresale/js/ui/main.js:488
#: pretix/static/pretixpresale/js/ui/main.js:507
#: pretix/static/pretixpresale/js/ui/main.js:500
#: pretix/static/pretixpresale/js/ui/main.js:519
msgid "Time zone:"
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:498
#: pretix/static/pretixpresale/js/ui/main.js:510
msgid "Your local time:"
msgstr ""
File diff suppressed because it is too large Load Diff
+6 -6
View File
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-30 16:13+0000\n"
"POT-Creation-Date: 2022-01-14 14:33+0000\n"
"PO-Revision-Date: 2021-12-06 23:00+0000\n"
"Last-Translator: Ondřej Sokol <osokol@treesoft.cz>\n"
"Language-Team: Czech <https://translate.pretix.eu/projects/pretix/pretix-js/"
@@ -528,20 +528,20 @@ msgstr "Dostanete %(currency)s %(amount)s zpět"
msgid "Please enter the amount the organizer can keep."
msgstr "Zadejte částku, kterou si organizátor může ponechat."
#: pretix/static/pretixpresale/js/ui/main.js:349
#: pretix/static/pretixpresale/js/ui/main.js:361
msgid "Please enter a quantity for one of the ticket types."
msgstr "Zadejte prosím množství pro jeden z typů vstupenek."
#: pretix/static/pretixpresale/js/ui/main.js:385
#: pretix/static/pretixpresale/js/ui/main.js:397
msgid "required"
msgstr "povinný"
#: pretix/static/pretixpresale/js/ui/main.js:488
#: pretix/static/pretixpresale/js/ui/main.js:507
#: pretix/static/pretixpresale/js/ui/main.js:500
#: pretix/static/pretixpresale/js/ui/main.js:519
msgid "Time zone:"
msgstr "Časové pásmo:"
#: pretix/static/pretixpresale/js/ui/main.js:498
#: pretix/static/pretixpresale/js/ui/main.js:510
msgid "Your local time:"
msgstr "Místní čas:"
File diff suppressed because it is too large Load Diff
+6 -6
View File
@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-30 16:13+0000\n"
"POT-Creation-Date: 2022-01-14 14:33+0000\n"
"PO-Revision-Date: 2021-09-13 09:48+0000\n"
"Last-Translator: Mie Frydensbjerg <mif@aarhus.dk>\n"
"Language-Team: Danish <https://translate.pretix.eu/projects/pretix/pretix-js/"
@@ -563,22 +563,22 @@ msgstr "fra %(currency)s %(price)s"
msgid "Please enter the amount the organizer can keep."
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:349
#: pretix/static/pretixpresale/js/ui/main.js:361
msgid "Please enter a quantity for one of the ticket types."
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:385
#: pretix/static/pretixpresale/js/ui/main.js:397
#, fuzzy
#| msgid "Cart expired"
msgid "required"
msgstr "Kurv udløbet"
#: pretix/static/pretixpresale/js/ui/main.js:488
#: pretix/static/pretixpresale/js/ui/main.js:507
#: pretix/static/pretixpresale/js/ui/main.js:500
#: pretix/static/pretixpresale/js/ui/main.js:519
msgid "Time zone:"
msgstr "Tidszone:"
#: pretix/static/pretixpresale/js/ui/main.js:498
#: pretix/static/pretixpresale/js/ui/main.js:510
msgid "Your local time:"
msgstr "Din lokaltid:"
File diff suppressed because it is too large Load Diff
+6 -6
View File
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-30 16:13+0000\n"
"POT-Creation-Date: 2022-01-14 14:33+0000\n"
"PO-Revision-Date: 2021-10-25 15:40+0000\n"
"Last-Translator: Raphael Michel <michel@rami.io>\n"
"Language-Team: German <https://translate.pretix.eu/projects/pretix/pretix-js/"
@@ -532,20 +532,20 @@ msgstr "Sie erhalten %(currency)s %(amount)s zurück"
msgid "Please enter the amount the organizer can keep."
msgstr "Bitte geben Sie den Betrag ein, den der Veranstalter einbehalten darf."
#: pretix/static/pretixpresale/js/ui/main.js:349
#: pretix/static/pretixpresale/js/ui/main.js:361
msgid "Please enter a quantity for one of the ticket types."
msgstr "Bitte tragen Sie eine Menge für eines der Produkte ein."
#: pretix/static/pretixpresale/js/ui/main.js:385
#: pretix/static/pretixpresale/js/ui/main.js:397
msgid "required"
msgstr "verpflichtend"
#: pretix/static/pretixpresale/js/ui/main.js:488
#: pretix/static/pretixpresale/js/ui/main.js:507
#: pretix/static/pretixpresale/js/ui/main.js:500
#: pretix/static/pretixpresale/js/ui/main.js:519
msgid "Time zone:"
msgstr "Zeitzone:"
#: pretix/static/pretixpresale/js/ui/main.js:498
#: pretix/static/pretixpresale/js/ui/main.js:510
msgid "Your local time:"
msgstr "Deine lokale Zeit:"
File diff suppressed because it is too large Load Diff
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-30 16:13+0000\n"
"POT-Creation-Date: 2022-01-14 14:33+0000\n"
"PO-Revision-Date: 2021-10-25 15:40+0000\n"
"Last-Translator: Raphael Michel <michel@rami.io>\n"
"Language-Team: German (informal) <https://translate.pretix.eu/projects/"
@@ -531,20 +531,20 @@ msgstr "Du erhältst %(currency)s %(amount)s zurück"
msgid "Please enter the amount the organizer can keep."
msgstr "Bitte gib den Betrag ein, den der Veranstalter einbehalten darf."
#: pretix/static/pretixpresale/js/ui/main.js:349
#: pretix/static/pretixpresale/js/ui/main.js:361
msgid "Please enter a quantity for one of the ticket types."
msgstr "Bitte trage eine Menge für eines der Produkte ein."
#: pretix/static/pretixpresale/js/ui/main.js:385
#: pretix/static/pretixpresale/js/ui/main.js:397
msgid "required"
msgstr "verpflichtend"
#: pretix/static/pretixpresale/js/ui/main.js:488
#: pretix/static/pretixpresale/js/ui/main.js:507
#: pretix/static/pretixpresale/js/ui/main.js:500
#: pretix/static/pretixpresale/js/ui/main.js:519
msgid "Time zone:"
msgstr "Zeitzone:"
#: pretix/static/pretixpresale/js/ui/main.js:498
#: pretix/static/pretixpresale/js/ui/main.js:510
msgid "Your local time:"
msgstr "Deine lokale Zeit:"
+1603 -1512
View File
File diff suppressed because it is too large Load Diff
+6 -6
View File
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-30 16:13+0000\n"
"POT-Creation-Date: 2022-01-14 14:33+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -505,20 +505,20 @@ msgstr ""
msgid "Please enter the amount the organizer can keep."
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:349
#: pretix/static/pretixpresale/js/ui/main.js:361
msgid "Please enter a quantity for one of the ticket types."
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:385
#: pretix/static/pretixpresale/js/ui/main.js:397
msgid "required"
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:488
#: pretix/static/pretixpresale/js/ui/main.js:507
#: pretix/static/pretixpresale/js/ui/main.js:500
#: pretix/static/pretixpresale/js/ui/main.js:519
msgid "Time zone:"
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:498
#: pretix/static/pretixpresale/js/ui/main.js:510
msgid "Your local time:"
msgstr ""
File diff suppressed because it is too large Load Diff
+6 -6
View File
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-30 16:13+0000\n"
"POT-Creation-Date: 2022-01-14 14:33+0000\n"
"PO-Revision-Date: 2019-10-03 19:00+0000\n"
"Last-Translator: Chris Spy <chrispiropoulou@hotmail.com>\n"
"Language-Team: Greek <https://translate.pretix.eu/projects/pretix/pretix-js/"
@@ -575,22 +575,22 @@ msgstr "απο %(currency)s %(price)s"
msgid "Please enter the amount the organizer can keep."
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:349
#: pretix/static/pretixpresale/js/ui/main.js:361
msgid "Please enter a quantity for one of the ticket types."
msgstr "Εισαγάγετε μια ποσότητα για έναν από τους τύπους εισιτηρίων."
#: pretix/static/pretixpresale/js/ui/main.js:385
#: pretix/static/pretixpresale/js/ui/main.js:397
#, fuzzy
#| msgid "Cart expired"
msgid "required"
msgstr "Το καλάθι έληξε"
#: pretix/static/pretixpresale/js/ui/main.js:488
#: pretix/static/pretixpresale/js/ui/main.js:507
#: pretix/static/pretixpresale/js/ui/main.js:500
#: pretix/static/pretixpresale/js/ui/main.js:519
msgid "Time zone:"
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:498
#: pretix/static/pretixpresale/js/ui/main.js:510
msgid "Your local time:"
msgstr ""
File diff suppressed because it is too large Load Diff
+6 -6
View File
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-30 16:13+0000\n"
"POT-Creation-Date: 2022-01-14 14:33+0000\n"
"PO-Revision-Date: 2021-11-25 21:00+0000\n"
"Last-Translator: Ismael Menéndez Fernández <ismael.menendez@balidea.com>\n"
"Language-Team: Spanish <https://translate.pretix.eu/projects/pretix/pretix-"
@@ -529,20 +529,20 @@ msgstr "Obtienes %(currency)s %(price)s de vuelta"
msgid "Please enter the amount the organizer can keep."
msgstr "Por favor, ingrese el monto que el organizador puede quedarse."
#: pretix/static/pretixpresale/js/ui/main.js:349
#: pretix/static/pretixpresale/js/ui/main.js:361
msgid "Please enter a quantity for one of the ticket types."
msgstr "Por favor, introduzca un valor para cada tipo de entrada."
#: pretix/static/pretixpresale/js/ui/main.js:385
#: pretix/static/pretixpresale/js/ui/main.js:397
msgid "required"
msgstr "campo requerido"
#: pretix/static/pretixpresale/js/ui/main.js:488
#: pretix/static/pretixpresale/js/ui/main.js:507
#: pretix/static/pretixpresale/js/ui/main.js:500
#: pretix/static/pretixpresale/js/ui/main.js:519
msgid "Time zone:"
msgstr "Zona horaria:"
#: pretix/static/pretixpresale/js/ui/main.js:498
#: pretix/static/pretixpresale/js/ui/main.js:510
msgid "Your local time:"
msgstr "Su hora local:"
File diff suppressed because it is too large Load Diff
+6 -6
View File
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-30 16:13+0000\n"
"POT-Creation-Date: 2022-01-14 14:33+0000\n"
"PO-Revision-Date: 2021-11-10 05:00+0000\n"
"Last-Translator: Jaakko Rinta-Filppula <jaakko@r-f.fi>\n"
"Language-Team: Finnish <https://translate.pretix.eu/projects/pretix/pretix-"
@@ -528,22 +528,22 @@ msgstr ""
msgid "Please enter the amount the organizer can keep."
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:349
#: pretix/static/pretixpresale/js/ui/main.js:361
msgid "Please enter a quantity for one of the ticket types."
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:385
#: pretix/static/pretixpresale/js/ui/main.js:397
#, fuzzy
#| msgid "Cart expired"
msgid "required"
msgstr "Ostoskori on vanhentunut"
#: pretix/static/pretixpresale/js/ui/main.js:488
#: pretix/static/pretixpresale/js/ui/main.js:507
#: pretix/static/pretixpresale/js/ui/main.js:500
#: pretix/static/pretixpresale/js/ui/main.js:519
msgid "Time zone:"
msgstr "Aikavyöhyke:"
#: pretix/static/pretixpresale/js/ui/main.js:498
#: pretix/static/pretixpresale/js/ui/main.js:510
msgid "Your local time:"
msgstr ""
File diff suppressed because it is too large Load Diff
+6 -6
View File
@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: French\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-30 16:13+0000\n"
"POT-Creation-Date: 2022-01-14 14:33+0000\n"
"PO-Revision-Date: 2021-12-04 01:00+0000\n"
"Last-Translator: Eva-Maria Obermann <obermann@rami.io>\n"
"Language-Team: French <https://translate.pretix.eu/projects/pretix/pretix-js/"
@@ -567,22 +567,22 @@ msgstr "de %(currency)s %(price)s"
msgid "Please enter the amount the organizer can keep."
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:349
#: pretix/static/pretixpresale/js/ui/main.js:361
msgid "Please enter a quantity for one of the ticket types."
msgstr "SVP entrez une quantité pour un de vos types de billets."
#: pretix/static/pretixpresale/js/ui/main.js:385
#: pretix/static/pretixpresale/js/ui/main.js:397
#, fuzzy
#| msgid "Cart expired"
msgid "required"
msgstr "Panier expiré"
#: pretix/static/pretixpresale/js/ui/main.js:488
#: pretix/static/pretixpresale/js/ui/main.js:507
#: pretix/static/pretixpresale/js/ui/main.js:500
#: pretix/static/pretixpresale/js/ui/main.js:519
msgid "Time zone:"
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:498
#: pretix/static/pretixpresale/js/ui/main.js:510
msgid "Your local time:"
msgstr ""
File diff suppressed because it is too large Load Diff
+6 -6
View File
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-30 16:13+0000\n"
"POT-Creation-Date: 2022-01-14 14:33+0000\n"
"PO-Revision-Date: 2021-11-25 21:00+0000\n"
"Last-Translator: Ismael Menéndez Fernández <ismael.menendez@balidea.com>\n"
"Language-Team: Galician <https://translate.pretix.eu/projects/pretix/pretix-"
@@ -526,20 +526,20 @@ msgstr "Obtés %(currency)s %(price)s de volta"
msgid "Please enter the amount the organizer can keep."
msgstr "Por favor, ingrese a cantidade que pode conservar o organizador."
#: pretix/static/pretixpresale/js/ui/main.js:349
#: pretix/static/pretixpresale/js/ui/main.js:361
msgid "Please enter a quantity for one of the ticket types."
msgstr "Por favor, introduza un valor para cada tipo de entrada."
#: pretix/static/pretixpresale/js/ui/main.js:385
#: pretix/static/pretixpresale/js/ui/main.js:397
msgid "required"
msgstr "campo requirido"
#: pretix/static/pretixpresale/js/ui/main.js:488
#: pretix/static/pretixpresale/js/ui/main.js:507
#: pretix/static/pretixpresale/js/ui/main.js:500
#: pretix/static/pretixpresale/js/ui/main.js:519
msgid "Time zone:"
msgstr "Zona horaria:"
#: pretix/static/pretixpresale/js/ui/main.js:498
#: pretix/static/pretixpresale/js/ui/main.js:510
msgid "Your local time:"
msgstr "A súa hora local:"
File diff suppressed because it is too large Load Diff
+6 -6
View File
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-30 16:13+0000\n"
"POT-Creation-Date: 2022-01-14 14:33+0000\n"
"PO-Revision-Date: 2021-09-24 13:54+0000\n"
"Last-Translator: ofirtro <ofir.tro@gmail.com>\n"
"Language-Team: Hebrew <https://translate.pretix.eu/projects/pretix/pretix-js/"
@@ -513,20 +513,20 @@ msgstr ""
msgid "Please enter the amount the organizer can keep."
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:349
#: pretix/static/pretixpresale/js/ui/main.js:361
msgid "Please enter a quantity for one of the ticket types."
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:385
#: pretix/static/pretixpresale/js/ui/main.js:397
msgid "required"
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:488
#: pretix/static/pretixpresale/js/ui/main.js:507
#: pretix/static/pretixpresale/js/ui/main.js:500
#: pretix/static/pretixpresale/js/ui/main.js:519
msgid "Time zone:"
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:498
#: pretix/static/pretixpresale/js/ui/main.js:510
msgid "Your local time:"
msgstr ""
File diff suppressed because it is too large Load Diff
+6 -6
View File
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-30 16:13+0000\n"
"POT-Creation-Date: 2022-01-14 14:33+0000\n"
"PO-Revision-Date: 2020-01-24 08:00+0000\n"
"Last-Translator: Prokaj Miklós <mixolid0@gmail.com>\n"
"Language-Team: Hungarian <https://translate.pretix.eu/projects/pretix/pretix-"
@@ -563,22 +563,22 @@ msgstr "%(currency) %(price)-tól"
msgid "Please enter the amount the organizer can keep."
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:349
#: pretix/static/pretixpresale/js/ui/main.js:361
msgid "Please enter a quantity for one of the ticket types."
msgstr "Adjon meg egy mennyiséget az egyik jegytípusból."
#: pretix/static/pretixpresale/js/ui/main.js:385
#: pretix/static/pretixpresale/js/ui/main.js:397
#, fuzzy
#| msgid "Cart expired"
msgid "required"
msgstr "A kosár lejárt"
#: pretix/static/pretixpresale/js/ui/main.js:488
#: pretix/static/pretixpresale/js/ui/main.js:507
#: pretix/static/pretixpresale/js/ui/main.js:500
#: pretix/static/pretixpresale/js/ui/main.js:519
msgid "Time zone:"
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:498
#: pretix/static/pretixpresale/js/ui/main.js:510
msgid "Your local time:"
msgstr ""
File diff suppressed because it is too large Load Diff
+6 -6
View File
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-30 16:13+0000\n"
"POT-Creation-Date: 2022-01-14 14:33+0000\n"
"PO-Revision-Date: 2021-11-20 03:00+0000\n"
"Last-Translator: Marco Giacopuzzi <marco.giaco2000@gmail.com>\n"
"Language-Team: Italian <https://translate.pretix.eu/projects/pretix/pretix-"
@@ -522,20 +522,20 @@ msgstr "Ricevi indietro %(currency)s %(amount)s"
msgid "Please enter the amount the organizer can keep."
msgstr "Inserisci l'importo che l'organizzatore può trattenere."
#: pretix/static/pretixpresale/js/ui/main.js:349
#: pretix/static/pretixpresale/js/ui/main.js:361
msgid "Please enter a quantity for one of the ticket types."
msgstr "Inserisci la quantità per una tipologia di biglietto."
#: pretix/static/pretixpresale/js/ui/main.js:385
#: pretix/static/pretixpresale/js/ui/main.js:397
msgid "required"
msgstr "richiesto"
#: pretix/static/pretixpresale/js/ui/main.js:488
#: pretix/static/pretixpresale/js/ui/main.js:507
#: pretix/static/pretixpresale/js/ui/main.js:500
#: pretix/static/pretixpresale/js/ui/main.js:519
msgid "Time zone:"
msgstr "Fuso orario:"
#: pretix/static/pretixpresale/js/ui/main.js:498
#: pretix/static/pretixpresale/js/ui/main.js:510
msgid "Your local time:"
msgstr "Ora locale:"
File diff suppressed because it is too large Load Diff
+176 -164
View File
@@ -7,9 +7,9 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-30 16:13+0000\n"
"PO-Revision-Date: 2021-12-13 21:00+0000\n"
"Last-Translator: DJG Bayern <pretix2021weblate@aruki.de>\n"
"POT-Creation-Date: 2022-01-14 14:33+0000\n"
"PO-Revision-Date: 2022-01-19 21:00+0000\n"
"Last-Translator: Yuriko Matsunami <y.matsunami@enobyte.com>\n"
"Language-Team: Japanese <https://translate.pretix.eu/projects/pretix/"
"pretix-js/ja/>\n"
"Language: ja\n"
@@ -23,16 +23,16 @@ msgstr ""
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:62
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:68
msgid "Marked as paid"
msgstr "支払い済みと表示"
msgstr "支払い済み"
#: pretix/plugins/banktransfer/static/pretixplugins/banktransfer/ui.js:76
msgid "Comment:"
msgstr "注:"
msgstr "注:"
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:15
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:39
msgid "Placed orders"
msgstr ""
msgstr "受注状況"
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:15
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:39
@@ -41,14 +41,13 @@ msgstr "支払い済みの注文"
#: pretix/plugins/statistics/static/pretixplugins/statistics/statistics.js:27
msgid "Total revenue"
msgstr "収益合計"
msgstr "売上合計"
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:12
msgid "Contacting Stripe …"
msgstr ""
msgstr "お問い合わせはこちら"
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:60
#, fuzzy
msgid "Total"
msgstr "合計"
@@ -59,19 +58,19 @@ msgstr "お支払い内容の確認"
#: pretix/plugins/stripe/static/pretixplugins/stripe/pretix-stripe.js:159
msgid "Contacting your bank …"
msgstr ""
msgstr "銀行へ問い合わせ中…"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:30
msgid "Select a check-in list"
msgstr ""
msgstr "チェックインリストを選択してください"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:31
msgid "No active check-in lists found."
msgstr ""
msgstr "アクティブなチェックインリストは見つかりません。"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:32
msgid "Switch check-in list"
msgstr ""
msgstr "チェックインリストを切り替え"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:33
msgid "Search results"
@@ -79,19 +78,17 @@ msgstr "検索結果"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:34
msgid "No tickets found"
msgstr ""
msgstr "チケットが見つかりません"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:35
msgid "Result"
msgstr ""
msgstr "結果"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:36
#, fuzzy
msgid "This ticket requires special attention"
msgstr "要注意チケット"
msgstr "このチケットは特別な対応が必要です"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:37
#, fuzzy
msgid "Switch direction"
msgstr "方向転換"
@@ -105,11 +102,11 @@ msgstr "出口"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:40
msgid "Scan a ticket or search and press return…"
msgstr ""
msgstr "チケットのスキャンや検索を行い、エンターキーで確定してください"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:41
msgid "Load more"
msgstr ""
msgstr "もっと見る"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:42
msgid "Valid"
@@ -126,80 +123,76 @@ msgstr "キャンセル"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:46
msgid "Redeemed"
msgstr ""
msgstr "使用済"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:47
msgid "Cancel"
msgstr "キャンセル"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:48
#, fuzzy
msgid "Continue"
msgstr "次へ"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:49
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:58
msgid "Ticket not paid"
msgstr ""
msgstr "チケット未払い"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:50
#, fuzzy
msgid "This ticket is not yet paid. Do you want to continue anyways?"
msgstr "チケットの支払いが完了していません。このまま続けますか?"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:51
#, fuzzy
msgid "Additional information required"
msgstr "追加情報が必要です"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:52
#, fuzzy
msgid "Valid ticket"
msgstr "有効なチケット"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:53
msgid "Exit recorded"
msgstr ""
msgstr "記録を保存"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:54
msgid "Ticket already used"
msgstr ""
msgstr "使用済みのチケット"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:55
msgid "Information required"
msgstr ""
msgstr "情報が必要"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:56
msgid "Unknown ticket"
msgstr ""
msgstr "不明なチケット"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:57
msgid "Ticket type not allowed here"
msgstr ""
msgstr "この種類のチケットは使用できません"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:59
msgid "Entry not allowed"
msgstr ""
msgstr "入力できません"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:60
msgid "Ticket code revoked/changed"
msgstr ""
msgstr "チケットコードのブロック/変更"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:61
msgid "Order canceled"
msgstr ""
msgstr "注文の取消し"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:62
msgid "Checked-in Tickets"
msgstr ""
msgstr "チェックイン済みのチケット"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:63
msgid "Valid Tickets"
msgstr ""
msgstr "有効なチケット"
#: pretix/plugins/webcheckin/static/pretixplugins/webcheckin/main.js:64
msgid "Currently inside"
msgstr ""
msgstr "現在オンラインです"
#: pretix/static/lightbox/js/lightbox.js:96
msgid "close"
@@ -211,11 +204,14 @@ msgid ""
"Your request is currently being processed. Depending on the size of your "
"event, this might take up to a few minutes."
msgstr ""
"お客様のリクエストは現在処理中です。イベントの規模により、数分かかる場合があ"
"ります。"
#: pretix/static/pretixbase/js/asynctask.js:48
#: pretix/static/pretixbase/js/asynctask.js:124
msgid "Your request has been queued on the server and will soon be processed."
msgstr ""
"サーバへ送信されたリクエスト順にお応えしています。今しばらくお待ちください。"
#: pretix/static/pretixbase/js/asynctask.js:54
#: pretix/static/pretixbase/js/asynctask.js:130
@@ -224,34 +220,39 @@ msgid ""
"If this takes longer than two minutes, please contact us or go back in your "
"browser and try again."
msgstr ""
"お客様のリクエストがサーバーへ送信されました。現在処理の待機中です。2分以上"
"経っても応答がない場合は、弊社へお問い合わせいただくか、ブラウザを一つ前に戻"
"して再度お試しください。"
#: pretix/static/pretixbase/js/asynctask.js:89
#: pretix/static/pretixbase/js/asynctask.js:175
#: pretix/static/pretixbase/js/asynctask.js:180
#: pretix/static/pretixcontrol/js/ui/mail.js:24
msgid "An error of type {code} occurred."
msgstr ""
msgstr "{code} のエラーが発生しました。"
#: pretix/static/pretixbase/js/asynctask.js:92
msgid ""
"We currently cannot reach the server, but we keep trying. Last error code: "
"{code}"
msgstr ""
"現在サーバへの接続ができませんが、接続試行中です。エラーコード: {code}"
#: pretix/static/pretixbase/js/asynctask.js:144
#: pretix/static/pretixcontrol/js/ui/mail.js:21
msgid "The request took too long. Please try again."
msgstr ""
msgstr "リクエストの時間切れです。再試行してください。"
#: pretix/static/pretixbase/js/asynctask.js:183
#: pretix/static/pretixcontrol/js/ui/mail.js:26
msgid ""
"We currently cannot reach the server. Please try again. Error code: {code}"
msgstr ""
"現在サーバが応答していません。再試行してください。エラーコード: {code}"
#: pretix/static/pretixbase/js/asynctask.js:205
msgid "We are processing your request …"
msgstr ""
msgstr "リクエストを処理しています…"
#: pretix/static/pretixbase/js/asynctask.js:213
msgid ""
@@ -259,351 +260,358 @@ msgid ""
"than one minute, please check your internet connection and then reload this "
"page and try again."
msgstr ""
"リクエストがサーバへ送信されました。1分以上経っても応答がない場合は、イン"
"ターネット接続を確認してください。確認完了後、ウェブページを再度読込み、再試"
"行してください。"
#: pretix/static/pretixbase/js/asynctask.js:264
#: pretix/static/pretixcontrol/js/ui/main.js:34
msgid "Close message"
msgstr ""
msgstr "閉じる"
#: pretix/static/pretixcontrol/js/clipboard.js:23
msgid "Copied!"
msgstr ""
msgstr "コピー完了!"
#: pretix/static/pretixcontrol/js/clipboard.js:29
msgid "Press Ctrl-C to copy!"
msgstr ""
msgstr "Ctrl-Cを押してコピー!"
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:10
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:16
msgid "is one of"
msgstr ""
msgstr "の一つです"
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:22
msgid "is before"
msgstr ""
msgstr "の前"
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:26
msgid "is after"
msgstr ""
msgstr "の後"
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:59
msgid "Product"
msgstr ""
msgstr "商品"
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:63
msgid "Product variation"
msgstr ""
msgstr "商品の種類"
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:67
msgid "Current date and time"
msgstr ""
msgstr "現在の日時"
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:71
msgid "Number of previous entries"
msgstr ""
msgstr "これまでの入力件数"
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:75
msgid "Number of previous entries since midnight"
msgstr ""
msgstr "0時から現在までの入力件数"
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:79
msgid "Number of days with a previous entry"
msgstr ""
msgstr "これまでの入力日数"
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:97
msgid "All of the conditions below (AND)"
msgstr ""
msgstr "以下全ての条件(と)"
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:98
msgid "At least one of the conditions below (OR)"
msgstr ""
msgstr "以下の条件のうち、最低1つ(または)"
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:99
msgid "Event start"
msgstr ""
msgstr "イベント開始"
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:100
msgid "Event end"
msgstr ""
msgstr "イベント終了"
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:101
msgid "Event admission"
msgstr ""
msgstr "イベントの入場"
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:102
msgid "custom date and time"
msgstr ""
msgstr "日時確定"
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:103
msgid "custom time"
msgstr ""
msgstr "時刻確定"
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:104
msgid "Tolerance (minutes)"
msgstr ""
msgstr "許容誤差(分)"
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:105
msgid "Add condition"
msgstr ""
msgstr "条件を追加"
#: pretix/static/pretixcontrol/js/ui/checkinrules.js:106
msgid "minutes"
msgstr ""
msgstr ""
#: pretix/static/pretixcontrol/js/ui/editor.js:69
msgid "Lead Scan QR"
msgstr ""
msgstr "QRコード読み込み"
#: pretix/static/pretixcontrol/js/ui/editor.js:71
msgid "Check-in QR"
msgstr ""
msgstr "チェックイン用QRコード"
#: pretix/static/pretixcontrol/js/ui/editor.js:313
msgid "The PDF background file could not be loaded for the following reason:"
msgstr ""
msgstr "以下の理由によりPDFファイルの読み込みに失敗しました:"
#: pretix/static/pretixcontrol/js/ui/editor.js:521
msgid "Group of objects"
msgstr ""
msgstr "オブジェクトグループ"
#: pretix/static/pretixcontrol/js/ui/editor.js:527
msgid "Text object"
msgstr ""
msgstr "テキストオブジェクト"
#: pretix/static/pretixcontrol/js/ui/editor.js:529
msgid "Barcode area"
msgstr ""
msgstr "バーコードエリア"
#: pretix/static/pretixcontrol/js/ui/editor.js:531
msgid "Image area"
msgstr ""
msgstr "画像エリア"
#: pretix/static/pretixcontrol/js/ui/editor.js:533
msgid "Powered by pretix"
msgstr ""
msgstr "Pretixのイベントチケット売り場"
#: pretix/static/pretixcontrol/js/ui/editor.js:535
msgid "Object"
msgstr ""
msgstr "オブジェクト"
#: pretix/static/pretixcontrol/js/ui/editor.js:539
msgid "Ticket design"
msgstr ""
msgstr "チケットのデザイン"
#: pretix/static/pretixcontrol/js/ui/editor.js:813
msgid "Saving failed."
msgstr ""
msgstr "保存できませんでした。"
#: pretix/static/pretixcontrol/js/ui/editor.js:862
#: pretix/static/pretixcontrol/js/ui/editor.js:901
msgid "Error while uploading your PDF file, please try again."
msgstr ""
msgstr "PDFのアップロード中に問題が発生しました。再試行してください。"
#: pretix/static/pretixcontrol/js/ui/editor.js:886
msgid "Do you really want to leave the editor without saving your changes?"
msgstr ""
msgstr "変更内容を保存せずに編集を終了しますか?"
#: pretix/static/pretixcontrol/js/ui/mail.js:19
msgid "An error has occurred."
msgstr ""
msgstr "エラーが発生しました。"
#: pretix/static/pretixcontrol/js/ui/mail.js:54
msgid "Generating messages …"
msgstr ""
msgstr "メッセージを作成中…"
#: pretix/static/pretixcontrol/js/ui/main.js:70
msgid "Unknown error."
msgstr ""
msgstr "不明なエラー。"
#: pretix/static/pretixcontrol/js/ui/main.js:271
msgid "Your color has great contrast and is very easy to read!"
msgstr ""
msgstr "色彩のコントラストが良く読みやすいです!"
#: pretix/static/pretixcontrol/js/ui/main.js:275
msgid "Your color has decent contrast and is probably good-enough to read!"
msgstr ""
msgstr "色彩のコントラストは読むのに十分です!"
#: pretix/static/pretixcontrol/js/ui/main.js:279
msgid ""
"Your color has bad contrast for text on white background, please choose a "
"darker shade."
msgstr ""
msgstr "このテキストカラーは白い背景とのコントラストがよくありません。暗い色に選び直してください。"
#: pretix/static/pretixcontrol/js/ui/main.js:417
msgid "All"
msgstr ""
msgstr ""
#: pretix/static/pretixcontrol/js/ui/main.js:418
msgid "None"
msgstr ""
msgstr "ない"
#: pretix/static/pretixcontrol/js/ui/main.js:419
msgid "Search query"
msgstr ""
msgstr "検索ワード"
#: pretix/static/pretixcontrol/js/ui/main.js:422
msgid "Selected only"
msgstr ""
msgstr "選択したもののみ"
#: pretix/static/pretixcontrol/js/ui/main.js:834
msgid "Use a different name internally"
msgstr ""
msgstr "内部で別の名前を使用してください"
#: pretix/static/pretixcontrol/js/ui/main.js:870
msgid "Click to close"
msgstr ""
msgstr "クリックして閉じる"
#: pretix/static/pretixcontrol/js/ui/main.js:911
msgid "You have unsaved changes!"
msgstr ""
msgstr "保存されていない変更があります!"
#: pretix/static/pretixcontrol/js/ui/orderchange.js:25
msgid "Calculating default price…"
msgstr ""
msgstr "デフォルトの料金を計算中…"
#: pretix/static/pretixcontrol/js/ui/question.js:42
msgid "Others"
msgstr ""
msgstr "その他"
#: pretix/static/pretixcontrol/js/ui/question.js:82
msgid "Count"
msgstr ""
msgstr "総数"
#: pretix/static/pretixcontrol/js/ui/question.js:136
#: pretix/static/pretixpresale/js/ui/questions.js:269
msgid "Yes"
msgstr ""
msgstr "はい"
#: pretix/static/pretixcontrol/js/ui/question.js:137
#: pretix/static/pretixpresale/js/ui/questions.js:269
msgid "No"
msgstr ""
msgstr "いいえ"
#: pretix/static/pretixcontrol/js/ui/subevent.js:111
msgid "(one more date)"
msgid_plural "({num} more dates)"
msgstr[0] ""
msgstr[0] "({num} 他の日程)"
#: pretix/static/pretixpresale/js/ui/cart.js:43
msgid ""
"The items in your cart are no longer reserved for you. You can still "
"complete your order as long as theyre available."
msgstr ""
"カートに入っている商品は現在売り切れです。在庫があれば、このまま注文を完了す"
"ることができます。"
#: pretix/static/pretixpresale/js/ui/cart.js:45
msgid "Cart expired"
msgstr ""
msgstr "カートの有効期限が切れています"
#: pretix/static/pretixpresale/js/ui/cart.js:50
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] ""
msgstr[0] "カート内の商品の予約は {num} 分以内に完了します。"
#: pretix/static/pretixpresale/js/ui/main.js:144
#, fuzzy
msgid "The organizer keeps %(currency)s %(amount)s"
msgstr ""
msgstr "イベント開催者には%(currency)s %(amount)sが与えられます"
#: pretix/static/pretixpresale/js/ui/main.js:152
#, fuzzy
msgid "You get %(currency)s %(amount)s back"
msgstr ""
msgstr "お客様には %(currency)s %(amount)s が払い戻されます"
#: pretix/static/pretixpresale/js/ui/main.js:168
msgid "Please enter the amount the organizer can keep."
msgstr ""
msgstr "イベント開催者が受け取る料金を入力してください。"
#: pretix/static/pretixpresale/js/ui/main.js:349
#: pretix/static/pretixpresale/js/ui/main.js:361
msgid "Please enter a quantity for one of the ticket types."
msgstr ""
msgstr "商品の総数を入力してください。"
#: pretix/static/pretixpresale/js/ui/main.js:385
#: pretix/static/pretixpresale/js/ui/main.js:397
msgid "required"
msgstr ""
msgstr "必須"
#: pretix/static/pretixpresale/js/ui/main.js:488
#: pretix/static/pretixpresale/js/ui/main.js:507
#: pretix/static/pretixpresale/js/ui/main.js:500
#: pretix/static/pretixpresale/js/ui/main.js:519
msgid "Time zone:"
msgstr ""
msgstr "タイムゾーン:"
#: pretix/static/pretixpresale/js/ui/main.js:498
#: pretix/static/pretixpresale/js/ui/main.js:510
msgid "Your local time:"
msgstr ""
msgstr "現地時間:"
#: pretix/static/pretixpresale/js/widget/widget.js:17
msgctxt "widget"
msgid "Sold out"
msgstr ""
msgstr "売り切れ"
#: pretix/static/pretixpresale/js/widget/widget.js:18
msgctxt "widget"
msgid "Buy"
msgstr ""
msgstr "カート内"
#: pretix/static/pretixpresale/js/widget/widget.js:19
msgctxt "widget"
msgid "Register"
msgstr ""
msgstr "登録"
#: pretix/static/pretixpresale/js/widget/widget.js:20
msgctxt "widget"
msgid "Reserved"
msgstr ""
msgstr "予約完了"
#: pretix/static/pretixpresale/js/widget/widget.js:21
msgctxt "widget"
msgid "FREE"
msgstr ""
msgstr "無料"
#: pretix/static/pretixpresale/js/widget/widget.js:22
msgctxt "widget"
msgid "from %(currency)s %(price)s"
msgstr ""
msgstr "%(currency)s %(price)sから"
#: pretix/static/pretixpresale/js/widget/widget.js:23
msgctxt "widget"
msgid "incl. %(rate)s% %(taxname)s"
msgstr ""
msgstr "%(rate)s% %(taxname)s込"
#: pretix/static/pretixpresale/js/widget/widget.js:24
msgctxt "widget"
msgid "plus %(rate)s% %(taxname)s"
msgstr ""
msgstr "%(rate)s% %(taxname)s抜"
#: pretix/static/pretixpresale/js/widget/widget.js:25
msgctxt "widget"
msgid "incl. taxes"
msgstr ""
msgstr "税込"
#: pretix/static/pretixpresale/js/widget/widget.js:26
msgctxt "widget"
msgid "plus taxes"
msgstr ""
msgstr "税抜"
#: pretix/static/pretixpresale/js/widget/widget.js:27
#, javascript-format
msgctxt "widget"
msgid "currently available: %s"
msgstr ""
msgstr "現在%s使用可能"
#: pretix/static/pretixpresale/js/widget/widget.js:28
msgctxt "widget"
msgid "Only available with a voucher"
msgstr ""
msgstr "クーポンをお持ちの方のみ"
#: pretix/static/pretixpresale/js/widget/widget.js:29
#, javascript-format
#, fuzzy, javascript-format
msgctxt "widget"
msgid "minimum amount to order: %s"
msgstr ""
msgstr "ご注文いただける最小値:%s"
#: pretix/static/pretixpresale/js/widget/widget.js:30
msgctxt "widget"
msgid "Close ticket shop"
msgstr ""
msgstr "チケットショップ閉店"
#: pretix/static/pretixpresale/js/widget/widget.js:31
msgctxt "widget"
msgid "The ticket shop could not be loaded."
msgstr ""
msgstr "チケットショップの読み込みに失敗しました。"
#: pretix/static/pretixpresale/js/widget/widget.js:32
msgctxt "widget"
@@ -611,188 +619,192 @@ msgid ""
"There are currently a lot of users in this ticket shop. Please open the shop "
"in a new tab to continue."
msgstr ""
"現在チケットショップが混み合っています。新しいタブでチケットショップを開き続"
"行してください。"
#: pretix/static/pretixpresale/js/widget/widget.js:34
msgctxt "widget"
msgid "Open ticket shop"
msgstr ""
msgstr "チケットショップを開く"
#: pretix/static/pretixpresale/js/widget/widget.js:35
msgctxt "widget"
msgid "The cart could not be created. Please try again later"
msgstr ""
msgstr "カートの作成に失敗しました。再試行してください。"
#: pretix/static/pretixpresale/js/widget/widget.js:36
msgctxt "widget"
msgid ""
"We could not create your cart, since there are currently too many users in "
"this ticket shop. Please click \"Continue\" to retry in a new tab."
msgstr ""
msgstr "現在チケットショップが混雑しているため、お客様のカートを作ることができませんでした。新しいタブを開き「次へ」をクリックしてください。"
#: pretix/static/pretixpresale/js/widget/widget.js:38
msgctxt "widget"
msgid "Waiting list"
msgstr ""
msgstr "待機リスト"
#: pretix/static/pretixpresale/js/widget/widget.js:39
msgctxt "widget"
msgid ""
"You currently have an active cart for this event. If you select more "
"products, they will be added to your existing cart."
msgstr ""
msgstr "お客様のカートはイベントの申し込みに有効です。商品を選択し、カートへ追加してください。"
#: pretix/static/pretixpresale/js/widget/widget.js:41
msgctxt "widget"
msgid "Resume checkout"
msgstr ""
msgstr "購入を続行する"
#: pretix/static/pretixpresale/js/widget/widget.js:42
msgctxt "widget"
msgid "Redeem a voucher"
msgstr ""
msgstr "クーポンを使用する"
#: pretix/static/pretixpresale/js/widget/widget.js:43
msgctxt "widget"
msgid "Redeem"
msgstr ""
msgstr "使用する"
#: pretix/static/pretixpresale/js/widget/widget.js:44
msgctxt "widget"
msgid "Voucher code"
msgstr ""
msgstr "クーポンコード"
#: pretix/static/pretixpresale/js/widget/widget.js:45
msgctxt "widget"
msgid "Close"
msgstr ""
msgstr "閉じる"
#: pretix/static/pretixpresale/js/widget/widget.js:46
msgctxt "widget"
msgid "Continue"
msgstr ""
msgstr "続ける"
#: pretix/static/pretixpresale/js/widget/widget.js:47
#, fuzzy
msgctxt "widget"
msgid "See variations"
msgstr ""
msgstr "他の種類を見る"
#: pretix/static/pretixpresale/js/widget/widget.js:48
msgctxt "widget"
msgid "Choose a different event"
msgstr ""
msgstr "他のイベントを選択する"
#: pretix/static/pretixpresale/js/widget/widget.js:49
msgctxt "widget"
msgid "Choose a different date"
msgstr ""
msgstr "他の日付を選択する"
#: pretix/static/pretixpresale/js/widget/widget.js:50
msgctxt "widget"
msgid "Back"
msgstr ""
msgstr "戻る"
#: pretix/static/pretixpresale/js/widget/widget.js:51
msgctxt "widget"
msgid "Next month"
msgstr ""
msgstr "翌月"
#: pretix/static/pretixpresale/js/widget/widget.js:52
msgctxt "widget"
msgid "Previous month"
msgstr ""
msgstr "前月"
#: pretix/static/pretixpresale/js/widget/widget.js:53
msgctxt "widget"
msgid "Next week"
msgstr ""
msgstr "翌週"
#: pretix/static/pretixpresale/js/widget/widget.js:54
msgctxt "widget"
msgid "Previous week"
msgstr ""
msgstr "前週"
#: pretix/static/pretixpresale/js/widget/widget.js:55
#, fuzzy
msgctxt "widget"
msgid "Open seat selection"
msgstr ""
msgstr "ルームプランを開く"
#: pretix/static/pretixpresale/js/widget/widget.js:56
msgctxt "widget"
msgid "Load more"
msgstr ""
msgstr "さらに読み込む"
#: pretix/static/pretixpresale/js/widget/widget.js:58
msgid "Mo"
msgstr ""
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:59
msgid "Tu"
msgstr ""
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:60
msgid "We"
msgstr ""
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:61
msgid "Th"
msgstr ""
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:62
msgid "Fr"
msgstr ""
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:63
msgid "Sa"
msgstr ""
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:64
msgid "Su"
msgstr ""
msgstr ""
#: pretix/static/pretixpresale/js/widget/widget.js:67
msgid "January"
msgstr ""
msgstr "1月"
#: pretix/static/pretixpresale/js/widget/widget.js:68
msgid "February"
msgstr ""
msgstr "2月"
#: pretix/static/pretixpresale/js/widget/widget.js:69
msgid "March"
msgstr ""
msgstr "3月"
#: pretix/static/pretixpresale/js/widget/widget.js:70
msgid "April"
msgstr ""
msgstr "4月"
#: pretix/static/pretixpresale/js/widget/widget.js:71
msgid "May"
msgstr ""
msgstr "5月"
#: pretix/static/pretixpresale/js/widget/widget.js:72
msgid "June"
msgstr ""
msgstr "6月"
#: pretix/static/pretixpresale/js/widget/widget.js:73
msgid "July"
msgstr ""
msgstr "7月"
#: pretix/static/pretixpresale/js/widget/widget.js:74
msgid "August"
msgstr ""
msgstr "8月"
#: pretix/static/pretixpresale/js/widget/widget.js:75
msgid "September"
msgstr ""
msgstr "9月"
#: pretix/static/pretixpresale/js/widget/widget.js:76
msgid "October"
msgstr ""
msgstr "10月"
#: pretix/static/pretixpresale/js/widget/widget.js:77
msgid "November"
msgstr ""
msgstr "11月"
#: pretix/static/pretixpresale/js/widget/widget.js:78
msgid "December"
msgstr ""
msgstr "12月"
File diff suppressed because it is too large Load Diff
+8 -8
View File
@@ -7,11 +7,11 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-29 08:28+0000\n"
"POT-Creation-Date: 2022-01-14 14:33+0000\n"
"PO-Revision-Date: 2021-12-09 15:49+0000\n"
"Last-Translator: Ilona Zilgalve <i.zilgalve@riga-jurmala.com>\n"
"Language-Team: Latvian <https://translate.pretix.eu/projects/pretix/"
"pretix-js/lv/>\n"
"Language-Team: Latvian <https://translate.pretix.eu/projects/pretix/pretix-"
"js/lv/>\n"
"Language: lv\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
@@ -530,20 +530,20 @@ msgstr "Jūs saņemsiet %(valūta)s %(cena)s atpakaļ"
msgid "Please enter the amount the organizer can keep."
msgstr "Lūdzu ievadiet skaitu (summu), ko pasākuma organizators var paturēt."
#: pretix/static/pretixpresale/js/ui/main.js:349
#: pretix/static/pretixpresale/js/ui/main.js:361
msgid "Please enter a quantity for one of the ticket types."
msgstr "Lūdzu, ievadiet nepieciešamo daudzumu izvēlētajam biļešu veidam."
#: pretix/static/pretixpresale/js/ui/main.js:375
#: pretix/static/pretixpresale/js/ui/main.js:397
msgid "required"
msgstr "obligāts"
#: pretix/static/pretixpresale/js/ui/main.js:488
#: pretix/static/pretixpresale/js/ui/main.js:507
#: pretix/static/pretixpresale/js/ui/main.js:500
#: pretix/static/pretixpresale/js/ui/main.js:519
msgid "Time zone:"
msgstr "Laika zona:"
#: pretix/static/pretixpresale/js/ui/main.js:498
#: pretix/static/pretixpresale/js/ui/main.js:510
msgid "Your local time:"
msgstr "Vietējais laiks:"
File diff suppressed because it is too large Load Diff
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-30 16:13+0000\n"
"POT-Creation-Date: 2022-01-14 14:33+0000\n"
"PO-Revision-Date: 2021-05-31 11:26+0000\n"
"Last-Translator: zackern <zacker@zacker.no>\n"
"Language-Team: Norwegian Bokmål <https://translate.pretix.eu/projects/pretix/"
@@ -517,20 +517,20 @@ msgstr ""
msgid "Please enter the amount the organizer can keep."
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:349
#: pretix/static/pretixpresale/js/ui/main.js:361
msgid "Please enter a quantity for one of the ticket types."
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:385
#: pretix/static/pretixpresale/js/ui/main.js:397
msgid "required"
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:488
#: pretix/static/pretixpresale/js/ui/main.js:507
#: pretix/static/pretixpresale/js/ui/main.js:500
#: pretix/static/pretixpresale/js/ui/main.js:519
msgid "Time zone:"
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:498
#: pretix/static/pretixpresale/js/ui/main.js:510
msgid "Your local time:"
msgstr ""
File diff suppressed because it is too large Load Diff
+6 -6
View File
@@ -6,7 +6,7 @@ msgid ""
msgstr ""
"Project-Id-Version: 1\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-30 16:13+0000\n"
"POT-Creation-Date: 2022-01-14 14:33+0000\n"
"PO-Revision-Date: 2021-10-29 02:00+0000\n"
"Last-Translator: Maarten van den Berg <maartenberg1@gmail.com>\n"
"Language-Team: Dutch <https://translate.pretix.eu/projects/pretix/pretix-js/"
@@ -522,20 +522,20 @@ msgstr "U krijgt %(currency)s %(amount)s terug"
msgid "Please enter the amount the organizer can keep."
msgstr "Voer het bedrag in dat de organisator mag houden."
#: pretix/static/pretixpresale/js/ui/main.js:349
#: pretix/static/pretixpresale/js/ui/main.js:361
msgid "Please enter a quantity for one of the ticket types."
msgstr "Voer een hoeveelheid voor een van de producten in."
#: pretix/static/pretixpresale/js/ui/main.js:385
#: pretix/static/pretixpresale/js/ui/main.js:397
msgid "required"
msgstr "verplicht"
#: pretix/static/pretixpresale/js/ui/main.js:488
#: pretix/static/pretixpresale/js/ui/main.js:507
#: pretix/static/pretixpresale/js/ui/main.js:500
#: pretix/static/pretixpresale/js/ui/main.js:519
msgid "Time zone:"
msgstr "Tijdzone:"
#: pretix/static/pretixpresale/js/ui/main.js:498
#: pretix/static/pretixpresale/js/ui/main.js:510
msgid "Your local time:"
msgstr "Uw lokale tijd:"
File diff suppressed because it is too large Load Diff
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-30 16:13+0000\n"
"POT-Creation-Date: 2022-01-14 14:33+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Automatically generated\n"
"Language-Team: none\n"
@@ -504,20 +504,20 @@ msgstr ""
msgid "Please enter the amount the organizer can keep."
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:349
#: pretix/static/pretixpresale/js/ui/main.js:361
msgid "Please enter a quantity for one of the ticket types."
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:385
#: pretix/static/pretixpresale/js/ui/main.js:397
msgid "required"
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:488
#: pretix/static/pretixpresale/js/ui/main.js:507
#: pretix/static/pretixpresale/js/ui/main.js:500
#: pretix/static/pretixpresale/js/ui/main.js:519
msgid "Time zone:"
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:498
#: pretix/static/pretixpresale/js/ui/main.js:510
msgid "Your local time:"
msgstr ""
File diff suppressed because it is too large Load Diff
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-30 16:13+0000\n"
"POT-Creation-Date: 2022-01-14 14:33+0000\n"
"PO-Revision-Date: 2021-08-05 04:00+0000\n"
"Last-Translator: Maarten van den Berg <maartenberg1@gmail.com>\n"
"Language-Team: Dutch (informal) <https://translate.pretix.eu/projects/pretix/"
@@ -532,20 +532,20 @@ msgstr "Jij krijgt %(currency)s %(amount)s terug"
msgid "Please enter the amount the organizer can keep."
msgstr "Voer het bedrag in dat de organisator mag houden."
#: pretix/static/pretixpresale/js/ui/main.js:349
#: pretix/static/pretixpresale/js/ui/main.js:361
msgid "Please enter a quantity for one of the ticket types."
msgstr "Voer een hoeveelheid voor een van de producten in."
#: pretix/static/pretixpresale/js/ui/main.js:385
#: pretix/static/pretixpresale/js/ui/main.js:397
msgid "required"
msgstr "verplicht"
#: pretix/static/pretixpresale/js/ui/main.js:488
#: pretix/static/pretixpresale/js/ui/main.js:507
#: pretix/static/pretixpresale/js/ui/main.js:500
#: pretix/static/pretixpresale/js/ui/main.js:519
msgid "Time zone:"
msgstr "Tijdzone:"
#: pretix/static/pretixpresale/js/ui/main.js:498
#: pretix/static/pretixpresale/js/ui/main.js:510
msgid "Your local time:"
msgstr "Je lokale tijd:"
File diff suppressed because it is too large Load Diff
+6 -6
View File
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-30 16:13+0000\n"
"POT-Creation-Date: 2022-01-14 14:33+0000\n"
"PO-Revision-Date: 2019-09-24 19:00+0000\n"
"Last-Translator: Serge Bazanski <q3k@hackerspace.pl>\n"
"Language-Team: Polish <https://translate.pretix.eu/projects/pretix/pretix-js/"
@@ -570,22 +570,22 @@ msgstr "od %(currency)s %(price)s"
msgid "Please enter the amount the organizer can keep."
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:349
#: pretix/static/pretixpresale/js/ui/main.js:361
msgid "Please enter a quantity for one of the ticket types."
msgstr "Proszę wybrać liczbę dla jednego z typów biletów."
#: pretix/static/pretixpresale/js/ui/main.js:385
#: pretix/static/pretixpresale/js/ui/main.js:397
#, fuzzy
#| msgid "Cart expired"
msgid "required"
msgstr "Koszyk wygasł"
#: pretix/static/pretixpresale/js/ui/main.js:488
#: pretix/static/pretixpresale/js/ui/main.js:507
#: pretix/static/pretixpresale/js/ui/main.js:500
#: pretix/static/pretixpresale/js/ui/main.js:519
msgid "Time zone:"
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:498
#: pretix/static/pretixpresale/js/ui/main.js:510
msgid "Your local time:"
msgstr ""
File diff suppressed because it is too large Load Diff
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-30 16:13+0000\n"
"POT-Creation-Date: 2022-01-14 14:33+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: Automatically generated\n"
"Language-Team: none\n"
@@ -507,20 +507,20 @@ msgstr ""
msgid "Please enter the amount the organizer can keep."
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:349
#: pretix/static/pretixpresale/js/ui/main.js:361
msgid "Please enter a quantity for one of the ticket types."
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:385
#: pretix/static/pretixpresale/js/ui/main.js:397
msgid "required"
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:488
#: pretix/static/pretixpresale/js/ui/main.js:507
#: pretix/static/pretixpresale/js/ui/main.js:500
#: pretix/static/pretixpresale/js/ui/main.js:519
msgid "Time zone:"
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:498
#: pretix/static/pretixpresale/js/ui/main.js:510
msgid "Your local time:"
msgstr ""
File diff suppressed because it is too large Load Diff
+6 -6
View File
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-30 16:13+0000\n"
"POT-Creation-Date: 2022-01-14 14:33+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -505,20 +505,20 @@ msgstr ""
msgid "Please enter the amount the organizer can keep."
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:349
#: pretix/static/pretixpresale/js/ui/main.js:361
msgid "Please enter a quantity for one of the ticket types."
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:385
#: pretix/static/pretixpresale/js/ui/main.js:397
msgid "required"
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:488
#: pretix/static/pretixpresale/js/ui/main.js:507
#: pretix/static/pretixpresale/js/ui/main.js:500
#: pretix/static/pretixpresale/js/ui/main.js:519
msgid "Time zone:"
msgstr ""
#: pretix/static/pretixpresale/js/ui/main.js:498
#: pretix/static/pretixpresale/js/ui/main.js:510
msgid "Your local time:"
msgstr ""

Some files were not shown because too many files have changed in this diff Show More