* Paging (gibts etwas von sqlalchemy)

This commit is contained in:
Daniel Grams 2020-07-31 16:02:55 +02:00
parent 9f08479be4
commit 6af7280908
11 changed files with 145 additions and 88 deletions

98
app.py
View File

@ -701,6 +701,24 @@ def assign_location_values(target, origin):
target.latitude = origin.latitude
target.longitude = origin.longitude
def get_pagination_urls(pagination, **kwargs):
result = {}
if pagination.has_prev:
args = request.args.copy()
args.update(kwargs)
args["page"] = pagination.prev_num
result["prev_url"] = url_for(request.endpoint, **args)
if pagination.has_next:
args = request.args.copy()
args.update(kwargs)
args["page"] = pagination.next_num
result["next_url"] = url_for(request.endpoint, **args)
return result
# Routes
@app.before_first_request
@ -1119,7 +1137,7 @@ def event_delete(event_id):
db.session.delete(event)
db.session.commit()
flash(gettext('Event successfully deleted'), 'success')
return redirect(url_for('manage_organizer_events', id=event.organizer_id))
return redirect(url_for('manage_organizer_events', organizer_id=event.organizer_id))
except SQLAlchemyError as e:
db.session.rollback()
flash(handleSqlError(e), 'danger')
@ -1178,11 +1196,12 @@ def manage_admin_unit(id):
@app.route('/manage/admin_unit/<int:id>/organizers')
def manage_admin_unit_organizers(id):
admin_unit = get_admin_unit_for_manage_or_404(id)
organizers = EventOrganizer.query.filter(EventOrganizer.admin_unit_id == admin_unit.id).order_by(func.lower(EventOrganizer.name)).all()
organizers = EventOrganizer.query.filter(EventOrganizer.admin_unit_id == admin_unit.id).order_by(func.lower(EventOrganizer.name)).paginate()
return render_template('manage/organizers.html',
admin_unit=admin_unit,
organizers=organizers)
organizers=organizers.items,
pagination=get_pagination_urls(organizers, id=id))
@app.route('/manage/admin_unit/<int:id>/event_places')
def manage_admin_unit_event_places(id):
@ -1190,30 +1209,28 @@ def manage_admin_unit_event_places(id):
organizer = EventOrganizer.query.filter(EventOrganizer.admin_unit_id == admin_unit.id).order_by(func.lower(EventOrganizer.name)).first()
if organizer:
return redirect(url_for('manage_organizer_event_places', id=organizer.id))
return redirect(url_for('manage_organizer_event_places', organizer_id=organizer.id))
abort(404)
from forms.event_place import FindEventPlaceForm
@app.route('/manage/organizer/<int:id>/event_places', methods=('GET', 'POST'))
def manage_organizer_event_places(id):
organizer = EventOrganizer.query.get_or_404(id)
@app.route('/manage/event_places')
def manage_organizer_event_places():
organizer = EventOrganizer.query.get_or_404(request.args.get('organizer_id'))
admin_unit = get_admin_unit_for_manage_or_404(organizer.admin_unit_id)
organizers = EventOrganizer.query.filter(EventOrganizer.admin_unit_id == admin_unit.id).order_by(func.lower(EventOrganizer.name)).all()
form = FindEventPlaceForm(organizer_id=organizer.id)
form = FindEventPlaceForm(**request.args)
form.organizer_id.choices = [(o.id, o.name) for o in organizers]
if form.validate_on_submit():
return redirect(url_for('manage_organizer_event_places', id=form.organizer_id.data))
places = EventPlace.query.filter(EventPlace.organizer_id == organizer.id).order_by(func.lower(EventPlace.name)).all()
places = EventPlace.query.filter(EventPlace.organizer_id == organizer.id).order_by(func.lower(EventPlace.name)).paginate()
return render_template('manage/places.html',
admin_unit=admin_unit,
organizer=organizer,
form=form,
places=places)
places=places.items,
pagination=get_pagination_urls(places))
@app.route('/manage/admin_unit/<int:id>/events')
def manage_admin_unit_events(id):
@ -1221,29 +1238,22 @@ def manage_admin_unit_events(id):
organizer = EventOrganizer.query.filter(EventOrganizer.admin_unit_id == admin_unit.id).order_by(func.lower(EventOrganizer.name)).first()
if organizer:
return redirect(url_for('manage_organizer_events', id=organizer.id))
return redirect(url_for('manage_organizer_events', organizer_id=organizer.id))
abort(404)
from forms.event import FindEventForm
@app.route('/manage/organizer/<int:id>/events', methods=('GET', 'POST'))
def manage_organizer_events(id):
organizer = EventOrganizer.query.get_or_404(id)
@app.route('/manage/events')
def manage_organizer_events():
organizer = EventOrganizer.query.get_or_404(request.args.get('organizer_id'))
admin_unit = get_admin_unit_for_manage_or_404(organizer.admin_unit_id)
organizers = EventOrganizer.query.filter(EventOrganizer.admin_unit_id == admin_unit.id).order_by(func.lower(EventOrganizer.name)).all()
form = FindEventForm(organizer_id=organizer.id)
form.organizer_id.choices = [(o.id, o.name) for o in organizers]
keyword = request.args.get('keyword') if 'keyword' in request.args else ""
if form.validate_on_submit():
if form.organizer_id.data != organizer.id:
return redirect(url_for('manage_organizer_events', id=form.organizer_id.data, keyword=keyword))
if form.keyword.data:
keyword = form.keyword.data
form = FindEventForm(**request.args)
form.organizer_id.choices = [(o.id, o.name) for o in organizers]
if keyword:
like_keyword = '%' + keyword + '%'
@ -1251,12 +1261,13 @@ def manage_organizer_events(id):
else:
event_filter = Event.organizer_id == organizer.id
events = Event.query.filter(event_filter).order_by(Event.start).all()
events = Event.query.filter(event_filter).order_by(Event.start).paginate()
return render_template('manage/events.html',
admin_unit=admin_unit,
organizer=organizer,
form=form,
events=events)
events=events.items,
pagination=get_pagination_urls(events))
@app.route('/organizer/<int:id>')
def organizer(id):
@ -1373,7 +1384,7 @@ def event_place_update(id):
try:
db.session.commit()
flash(gettext('Place successfully updated'), 'success')
return redirect(url_for('manage_organizer_event_places', id=place.organizer.id))
return redirect(url_for('manage_organizer_event_places', organizer_id=place.organizer.id))
except SQLAlchemyError as e:
db.session.rollback()
flash(handleSqlError(e), 'danger')
@ -1402,7 +1413,7 @@ def manage_organizer_places_create(id):
db.session.add(place)
db.session.commit()
flash(gettext('Place successfully created'), 'success')
return redirect(url_for('manage_organizer_event_places', id=organizer.id))
return redirect(url_for('manage_organizer_event_places', organizer_id=organizer.id))
except SQLAlchemyError as e:
db.session.rollback()
flash(handleSqlError(e), 'danger')
@ -1422,38 +1433,43 @@ def form_input_to_date(date_str, hour=0, minute=0, second=0):
def form_input_from_date(date):
return date.strftime("%Y-%m-%d")
@app.route("/<string:au_short_name>/widget/eventdates", methods=('GET', 'POST'))
@app.route("/<string:au_short_name>/widget/eventdates")
def widget_event_dates(au_short_name):
admin_unit = AdminUnit.query.filter(AdminUnit.short_name == au_short_name).first_or_404()
date_from = today
date_to = date_set_end_of_day(today + relativedelta(days=7))
date_to = date_set_end_of_day(today + relativedelta(months=12))
date_from_str = form_input_from_date(date_from)
date_to_str = form_input_from_date(date_to)
keyword = ''
if request.method == 'POST':
date_from_str = request.form['date_from']
date_to_str = request.form['date_to']
if 'date_from' in request.args:
date_from_str = request.args['date_from']
date_from = form_input_to_date(date_from_str)
date_to = form_input_to_date(date_to_str, 23, 59, 59)
if 'keyword' in request.form:
keyword = request.form['keyword']
if 'date_to' in request.args:
date_to_str = request.args['date_to']
date_to = form_input_to_date(date_to_str)
if 'keyword' in request.args:
keyword = request.args['keyword']
date_filter = and_(EventDate.start >= date_from, EventDate.start < date_to)
if keyword:
like_keyword = '%' + keyword + '%'
dates = EventDate.query.join(Event).filter(date_filter).filter(and_(Event.admin_unit_id == admin_unit.id, Event.verified, or_(Event.name.ilike(like_keyword), Event.description.ilike(like_keyword), Event.tags.ilike(like_keyword)))).order_by(EventDate.start).all()
event_filter = and_(Event.admin_unit_id == admin_unit.id, Event.verified, or_(Event.name.ilike(like_keyword), Event.description.ilike(like_keyword), Event.tags.ilike(like_keyword)))
else:
dates = EventDate.query.join(Event).filter(date_filter).filter(and_(Event.admin_unit_id == admin_unit.id, Event.verified)).order_by(EventDate.start).all()
event_filter = and_(Event.admin_unit_id == admin_unit.id, Event.verified)
dates = EventDate.query.join(Event).filter(date_filter).filter(event_filter).order_by(EventDate.start).paginate()
return render_template('widget/event_date/list.html',
date_from_str=date_from_str,
date_to_str=date_to_str,
keyword=keyword,
dates=dates)
dates=dates.items,
pagination=get_pagination_urls(dates, au_short_name=au_short_name))
@app.route('/widget/eventdate/<int:id>')
def widget_event_date(id):

View File

@ -107,6 +107,8 @@ class DeleteEventForm(FlaskForm):
name = StringField(lazy_gettext('Name'), validators=[DataRequired()])
class FindEventForm(FlaskForm):
class Meta:
csrf = False
submit = SubmitField(lazy_gettext("Find events"))
keyword = StringField(lazy_gettext('Keyword'), validators=[Optional()])
organizer_id = SelectField(lazy_gettext('Organizer'), validators=[DataRequired()], coerce=int)

View File

@ -38,5 +38,7 @@ class UpdateEventPlaceForm(BaseEventPlaceForm):
submit = SubmitField(lazy_gettext("Update place"))
class FindEventPlaceForm(FlaskForm):
class Meta:
csrf = False
submit = SubmitField(lazy_gettext("Find places"))
organizer_id = SelectField(lazy_gettext('Organizer'), validators=[DataRequired()], coerce=int)

View File

@ -20,6 +20,6 @@ body {
background-color: transparent;
}
.card-title {
.card-title, .page-link, .page-link:hover {
color: #7B2424;
}

View File

@ -487,4 +487,23 @@ $( function() {
});
});
</script>
{% endmacro %}
{% macro render_pagination(pagination) %}
{% if 'prev_url' in pagination or 'next_url' in pagination %}
<nav aria-label="Page navigation example">
<ul class="pagination">
{% if pagination['prev_url'] %}
<li class="page-item"> <a class="page-link" href="{{ pagination['prev_url'] }}">{{ _('Previous') }}</a></li>
{% else %}
<li class="page-item"><a class="page-link btn disabled" href="#">{{ _('Previous') }}</a></li>
{% endif %}
{% if pagination['next_url'] %}
<li class="page-item"> <a class="page-link" href="{{ pagination['next_url'] }}">{{ _('Next') }}</a></li>
{% else %}
<li class="page-item"><a class="page-link btn disabled" href="#">{{ _('Next') }}</a></li>
{% endif %}
</ul>
</nav>
{% endif %}
{% endmacro %}

View File

@ -1,5 +1,5 @@
{% extends "layout.html" %}
{% from "_macros.html" import render_event_date, render_field_with_errors, render_event_organizer, render_manage_menu %}
{% from "_macros.html" import render_pagination, render_event_date, render_field_with_errors, render_event_organizer, render_manage_menu %}
{% block title %}
{{ _('Events') }}
{% endblock %}
@ -10,7 +10,7 @@
{{ render_manage_menu(admin_unit, 'events') }}
<div class="my-4">
<form action="" class="form-inline" method="POST">
<form action="" class="form-inline" method="GET">
{{ form.hidden_tag() }}
<div class="input-group mb-2 mr-sm-2">
@ -52,4 +52,6 @@
{% endfor %}
</ul>
<div class="my-4">{{ render_pagination(pagination) }}</div>
{% endblock %}

View File

@ -1,5 +1,5 @@
{% extends "layout.html" %}
{% from "_macros.html" import render_event_organizer, render_manage_menu %}
{% from "_macros.html" import render_pagination, render_event_organizer, render_manage_menu %}
{% block title %}
{{ _('Organizers') }}
{% endblock %}
@ -29,4 +29,6 @@
{% endfor %}
</ul>
<div class="my-4">{{ render_pagination(pagination) }}</div>
{% endblock %}

View File

@ -1,5 +1,5 @@
{% extends "layout.html" %}
{% from "_macros.html" import render_field_with_errors, render_event_organizer, render_manage_menu %}
{% from "_macros.html" import render_pagination, render_field_with_errors, render_event_organizer, render_manage_menu %}
{% block title %}
{{ _('Places') }}
{% endblock %}
@ -10,7 +10,7 @@
{{ render_manage_menu(admin_unit, 'places') }}
<div class="my-4">
<form action="" class="form-inline" method="POST">
<form action="" class="form-inline" method="GET">
{{ form.hidden_tag() }}
<div class="input-group mb-2 mr-sm-2">
@ -39,4 +39,6 @@
{% endfor %}
</ul>
<div class="my-4">{{ render_pagination(pagination) }}</div>
{% endblock %}

View File

@ -1,5 +1,5 @@
{% extends "layout.html" %}
{% from "_macros.html" import render_event_status_pill, render_event_status_pill, render_ooa, render_place, render_events_sub_menu %}
{% from "_macros.html" import render_pagination, render_event_status_pill, render_event_status_pill, render_ooa, render_place, render_events_sub_menu %}
{% block title %}
{{ _('Widget') }}
{% endblock %}
@ -10,7 +10,7 @@
{% endblock %}
{% block content %}
<form action="{{ url_for('widget_event_dates', au_short_name='goslar') }}" class="form-inline mb-4" method="POST" autocomplete="off">
<form action="{{ url_for('widget_event_dates', au_short_name='goslar') }}" class="form-inline mb-4" method="GET" autocomplete="off">
<div class="input-group mb-2 mr-sm-2">
<div class="input-group-prepend">
@ -88,4 +88,6 @@
{% endfor %}
{{ render_pagination(pagination) }}
{% endblock %}

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2020-07-31 08:33+0200\n"
"POT-Creation-Date: 2020-07-31 14:53+0200\n"
"PO-Revision-Date: 2020-06-07 18:51+0200\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language: de\n"
@ -102,60 +102,60 @@ msgstr "Sonstiges"
msgid "Typical Age range"
msgstr "Typische Altersspanne"
#: app.py:718
#: app.py:713
#, python-format
msgid "Error in the %s field - %s"
msgstr "Fehler im Feld %s: %s"
#: app.py:770
#: app.py:765
msgid "Admin unit successfully updated"
msgstr "Verwaltungseinheit erfolgreich aktualisiert"
#: app.py:828
#: app.py:823
msgid "Organization successfully created"
msgstr "Organisation erfolgreich erstellt"
#: app.py:849
#: app.py:844
msgid "Organization successfully updated"
msgstr "Organisation erfolgreich aktualisiert"
#: app.py:909 app.py:1380
#: app.py:904 app.py:1375
msgid "Place successfully updated"
msgstr "Ort erfolgreich aktualisiert"
#: app.py:933 app.py:1409
#: app.py:928 app.py:1404
msgid "Place successfully created"
msgstr "Ort erfolgreich erstellt"
#: app.py:1063
#: app.py:1058
msgid "Event successfully created"
msgstr "Veranstaltung erfolgreich erstellt"
#: app.py:1098
#: app.py:1093
msgid "Event successfully updated"
msgstr "Veranstaltung erfolgreich aktualisiert"
#: app.py:1121
#: app.py:1116
msgid "Entered name does not match event name"
msgstr "Der eingegebene Name entspricht nicht dem Namen der Veranstaltung"
#: app.py:1126
#: app.py:1121
msgid "Event successfully deleted"
msgstr "Veranstaltung erfolgreich gelöscht"
#: app.py:1296
#: app.py:1291
msgid "Organizer successfully created"
msgstr "Veranstalter erfolgreich erstellt"
#: app.py:1318
#: app.py:1313
msgid "Organizer successfully updated"
msgstr "Veranstalter erfolgreich aktualisiert"
#: app.py:1340
#: app.py:1335
msgid "Entered name does not match organizer name"
msgstr "Der eingegebene Name entspricht nicht dem Namen des Veranstalters"
#: app.py:1345
#: app.py:1340
msgid "Organizer successfully deleted"
msgstr "Veranstalter erfolgreich gelöscht"
@ -163,38 +163,38 @@ msgstr "Veranstalter erfolgreich gelöscht"
msgid "Successfully signed in."
msgstr "Erfolgreich eingeloggt."
#: forms/admin_unit.py:11 forms/event.py:12 forms/event_place.py:11
#: forms/admin_unit.py:11 forms/event.py:12 forms/event_place.py:12
#: forms/organization.py:11 forms/organizer.py:11 forms/place.py:9
msgid "Street"
msgstr "Straße"
#: forms/admin_unit.py:12 forms/event.py:13 forms/event_place.py:12
#: forms/admin_unit.py:12 forms/event.py:13 forms/event_place.py:13
#: forms/organization.py:12 forms/organizer.py:12 forms/place.py:10
msgid "Postal code"
msgstr "Postleitzahl"
#: forms/admin_unit.py:13 forms/event.py:14 forms/event_place.py:13
#: forms/admin_unit.py:13 forms/event.py:14 forms/event_place.py:14
#: forms/organization.py:13 forms/organizer.py:13 forms/place.py:11
msgid "City"
msgstr "Stadt/Ort"
#: forms/admin_unit.py:14 forms/event_place.py:14 forms/organization.py:14
#: forms/admin_unit.py:14 forms/event_place.py:15 forms/organization.py:14
#: forms/organizer.py:14 forms/place.py:12
msgid "State"
msgstr "Bundesland"
#: forms/admin_unit.py:15 forms/event_place.py:15 forms/organization.py:15
#: forms/admin_unit.py:15 forms/event_place.py:16 forms/organization.py:15
#: forms/organizer.py:15 forms/place.py:13
msgid "Latitude"
msgstr "Breitengrad"
#: forms/admin_unit.py:16 forms/event_place.py:16 forms/organization.py:16
#: forms/admin_unit.py:16 forms/event_place.py:17 forms/organization.py:16
#: forms/organizer.py:16 forms/place.py:14
msgid "Longitude"
msgstr "Längengrad"
#: forms/admin_unit.py:19 forms/event.py:17 forms/event.py:35
#: forms/event.py:107 forms/event_place.py:21 forms/organization.py:19
#: forms/event.py:107 forms/event_place.py:20 forms/organization.py:19
#: forms/organizer.py:19 forms/organizer.py:41 forms/place.py:19
#: templates/_macros.html:98 templates/admin/admin_units.html:18
#: templates/admin_unit/list.html:13 templates/admin_unit/read.html:66
@ -214,7 +214,7 @@ msgid "Short name must contain only letters numbers or underscore"
msgstr "Der Kurzname darf nur Buchstaben, Nummern und Unterstriche enthalten"
#: forms/admin_unit.py:21 forms/event.py:29 forms/event.py:36
#: forms/event_place.py:22 forms/organization.py:20 forms/organizer.py:20
#: forms/event_place.py:21 forms/organization.py:20 forms/organizer.py:20
#: forms/place.py:20
msgid "Link URL"
msgstr "Link URL"
@ -238,7 +238,7 @@ msgstr "Fax"
msgid "Logo"
msgstr "Logo"
#: forms/admin_unit.py:25 forms/event.py:64 forms/event_place.py:23
#: forms/admin_unit.py:25 forms/event.py:64 forms/event_place.py:22
#: forms/organization.py:24 forms/organizer.py:24 forms/place.py:21
msgid "Images only!"
msgstr "Nur Fotos!"
@ -252,7 +252,7 @@ msgstr "Verwaltungseinheit erstellen"
msgid "Update admin unit"
msgstr "Verwaltungseinheit aktualisieren"
#: forms/event.py:19 forms/event_place.py:26
#: forms/event.py:19 forms/event_place.py:33 forms/event_place.py:37
msgid "Other organizers can use this location"
msgstr "Andere Veranstalter können diesen Ort verwenden"
@ -264,7 +264,7 @@ msgstr "Organisator"
msgid "Ticket Link URL"
msgstr "Ticket Link"
#: forms/event.py:38 forms/event_place.py:24 forms/place.py:22
#: forms/event.py:38 forms/event_place.py:23 forms/place.py:22
msgid "Description"
msgstr "Beschreibung"
@ -288,8 +288,8 @@ msgstr "Vorheriges Startdatum"
msgid "Tags"
msgstr "Stichworte"
#: forms/event.py:45 forms/event.py:112 forms/event_place.py:33
#: templates/_macros.html:356 templates/event/create.html:59
#: forms/event.py:45 forms/event.py:112 forms/event_place.py:42
#: templates/_macros.html:336 templates/event/create.html:59
#: templates/event/update.html:46 templates/manage/events.html:18
#: templates/manage/places.html:18 templates/organizer/create.html:16
#: templates/organizer/delete.html:13 templates/organizer/update.html:16
@ -300,7 +300,7 @@ msgstr "Veranstalter"
msgid "Category"
msgstr "Kategorie"
#: forms/event.py:47 forms/organization.py:37 templates/_macros.html:371
#: forms/event.py:47 forms/organization.py:37 templates/_macros.html:351
#: templates/admin_unit/update.html:16 templates/event/update.html:91
#: templates/organization/create.html:58
msgid "Admin unit"
@ -354,7 +354,7 @@ msgstr "Online"
msgid "EventAttendanceMode.mixed"
msgstr "Online und offline"
#: forms/event.py:64 forms/event_place.py:23 forms/place.py:21
#: forms/event.py:64 forms/event_place.py:22 forms/place.py:21
msgid "Photo"
msgstr "Foto"
@ -426,20 +426,20 @@ msgstr "Veranstaltungen finden"
msgid "Keyword"
msgstr "Stichwort"
#: forms/event_place.py:19 forms/place.py:17
#: forms/event_place.py:34 forms/place.py:17
#: templates/event_place/create.html:10 templates/event_place/list.html:11
#: templates/manage/places.html:26 templates/place/create.html:10
#: templates/place/list.html:11
msgid "Create place"
msgstr "Ort hinzufügen"
#: forms/event_place.py:29 forms/place.py:26 templates/event_place/read.html:12
#: forms/event_place.py:38 forms/place.py:26 templates/event_place/read.html:12
#: templates/event_place/update.html:10 templates/place/read.html:12
#: templates/place/update.html:10
msgid "Update place"
msgstr "Ort aktualisieren"
#: forms/event_place.py:32
#: forms/event_place.py:41
msgid "Find places"
msgstr "Orte finden"
@ -516,30 +516,30 @@ msgstr "Veranstaltung"
msgid "%(count)d event dates"
msgstr "%(count)d Termine"
#: templates/_macros.html:326 templates/_macros.html:346
#: templates/_macros.html:326
msgid "Show directions"
msgstr "Anreise planen"
#: templates/_macros.html:395
#: templates/_macros.html:375
msgid "Sign in with Google"
msgstr "Mit Google anmelden"
#: templates/_macros.html:455
#: templates/_macros.html:435
msgid "Search location on Google"
msgstr "Ort bei Google suchen"
#: templates/_macros.html:475 templates/admin_unit/read.html:30
#: templates/_macros.html:455 templates/admin_unit/read.html:30
#: templates/event/list.html:4 templates/event/list.html:8
#: templates/event_place/read.html:22 templates/manage/events.html:4
#: templates/organization/read.html:27 templates/place/read.html:22
msgid "Events"
msgstr "Veranstaltungen"
#: templates/_macros.html:476 templates/manage/organizers.html:4
#: templates/_macros.html:456 templates/manage/organizers.html:4
msgid "Organizers"
msgstr "Veranstalter"
#: templates/_macros.html:477 templates/event_place/list.html:3
#: templates/_macros.html:457 templates/event_place/list.html:3
#: templates/event_place/list.html:7 templates/manage/places.html:4
#: templates/place/list.html:3 templates/place/list.html:7
msgid "Places"
@ -673,6 +673,16 @@ msgstr "Von"
msgid "to"
msgstr "bis"
#: templates/widget/event_date/list.html:94
#: templates/widget/event_date/list.html:96
msgid "Previous"
msgstr "Zurück"
#: templates/widget/event_date/list.html:99
#: templates/widget/event_date/list.html:101
msgid "Next"
msgstr "Weiter"
#~ msgid "You"
#~ msgstr "Du"