diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 8c6a5552220106c364330db2f1952b9d568ab6d4..74ee2f25784f8ba6aff67d3ac2d594a22c0b0758 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -9,6 +9,51 @@ and this project adheres to `Semantic Versioning`_.
 Unreleased
 ----------
 
+Fixed
+~~~~~
+
+* Migration added in 2.7.2 did not work in all scenarios
+* [Dev] Field change tracking API for Person was broken in 2.7.2
+
+`2.7.2`_ - 2022-01-31
+---------------------
+
+Changed
+~~~~~~~
+
+* [Dev] The (undocumented) setting PDF_CONTEXT_PROCESSORS is now named NON_REQUEST_CONTEXT_PROCESSORS
+* [Docker] Cache is now cleared if migrations are applied
+* Update German translations.
+
+Fixed
+~~~~~
+
+* Celery progress could be inaccurate if recording progress during a transaction
+
+
+`2.7.1`_ - 2022-01-28
+---------------------
+
+Changed
+~~~~~~~
+
+* PWA icons can now be marked maskable
+* [OAuth] Expired tokens are now cleared in a periodic task
+* PDF file jobs are now automatically expired
+* Data checks are now scheduled every 15 minutes by default
+
+Fixed
+~~~~~
+
+* PDF generation failed with S3 storage due to incompatibility with boto3
+* PWA theme colour defaulted to red
+* Form for editing group type displayed irrelevant fields
+* Permission groups could get outdated if re-assigning a user account to a different person
+* User preferences didn't work correctly sometimes due to race conditions.
+
+`2.7`_ - 2022-01-24
+-------------------
+
 Added
 ~~~~~
 
@@ -670,3 +715,6 @@ Fixed
 .. _2.4: https://edugit.org/AlekSIS/Official/AlekSIS/-/tags/2.4
 .. _2.5: https://edugit.org/AlekSIS/Official/AlekSIS/-/tags/2.5
 .. _2.6: https://edugit.org/AlekSIS/Official/AlekSIS/-/tags/2.6
+.. _2.7: https://edugit.org/AlekSIS/Official/AlekSIS/-/tags/2.7
+.. _2.7.1: https://edugit.org/AlekSIS/Official/AlekSIS/-/tags/2.7.1
+.. _2.7.2: https://edugit.org/AlekSIS/Official/AlekSIS/-/tags/2.7.2
diff --git a/aleksis/core/data_checks.py b/aleksis/core/data_checks.py
index e077f4ccd6175837eedce1814778341fe2772b66..d82c30d5ddf0b5ab11e7b1b5f8c2a595838c07e1 100644
--- a/aleksis/core/data_checks.py
+++ b/aleksis/core/data_checks.py
@@ -1,4 +1,5 @@
 import logging
+from datetime import timedelta
 
 from django.apps import apps
 from django.contrib.contenttypes.models import ContentType
@@ -236,7 +237,7 @@ class DataCheckRegistry:
         return [(check.name, check.verbose_name) for check in cls.data_checks]
 
 
-@recorded_task
+@recorded_task(run_every=timedelta(minutes=15))
 def check_data(recorder: ProgressRecorder):
     """Execute all registered data checks and send email if activated."""
     for check in recorder.iterate(DataCheckRegistry.data_checks):
diff --git a/aleksis/core/forms.py b/aleksis/core/forms.py
index f313c365e6bdb8d92b6c72cf9747aeadc9a0e367..58bbba7f63869e1212c50ecd7131fdcd4e72999a 100644
--- a/aleksis/core/forms.py
+++ b/aleksis/core/forms.py
@@ -353,7 +353,7 @@ class EditGroupTypeForm(forms.ModelForm):
 
     class Meta:
         model = GroupType
-        exclude = []
+        fields = ["name", "description"]
 
 
 class SchoolTermForm(ExtensibleForm):
diff --git a/aleksis/core/locale/ar/LC_MESSAGES/django.po b/aleksis/core/locale/ar/LC_MESSAGES/django.po
index 481291cc4af7081e88804d25896eeca0053213f1..639948d3fae74fb482f0919b2d67f3162378c6ee 100644
--- a/aleksis/core/locale/ar/LC_MESSAGES/django.po
+++ b/aleksis/core/locale/ar/LC_MESSAGES/django.po
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: AlekSIS (School Information System) 0.1\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2022-01-10 17:26+0100\n"
+"POT-Creation-Date: 2022-01-31 17:03+0100\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"
@@ -18,51 +18,51 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
 
-#: aleksis/core/apps.py:154
+#: aleksis/core/apps.py:166
 msgid "OpenID Connect scope"
 msgstr ""
 
-#: aleksis/core/apps.py:155
+#: aleksis/core/apps.py:167
 msgid "Given name, family name, link to profile and picture if existing."
 msgstr ""
 
-#: aleksis/core/apps.py:156
+#: aleksis/core/apps.py:168
 msgid "Full home postal address"
 msgstr ""
 
-#: aleksis/core/apps.py:157
+#: aleksis/core/apps.py:169
 msgid "Email address"
 msgstr ""
 
-#: aleksis/core/apps.py:158
+#: aleksis/core/apps.py:170
 msgid "Home and mobile phone"
 msgstr ""
 
-#: aleksis/core/apps.py:159 aleksis/core/forms.py:223 aleksis/core/menus.py:265
-#: aleksis/core/models.py:449 aleksis/core/templates/core/group/list.html:8
+#: aleksis/core/apps.py:171 aleksis/core/forms.py:218 aleksis/core/menus.py:265
+#: aleksis/core/models.py:462 aleksis/core/templates/core/group/list.html:8
 #: aleksis/core/templates/core/group/list.html:9
-#: aleksis/core/templates/core/person/full.html:242
+#: aleksis/core/templates/core/person/full.html:250
 msgid "Groups"
 msgstr ""
 
-#: aleksis/core/data_checks.py:55
+#: aleksis/core/data_checks.py:56
 msgid "Ignore problem"
 msgstr ""
 
-#: aleksis/core/data_checks.py:184
+#: aleksis/core/data_checks.py:185
 #, python-brace-format
 msgid "Solve option '{solve_option_obj.verbose_name}' "
 msgstr ""
 
-#: aleksis/core/data_checks.py:290
+#: aleksis/core/data_checks.py:291
 msgid "Deactivate DashboardWidget"
 msgstr ""
 
-#: aleksis/core/data_checks.py:302
+#: aleksis/core/data_checks.py:303
 msgid "Ensure that there are no broken DashboardWidgets."
 msgstr ""
 
-#: aleksis/core/data_checks.py:303
+#: aleksis/core/data_checks.py:304
 msgid "The DashboardWidget was reported broken automatically."
 msgstr ""
 
@@ -91,15 +91,15 @@ msgstr ""
 msgid "Content type"
 msgstr ""
 
-#: aleksis/core/filters.py:113 aleksis/core/models.py:675
+#: aleksis/core/filters.py:113 aleksis/core/models.py:688
 msgid "User"
 msgstr ""
 
-#: aleksis/core/filters.py:135 aleksis/core/models.py:448
+#: aleksis/core/filters.py:135 aleksis/core/models.py:461
 msgid "Group"
 msgstr ""
 
-#: aleksis/core/forms.py:48 aleksis/core/forms.py:559
+#: aleksis/core/forms.py:48 aleksis/core/forms.py:554
 msgid "Base data"
 msgstr ""
 
@@ -107,7 +107,7 @@ msgstr ""
 msgid "Address"
 msgstr ""
 
-#: aleksis/core/forms.py:54 aleksis/core/forms.py:568
+#: aleksis/core/forms.py:54 aleksis/core/forms.py:563
 msgid "Contact data"
 msgstr ""
 
@@ -123,121 +123,121 @@ msgstr ""
 msgid "Create a new account"
 msgstr ""
 
-#: aleksis/core/forms.py:135
+#: aleksis/core/forms.py:130
 msgid "You cannot set a new username when also selecting an existing user."
 msgstr ""
 
-#: aleksis/core/forms.py:139
+#: aleksis/core/forms.py:134
 msgid "This username is already in use."
 msgstr ""
 
-#: aleksis/core/forms.py:156 aleksis/core/models.py:130
+#: aleksis/core/forms.py:151 aleksis/core/models.py:130
 msgid "School term"
 msgstr ""
 
-#: aleksis/core/forms.py:157
+#: aleksis/core/forms.py:152
 msgid "Common data"
 msgstr ""
 
-#: aleksis/core/forms.py:158 aleksis/core/forms.py:210
+#: aleksis/core/forms.py:153 aleksis/core/forms.py:205
 #: aleksis/core/menus.py:254 aleksis/core/models.py:153
 #: aleksis/core/templates/core/person/list.html:8
 #: aleksis/core/templates/core/person/list.html:9
 msgid "Persons"
 msgstr ""
 
-#: aleksis/core/forms.py:159 aleksis/core/forms.py:570
+#: aleksis/core/forms.py:154 aleksis/core/forms.py:565
 msgid "Additional data"
 msgstr ""
 
-#: aleksis/core/forms.py:160 aleksis/core/models.py:206
-#: aleksis/core/models.py:501
+#: aleksis/core/forms.py:155 aleksis/core/models.py:206
+#: aleksis/core/models.py:514
 msgid "Photo"
 msgstr ""
 
-#: aleksis/core/forms.py:202 aleksis/core/forms.py:205
+#: aleksis/core/forms.py:197 aleksis/core/forms.py:200
 #: aleksis/core/models.py:73
 msgid "Date"
 msgstr ""
 
-#: aleksis/core/forms.py:203 aleksis/core/forms.py:206
+#: aleksis/core/forms.py:198 aleksis/core/forms.py:201
 #: aleksis/core/models.py:81
 msgid "Time"
 msgstr ""
 
-#: aleksis/core/forms.py:236
+#: aleksis/core/forms.py:231
 msgid "From when until when should the announcement be displayed?"
 msgstr ""
 
-#: aleksis/core/forms.py:239
+#: aleksis/core/forms.py:234
 msgid "Who should see the announcement?"
 msgstr ""
 
-#: aleksis/core/forms.py:240
+#: aleksis/core/forms.py:235
 msgid "Write your announcement:"
 msgstr ""
 
-#: aleksis/core/forms.py:279
+#: aleksis/core/forms.py:274
 msgid "You are not allowed to create announcements which are only valid in the past."
 msgstr ""
 
-#: aleksis/core/forms.py:283
+#: aleksis/core/forms.py:278
 msgid "The from date and time must be earlier then the until date and time."
 msgstr ""
 
-#: aleksis/core/forms.py:292
+#: aleksis/core/forms.py:287
 msgid "You need at least one recipient."
 msgstr ""
 
-#: aleksis/core/forms.py:401
+#: aleksis/core/forms.py:396
 msgid "Invitation code"
 msgstr ""
 
-#: aleksis/core/forms.py:402
+#: aleksis/core/forms.py:397
 msgid "Please enter your invitation code."
 msgstr ""
 
-#: aleksis/core/forms.py:434
+#: aleksis/core/forms.py:429
 msgid "Who should get the permission?"
 msgstr ""
 
-#: aleksis/core/forms.py:435
+#: aleksis/core/forms.py:430
 msgid "On what?"
 msgstr ""
 
-#: aleksis/core/forms.py:461
+#: aleksis/core/forms.py:456
 msgid "Select objects which the permission should be granted for:"
 msgstr ""
 
-#: aleksis/core/forms.py:464
+#: aleksis/core/forms.py:459
 msgid "Grant the permission for all objects"
 msgstr ""
 
-#: aleksis/core/forms.py:472
+#: aleksis/core/forms.py:467
 msgid "You must select at least one group or person which should get the permission."
 msgstr ""
 
-#: aleksis/core/forms.py:477
+#: aleksis/core/forms.py:472
 msgid "You must grant the permission to all objects and/or to some objects."
 msgstr ""
 
-#: aleksis/core/forms.py:564
+#: aleksis/core/forms.py:559
 msgid "Adress data"
 msgstr ""
 
-#: aleksis/core/forms.py:576
+#: aleksis/core/forms.py:571
 msgid "Account data"
 msgstr ""
 
-#: aleksis/core/forms.py:583
+#: aleksis/core/forms.py:578
 msgid "Password"
 msgstr ""
 
-#: aleksis/core/forms.py:586
+#: aleksis/core/forms.py:581
 msgid "Password (again)"
 msgstr ""
 
-#: aleksis/core/forms.py:752
+#: aleksis/core/forms.py:747
 msgid "No valid selection."
 msgstr ""
 
@@ -245,22 +245,20 @@ msgstr ""
 msgid "There are unresolved data problems."
 msgstr ""
 
-#: aleksis/core/health_checks.py:44
-#, python-brace-format
-msgid "Last backup {time_gone_since_backup}!"
+#: aleksis/core/health_checks.py:40
+msgid "Error accessing backup storage: {}"
 msgstr ""
 
-#: aleksis/core/health_checks.py:46
-msgid "No backup found!"
+#: aleksis/core/health_checks.py:50
+msgid "Last backup {}!"
 msgstr ""
 
-#: aleksis/core/health_checks.py:73
-msgid "No backup result found!"
+#: aleksis/core/health_checks.py:52
+msgid "No backup found!"
 msgstr ""
 
-#: aleksis/core/health_checks.py:75
-#, python-brace-format
-msgid "{task.status} - {task.result}"
+#: aleksis/core/health_checks.py:79
+msgid "No backup result found!"
 msgstr ""
 
 #: aleksis/core/menus.py:9 aleksis/core/templates/two_factor/core/login.html:6
@@ -282,7 +280,7 @@ msgstr ""
 msgid "Dashboard"
 msgstr ""
 
-#: aleksis/core/menus.py:41 aleksis/core/models.py:721
+#: aleksis/core/menus.py:41 aleksis/core/models.py:734
 #: aleksis/core/preferences.py:29
 #: aleksis/core/templates/core/notifications.html:4
 #: aleksis/core/templates/core/notifications.html:5
@@ -340,7 +338,7 @@ msgstr ""
 msgid "Admin"
 msgstr ""
 
-#: aleksis/core/menus.py:141 aleksis/core/models.py:821
+#: aleksis/core/menus.py:141 aleksis/core/models.py:834
 #: aleksis/core/templates/core/announcement/list.html:7
 #: aleksis/core/templates/core/announcement/list.html:8
 msgid "Announcements"
@@ -398,7 +396,7 @@ msgstr ""
 msgid "People"
 msgstr ""
 
-#: aleksis/core/menus.py:276 aleksis/core/models.py:1075
+#: aleksis/core/menus.py:276 aleksis/core/models.py:1055
 #: aleksis/core/templates/core/group_type/list.html:8
 #: aleksis/core/templates/core/group_type/list.html:9
 msgid "Group types"
@@ -408,7 +406,7 @@ msgstr ""
 msgid "Groups and child groups"
 msgstr ""
 
-#: aleksis/core/menus.py:298 aleksis/core/models.py:497
+#: aleksis/core/menus.py:298 aleksis/core/models.py:510
 #: aleksis/core/templates/core/additional_field/list.html:8
 #: aleksis/core/templates/core/additional_field/list.html:9
 msgid "Additional fields"
@@ -468,7 +466,7 @@ msgstr ""
 msgid "URL / Link"
 msgstr ""
 
-#: aleksis/core/models.py:94 aleksis/core/models.py:1044
+#: aleksis/core/models.py:94 aleksis/core/models.py:1024
 msgid "Name"
 msgstr ""
 
@@ -488,7 +486,7 @@ msgstr ""
 msgid "There is already a school term for this time or a part of this time."
 msgstr ""
 
-#: aleksis/core/models.py:152 aleksis/core/models.py:993
+#: aleksis/core/models.py:152 aleksis/core/models.py:973
 msgid "Person"
 msgstr ""
 
@@ -524,7 +522,7 @@ msgstr ""
 msgid "male"
 msgstr ""
 
-#: aleksis/core/models.py:178 aleksis/core/models.py:1238
+#: aleksis/core/models.py:178 aleksis/core/models.py:1219
 msgid "Linked user"
 msgstr ""
 
@@ -540,7 +538,7 @@ msgstr ""
 msgid "Additional name(s)"
 msgstr ""
 
-#: aleksis/core/models.py:188 aleksis/core/models.py:466
+#: aleksis/core/models.py:188 aleksis/core/models.py:479
 msgid "Short name"
 msgstr ""
 
@@ -560,11 +558,11 @@ msgstr ""
 msgid "Place"
 msgstr ""
 
-#: aleksis/core/models.py:196
+#: aleksis/core/models.py:196 aleksis/core/templates/core/person/full.html:172
 msgid "Home phone"
 msgstr ""
 
-#: aleksis/core/models.py:197
+#: aleksis/core/models.py:197 aleksis/core/templates/core/person/full.html:182
 msgid "Mobile phone"
 msgstr ""
 
@@ -580,19 +578,19 @@ msgstr ""
 msgid "Sex"
 msgstr ""
 
-#: aleksis/core/models.py:210 aleksis/core/models.py:505
+#: aleksis/core/models.py:210 aleksis/core/models.py:518
 msgid "This is an official photo, used for official documents and for internal use cases."
 msgstr ""
 
-#: aleksis/core/models.py:215 aleksis/core/models.py:509
+#: aleksis/core/models.py:215 aleksis/core/models.py:522
 msgid "Display picture / Avatar"
 msgstr ""
 
-#: aleksis/core/models.py:218 aleksis/core/models.py:512
+#: aleksis/core/models.py:218 aleksis/core/models.py:525
 msgid "This is a picture or an avatar for public display."
 msgstr ""
 
-#: aleksis/core/models.py:223 aleksis/core/templates/core/person/full.html:231
+#: aleksis/core/models.py:223 aleksis/core/templates/core/person/full.html:239
 msgid "Guardians / Parents"
 msgstr ""
 
@@ -600,364 +598,368 @@ msgstr ""
 msgid "Primary group"
 msgstr ""
 
-#: aleksis/core/models.py:233 aleksis/core/models.py:679
-#: aleksis/core/models.py:703 aleksis/core/models.py:788
-#: aleksis/core/models.py:1068
+#: aleksis/core/models.py:233 aleksis/core/models.py:692
+#: aleksis/core/models.py:716 aleksis/core/models.py:801
+#: aleksis/core/models.py:1048
 msgid "Description"
 msgstr ""
 
-#: aleksis/core/models.py:421
+#: aleksis/core/models.py:434
 msgid "Title of field"
 msgstr ""
 
-#: aleksis/core/models.py:423
+#: aleksis/core/models.py:436
 msgid "Type of field"
 msgstr ""
 
-#: aleksis/core/models.py:430
+#: aleksis/core/models.py:443
 msgid "Addtitional field for groups"
 msgstr ""
 
-#: aleksis/core/models.py:431
+#: aleksis/core/models.py:444
 msgid "Addtitional fields for groups"
 msgstr ""
 
-#: aleksis/core/models.py:451
+#: aleksis/core/models.py:464
 msgid "Can assign child groups to groups"
 msgstr ""
 
-#: aleksis/core/models.py:452
+#: aleksis/core/models.py:465
 msgid "Can view statistics about group."
 msgstr ""
 
-#: aleksis/core/models.py:464
+#: aleksis/core/models.py:477
 msgid "Long name"
 msgstr ""
 
-#: aleksis/core/models.py:474 aleksis/core/templates/core/group/full.html:85
+#: aleksis/core/models.py:487 aleksis/core/templates/core/group/full.html:85
 msgid "Members"
 msgstr ""
 
-#: aleksis/core/models.py:477 aleksis/core/templates/core/group/full.html:82
+#: aleksis/core/models.py:490 aleksis/core/templates/core/group/full.html:82
 msgid "Owners"
 msgstr ""
 
-#: aleksis/core/models.py:484 aleksis/core/templates/core/group/full.html:55
+#: aleksis/core/models.py:497 aleksis/core/templates/core/group/full.html:55
 msgid "Parent groups"
 msgstr ""
 
-#: aleksis/core/models.py:492
+#: aleksis/core/models.py:505
 msgid "Type of group"
 msgstr ""
 
-#: aleksis/core/models.py:678 aleksis/core/models.py:702
-#: aleksis/core/models.py:787
+#: aleksis/core/models.py:691 aleksis/core/models.py:715
+#: aleksis/core/models.py:800
 #: aleksis/core/templates/core/announcement/list.html:18
 msgid "Title"
 msgstr ""
 
-#: aleksis/core/models.py:681
+#: aleksis/core/models.py:694
 msgid "Application"
 msgstr ""
 
-#: aleksis/core/models.py:687
+#: aleksis/core/models.py:700
 msgid "Activity"
 msgstr ""
 
-#: aleksis/core/models.py:688
+#: aleksis/core/models.py:701
 msgid "Activities"
 msgstr ""
 
-#: aleksis/core/models.py:694
+#: aleksis/core/models.py:707
 msgid "Sender"
 msgstr ""
 
-#: aleksis/core/models.py:699
+#: aleksis/core/models.py:712
 msgid "Recipient"
 msgstr ""
 
-#: aleksis/core/models.py:704 aleksis/core/models.py:1045
+#: aleksis/core/models.py:717 aleksis/core/models.py:1025
 msgid "Link"
 msgstr ""
 
-#: aleksis/core/models.py:706
+#: aleksis/core/models.py:719
 msgid "Read"
 msgstr ""
 
-#: aleksis/core/models.py:707
+#: aleksis/core/models.py:720
 msgid "Sent"
 msgstr ""
 
-#: aleksis/core/models.py:720
+#: aleksis/core/models.py:733
 msgid "Notification"
 msgstr ""
 
-#: aleksis/core/models.py:789
+#: aleksis/core/models.py:802
 msgid "Link to detailed view"
 msgstr ""
 
-#: aleksis/core/models.py:792
+#: aleksis/core/models.py:805
 msgid "Date and time from when to show"
 msgstr ""
 
-#: aleksis/core/models.py:795
+#: aleksis/core/models.py:808
 msgid "Date and time until when to show"
 msgstr ""
 
-#: aleksis/core/models.py:820
+#: aleksis/core/models.py:833
 msgid "Announcement"
 msgstr ""
 
-#: aleksis/core/models.py:858
+#: aleksis/core/models.py:871
 msgid "Announcement recipient"
 msgstr ""
 
-#: aleksis/core/models.py:859
+#: aleksis/core/models.py:872
 msgid "Announcement recipients"
 msgstr ""
 
-#: aleksis/core/models.py:914
+#: aleksis/core/models.py:894
 msgid "Widget Title"
 msgstr ""
 
-#: aleksis/core/models.py:915
+#: aleksis/core/models.py:895
 msgid "Activate Widget"
 msgstr ""
 
-#: aleksis/core/models.py:916
+#: aleksis/core/models.py:896
 msgid "Widget is broken"
 msgstr ""
 
-#: aleksis/core/models.py:919
+#: aleksis/core/models.py:899
 msgid "Size on mobile devices"
 msgstr ""
 
-#: aleksis/core/models.py:920
+#: aleksis/core/models.py:900
 msgid "<= 600 px, 12 columns"
 msgstr ""
 
-#: aleksis/core/models.py:925
+#: aleksis/core/models.py:905
 msgid "Size on tablet devices"
 msgstr ""
 
-#: aleksis/core/models.py:926
+#: aleksis/core/models.py:906
 msgid "> 600 px, 12 columns"
 msgstr ""
 
-#: aleksis/core/models.py:931
+#: aleksis/core/models.py:911
 msgid "Size on desktop devices"
 msgstr ""
 
-#: aleksis/core/models.py:932
+#: aleksis/core/models.py:912
 msgid "> 992 px, 12 columns"
 msgstr ""
 
-#: aleksis/core/models.py:937
+#: aleksis/core/models.py:917
 msgid "Size on large desktop devices"
 msgstr ""
 
-#: aleksis/core/models.py:938
+#: aleksis/core/models.py:918
 msgid "> 1200 px>, 12 columns"
 msgstr ""
 
-#: aleksis/core/models.py:969
+#: aleksis/core/models.py:949
 msgid "Can edit default dashboard"
 msgstr ""
 
-#: aleksis/core/models.py:970
+#: aleksis/core/models.py:950
 msgid "Dashboard Widget"
 msgstr ""
 
-#: aleksis/core/models.py:971
+#: aleksis/core/models.py:951
 msgid "Dashboard Widgets"
 msgstr ""
 
-#: aleksis/core/models.py:977
+#: aleksis/core/models.py:957
 msgid "URL"
 msgstr ""
 
-#: aleksis/core/models.py:978
+#: aleksis/core/models.py:958
 msgid "Icon URL"
 msgstr ""
 
-#: aleksis/core/models.py:984
+#: aleksis/core/models.py:964
 msgid "External link widget"
 msgstr ""
 
-#: aleksis/core/models.py:985
+#: aleksis/core/models.py:965
 msgid "External link widgets"
 msgstr ""
 
-#: aleksis/core/models.py:990
+#: aleksis/core/models.py:970
 msgid "Dashboard widget"
 msgstr ""
 
-#: aleksis/core/models.py:995
+#: aleksis/core/models.py:975
 msgid "Order"
 msgstr ""
 
-#: aleksis/core/models.py:996
+#: aleksis/core/models.py:976
 msgid "Part of the default dashboard"
 msgstr ""
 
-#: aleksis/core/models.py:1011
+#: aleksis/core/models.py:991
 msgid "Dashboard widget order"
 msgstr ""
 
-#: aleksis/core/models.py:1012
+#: aleksis/core/models.py:992
 msgid "Dashboard widget orders"
 msgstr ""
 
-#: aleksis/core/models.py:1018
+#: aleksis/core/models.py:998
 msgid "Menu ID"
 msgstr ""
 
-#: aleksis/core/models.py:1031
+#: aleksis/core/models.py:1011
 msgid "Custom menu"
 msgstr ""
 
-#: aleksis/core/models.py:1032
+#: aleksis/core/models.py:1012
 msgid "Custom menus"
 msgstr ""
 
-#: aleksis/core/models.py:1042
+#: aleksis/core/models.py:1022
 msgid "Menu"
 msgstr ""
 
-#: aleksis/core/models.py:1046 aleksis/core/models.py:1285
+#: aleksis/core/models.py:1026 aleksis/core/models.py:1266
 #: aleksis/core/templates/oauth2_provider/application/detail.html:26
 msgid "Icon"
 msgstr ""
 
-#: aleksis/core/models.py:1052
+#: aleksis/core/models.py:1032
 msgid "Custom menu item"
 msgstr ""
 
-#: aleksis/core/models.py:1053
+#: aleksis/core/models.py:1033
 msgid "Custom menu items"
 msgstr ""
 
-#: aleksis/core/models.py:1067
+#: aleksis/core/models.py:1047
 msgid "Title of type"
 msgstr ""
 
-#: aleksis/core/models.py:1074 aleksis/core/templates/core/group/full.html:47
+#: aleksis/core/models.py:1054 aleksis/core/templates/core/group/full.html:47
 msgid "Group type"
 msgstr ""
 
-#: aleksis/core/models.py:1088
+#: aleksis/core/models.py:1068
 msgid "Can view system status"
 msgstr ""
 
-#: aleksis/core/models.py:1089
+#: aleksis/core/models.py:1069
 msgid "Can manage data"
 msgstr ""
 
-#: aleksis/core/models.py:1090
+#: aleksis/core/models.py:1070
 msgid "Can impersonate"
 msgstr ""
 
-#: aleksis/core/models.py:1091
+#: aleksis/core/models.py:1071
 msgid "Can use search"
 msgstr ""
 
-#: aleksis/core/models.py:1092
+#: aleksis/core/models.py:1072
 msgid "Can change site preferences"
 msgstr ""
 
-#: aleksis/core/models.py:1093
+#: aleksis/core/models.py:1073
 msgid "Can change person preferences"
 msgstr ""
 
-#: aleksis/core/models.py:1094
+#: aleksis/core/models.py:1074
 msgid "Can change group preferences"
 msgstr ""
 
-#: aleksis/core/models.py:1095
+#: aleksis/core/models.py:1075
 msgid "Can test PDF generation"
 msgstr ""
 
-#: aleksis/core/models.py:1131
+#: aleksis/core/models.py:1076
+msgid "Can invite persons"
+msgstr ""
+
+#: aleksis/core/models.py:1112
 msgid "Related data check task"
 msgstr ""
 
-#: aleksis/core/models.py:1139
+#: aleksis/core/models.py:1120
 msgid "Issue solved"
 msgstr ""
 
-#: aleksis/core/models.py:1140
+#: aleksis/core/models.py:1121
 msgid "Notification sent"
 msgstr ""
 
-#: aleksis/core/models.py:1153
+#: aleksis/core/models.py:1134
 msgid "Data check result"
 msgstr ""
 
-#: aleksis/core/models.py:1154
+#: aleksis/core/models.py:1135
 msgid "Data check results"
 msgstr ""
 
-#: aleksis/core/models.py:1156
+#: aleksis/core/models.py:1137
 msgid "Can run data checks"
 msgstr ""
 
-#: aleksis/core/models.py:1157
+#: aleksis/core/models.py:1138
 msgid "Can solve data check problems"
 msgstr ""
 
-#: aleksis/core/models.py:1164
+#: aleksis/core/models.py:1145
 msgid "E-Mail address"
 msgstr ""
 
-#: aleksis/core/models.py:1188
+#: aleksis/core/models.py:1169
 msgid "Owner"
 msgstr ""
 
-#: aleksis/core/models.py:1192
+#: aleksis/core/models.py:1173
 msgid "File expires at"
 msgstr ""
 
-#: aleksis/core/models.py:1194
+#: aleksis/core/models.py:1175
 msgid "Generated HTML file"
 msgstr ""
 
-#: aleksis/core/models.py:1196
+#: aleksis/core/models.py:1177
 msgid "Generated PDF file"
 msgstr ""
 
-#: aleksis/core/models.py:1203
+#: aleksis/core/models.py:1184
 msgid "PDF file"
 msgstr ""
 
-#: aleksis/core/models.py:1204
+#: aleksis/core/models.py:1185
 msgid "PDF files"
 msgstr ""
 
-#: aleksis/core/models.py:1209
+#: aleksis/core/models.py:1190
 msgid "Task result"
 msgstr ""
 
-#: aleksis/core/models.py:1212
+#: aleksis/core/models.py:1193
 msgid "Task user"
 msgstr ""
 
-#: aleksis/core/models.py:1224
+#: aleksis/core/models.py:1205
 msgid "Task user assignment"
 msgstr ""
 
-#: aleksis/core/models.py:1225
+#: aleksis/core/models.py:1206
 msgid "Task user assignments"
 msgstr ""
 
-#: aleksis/core/models.py:1241
+#: aleksis/core/models.py:1222
 msgid "Additional attributes"
 msgstr ""
 
-#: aleksis/core/models.py:1279
+#: aleksis/core/models.py:1260
 msgid "Allowed scopes that clients can request"
 msgstr ""
 
-#: aleksis/core/models.py:1289
+#: aleksis/core/models.py:1270
 msgid "This image will be shown as icon in the authorization flow. It should be squared."
 msgstr ""
 
@@ -993,7 +995,7 @@ msgstr ""
 msgid "Internationalisation"
 msgstr ""
 
-#: aleksis/core/preferences.py:44
+#: aleksis/core/preferences.py:43
 msgid "Site title"
 msgstr ""
 
@@ -1001,11 +1003,11 @@ msgstr ""
 msgid "Site description"
 msgstr ""
 
-#: aleksis/core/preferences.py:66
+#: aleksis/core/preferences.py:65
 msgid "Primary colour"
 msgstr ""
 
-#: aleksis/core/preferences.py:78
+#: aleksis/core/preferences.py:77
 msgid "Secondary colour"
 msgstr ""
 
@@ -1013,147 +1015,151 @@ msgstr ""
 msgid "Logo"
 msgstr ""
 
-#: aleksis/core/preferences.py:99
+#: aleksis/core/preferences.py:100
 msgid "Favicon"
 msgstr ""
 
-#: aleksis/core/preferences.py:109
+#: aleksis/core/preferences.py:111
 msgid "PWA-Icon"
 msgstr ""
 
-#: aleksis/core/preferences.py:120
+#: aleksis/core/preferences.py:121
+msgid "PWA-Icon is maskable"
+msgstr ""
+
+#: aleksis/core/preferences.py:133
 msgid "Mail out name"
 msgstr ""
 
-#: aleksis/core/preferences.py:131
+#: aleksis/core/preferences.py:144
 msgid "Mail out address"
 msgstr ""
 
-#: aleksis/core/preferences.py:143
+#: aleksis/core/preferences.py:157
 msgid "Link to privacy policy"
 msgstr ""
 
-#: aleksis/core/preferences.py:155
+#: aleksis/core/preferences.py:169
 msgid "Link to imprint"
 msgstr ""
 
-#: aleksis/core/preferences.py:167
+#: aleksis/core/preferences.py:180
 msgid "Name format for addressing"
 msgstr ""
 
-#: aleksis/core/preferences.py:183
+#: aleksis/core/preferences.py:197
 msgid "Channels to use for notifications"
 msgstr ""
 
-#: aleksis/core/preferences.py:195
+#: aleksis/core/preferences.py:209
 msgid "Regular expression to match primary group, e.g. '^Class .*'"
 msgstr ""
 
-#: aleksis/core/preferences.py:206
+#: aleksis/core/preferences.py:220
 msgid "Field on person to match primary group against"
 msgstr ""
 
-#: aleksis/core/preferences.py:218
+#: aleksis/core/preferences.py:232
 msgid "Automatically create new persons for new users"
 msgstr ""
 
-#: aleksis/core/preferences.py:227
+#: aleksis/core/preferences.py:241
 msgid "Automatically link existing persons to new users by their e-mail address"
 msgstr ""
 
-#: aleksis/core/preferences.py:238
+#: aleksis/core/preferences.py:252
 msgid "Display name of the school"
 msgstr ""
 
-#: aleksis/core/preferences.py:249
+#: aleksis/core/preferences.py:263
 msgid "Official name of the school, e.g. as given by supervisory authority"
 msgstr ""
 
-#: aleksis/core/preferences.py:257
+#: aleksis/core/preferences.py:271
 msgid "Allow users to change their passwords"
 msgstr ""
 
-#: aleksis/core/preferences.py:265
+#: aleksis/core/preferences.py:279
 msgid "Enable signup"
 msgstr ""
 
-#: aleksis/core/preferences.py:273
+#: aleksis/core/preferences.py:287
 msgid "Enable invitations"
 msgstr ""
 
-#: aleksis/core/preferences.py:281
+#: aleksis/core/preferences.py:295
 msgid "Length of invite code. (Default 3: abcde-acbde-abcde)"
 msgstr ""
 
-#: aleksis/core/preferences.py:289
+#: aleksis/core/preferences.py:303
 msgid "Size of packets. (Default 5: abcde)"
 msgstr ""
 
-#: aleksis/core/preferences.py:300
+#: aleksis/core/preferences.py:314
 msgid "Allowed Grant Flows for OAuth applications"
 msgstr ""
 
-#: aleksis/core/preferences.py:313
+#: aleksis/core/preferences.py:328
 msgid "Available languages"
 msgstr ""
 
-#: aleksis/core/preferences.py:325
+#: aleksis/core/preferences.py:341
 msgid "Send emails if data checks detect problems"
 msgstr ""
 
-#: aleksis/core/preferences.py:336
+#: aleksis/core/preferences.py:352
 msgid "Email recipients for data checks problem emails"
 msgstr ""
 
-#: aleksis/core/preferences.py:347
+#: aleksis/core/preferences.py:363
 msgid "Email recipient groups for data checks problem emails"
 msgstr ""
 
-#: aleksis/core/preferences.py:356
+#: aleksis/core/preferences.py:372
 msgid "Show dashboard to users without login"
 msgstr ""
 
-#: aleksis/core/preferences.py:365
+#: aleksis/core/preferences.py:381
 msgid "Allow users to edit their dashboard"
 msgstr ""
 
-#: aleksis/core/preferences.py:376
+#: aleksis/core/preferences.py:392
 msgid "Fields on person model which are editable by themselves."
 msgstr ""
 
-#: aleksis/core/preferences.py:390
+#: aleksis/core/preferences.py:407
 msgid "Editable fields on person model which should trigger a notification on change"
 msgstr ""
 
-#: aleksis/core/preferences.py:403
+#: aleksis/core/preferences.py:421
 msgid "Contact for notification if a person changes their data"
 msgstr ""
 
-#: aleksis/core/preferences.py:413
+#: aleksis/core/preferences.py:432
 msgid "PDF file expiration duration"
 msgstr ""
 
-#: aleksis/core/preferences.py:414
+#: aleksis/core/preferences.py:433
 msgid "in minutes"
 msgstr ""
 
-#: aleksis/core/preferences.py:424
+#: aleksis/core/preferences.py:443
 msgid "Automatically update the dashboard and its widgets"
 msgstr ""
 
-#: aleksis/core/preferences.py:434
+#: aleksis/core/preferences.py:453
 msgid "Automatically update the dashboard and its widgets sitewide"
 msgstr ""
 
-#: aleksis/core/preferences.py:444
+#: aleksis/core/preferences.py:463
 msgid "Country for phone number parsing"
 msgstr ""
 
-#: aleksis/core/settings.py:518
+#: aleksis/core/settings.py:526
 msgid "English"
 msgstr ""
 
-#: aleksis/core/settings.py:519
+#: aleksis/core/settings.py:527
 msgid "German"
 msgstr ""
 
@@ -1500,7 +1506,7 @@ msgstr ""
 msgid "Privacy Policy"
 msgstr ""
 
-#: aleksis/core/templates/core/base_print.html:72
+#: aleksis/core/templates/core/base_print.html:74
 msgid "Powered by AlekSIS®"
 msgstr ""
 
@@ -2127,19 +2133,11 @@ msgstr ""
 msgid "Contact details"
 msgstr ""
 
-#: aleksis/core/templates/core/person/full.html:168
-msgid "home number"
-msgstr ""
-
-#: aleksis/core/templates/core/person/full.html:174
-msgid "mobile number"
-msgstr ""
-
-#: aleksis/core/templates/core/person/full.html:216
+#: aleksis/core/templates/core/person/full.html:224
 msgid "This person didn't upload a personal photo."
 msgstr ""
 
-#: aleksis/core/templates/core/person/full.html:224
+#: aleksis/core/templates/core/person/full.html:232
 msgid "Children"
 msgstr ""
 
@@ -2939,23 +2937,23 @@ msgstr ""
 msgid "SMS"
 msgstr ""
 
-#: aleksis/core/util/pdf.py:113
+#: aleksis/core/util/pdf.py:118
 msgid "Progress: Generate PDF file"
 msgstr ""
 
-#: aleksis/core/util/pdf.py:114
+#: aleksis/core/util/pdf.py:119
 msgid "Generating PDF file …"
 msgstr ""
 
-#: aleksis/core/util/pdf.py:115
+#: aleksis/core/util/pdf.py:120
 msgid "The PDF file has been generated successfully."
 msgstr ""
 
-#: aleksis/core/util/pdf.py:116
+#: aleksis/core/util/pdf.py:121
 msgid "There was a problem while generating the PDF file."
 msgstr ""
 
-#: aleksis/core/util/pdf.py:119
+#: aleksis/core/util/pdf.py:124
 msgid "Download PDF"
 msgstr ""
 
@@ -3105,10 +3103,10 @@ msgstr ""
 msgid "The third-party account has been successfully disconnected."
 msgstr ""
 
-#: aleksis/core/views.py:1443
+#: aleksis/core/views.py:1445
 msgid "Person was invited successfully."
 msgstr ""
 
-#: aleksis/core/views.py:1445
+#: aleksis/core/views.py:1447
 msgid "Person was already invited."
 msgstr ""
diff --git a/aleksis/core/locale/ar/LC_MESSAGES/djangojs.po b/aleksis/core/locale/ar/LC_MESSAGES/djangojs.po
index 55a1fa4b4213ab34f133746e776138df18c9f6a1..590f5ff9ab6b78cb5ebbc5738c367994cfd58aac 100644
--- a/aleksis/core/locale/ar/LC_MESSAGES/djangojs.po
+++ b/aleksis/core/locale/ar/LC_MESSAGES/djangojs.po
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2022-01-10 17:26+0100\n"
+"POT-Creation-Date: 2022-01-31 17:03+0100\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"
@@ -18,18 +18,18 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
 
-#: aleksis/core/static/js/main.js:15
+#: aleksis/core/static/js/main.js:66
 msgid "Today"
 msgstr ""
 
-#: aleksis/core/static/js/main.js:16
+#: aleksis/core/static/js/main.js:67
 msgid "Cancel"
 msgstr ""
 
-#: aleksis/core/static/js/main.js:17
+#: aleksis/core/static/js/main.js:68
 msgid "OK"
 msgstr ""
 
-#: aleksis/core/static/js/main.js:131
+#: aleksis/core/static/js/main.js:191
 msgid "This page may contain outdated information since there is no internet connection."
 msgstr ""
diff --git a/aleksis/core/locale/de_DE/LC_MESSAGES/django.po b/aleksis/core/locale/de_DE/LC_MESSAGES/django.po
index 6e5699b45e511610a2319cbd2cefa15b8f9c037d..d3dc00144fe56aebf7c76d7597bae467d0ddbadd 100644
--- a/aleksis/core/locale/de_DE/LC_MESSAGES/django.po
+++ b/aleksis/core/locale/de_DE/LC_MESSAGES/django.po
@@ -7,8 +7,8 @@ msgid ""
 msgstr ""
 "Project-Id-Version: AlekSIS (School Information System) 0.1\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2022-01-10 17:26+0100\n"
-"PO-Revision-Date: 2022-01-10 16:31+0000\n"
+"POT-Creation-Date: 2022-01-31 17:03+0100\n"
+"PO-Revision-Date: 2022-01-31 16:15+0000\n"
 "Last-Translator: Jonathan Weth <teckids@jonathanweth.de>\n"
 "Language-Team: German <https://translate.edugit.org/projects/aleksis/"
 "aleksis-core/de/>\n"
@@ -19,51 +19,51 @@ msgstr ""
 "Plural-Forms: nplurals=2; plural=n != 1;\n"
 "X-Generator: Weblate 4.8\n"
 
-#: aleksis/core/apps.py:154
+#: aleksis/core/apps.py:166
 msgid "OpenID Connect scope"
 msgstr "OpenID-Connect-Scope"
 
-#: aleksis/core/apps.py:155
+#: aleksis/core/apps.py:167
 msgid "Given name, family name, link to profile and picture if existing."
 msgstr "Vorname, Nachname, Link zum Profil und Bild falls vorhanden"
 
-#: aleksis/core/apps.py:156
+#: aleksis/core/apps.py:168
 msgid "Full home postal address"
 msgstr "Vollständige Postanschrift"
 
-#: aleksis/core/apps.py:157
+#: aleksis/core/apps.py:169
 msgid "Email address"
 msgstr "E-Mail-Adresse"
 
-#: aleksis/core/apps.py:158
+#: aleksis/core/apps.py:170
 msgid "Home and mobile phone"
 msgstr "Festnetz- und Mobilfunknummer"
 
-#: aleksis/core/apps.py:159 aleksis/core/forms.py:223 aleksis/core/menus.py:265
-#: aleksis/core/models.py:449 aleksis/core/templates/core/group/list.html:8
+#: aleksis/core/apps.py:171 aleksis/core/forms.py:218 aleksis/core/menus.py:265
+#: aleksis/core/models.py:462 aleksis/core/templates/core/group/list.html:8
 #: aleksis/core/templates/core/group/list.html:9
-#: aleksis/core/templates/core/person/full.html:242
+#: aleksis/core/templates/core/person/full.html:250
 msgid "Groups"
 msgstr "Gruppen"
 
-#: aleksis/core/data_checks.py:55
+#: aleksis/core/data_checks.py:56
 msgid "Ignore problem"
 msgstr "Problem ignorieren"
 
-#: aleksis/core/data_checks.py:184
+#: aleksis/core/data_checks.py:185
 #, python-brace-format
 msgid "Solve option '{solve_option_obj.verbose_name}' "
 msgstr "Lösungsoption \"{solve_option_obj.verbose_name}\" "
 
-#: aleksis/core/data_checks.py:290
+#: aleksis/core/data_checks.py:291
 msgid "Deactivate DashboardWidget"
 msgstr "Dashboard-Widget deaktivieren"
 
-#: aleksis/core/data_checks.py:302
+#: aleksis/core/data_checks.py:303
 msgid "Ensure that there are no broken DashboardWidgets."
 msgstr "Sicherstellen, dass es keine kaputten Dashboard-Widgets gibt."
 
-#: aleksis/core/data_checks.py:303
+#: aleksis/core/data_checks.py:304
 msgid "The DashboardWidget was reported broken automatically."
 msgstr "Das Dashboard-Widget wurde automatisch als kaputt gemeldet."
 
@@ -92,15 +92,15 @@ msgstr "Berechtigung"
 msgid "Content type"
 msgstr "Inhaltstyp"
 
-#: aleksis/core/filters.py:113 aleksis/core/models.py:675
+#: aleksis/core/filters.py:113 aleksis/core/models.py:688
 msgid "User"
 msgstr "Benutzer"
 
-#: aleksis/core/filters.py:135 aleksis/core/models.py:448
+#: aleksis/core/filters.py:135 aleksis/core/models.py:461
 msgid "Group"
 msgstr "Gruppe"
 
-#: aleksis/core/forms.py:48 aleksis/core/forms.py:559
+#: aleksis/core/forms.py:48 aleksis/core/forms.py:554
 msgid "Base data"
 msgstr "Basisdaten"
 
@@ -108,7 +108,7 @@ msgstr "Basisdaten"
 msgid "Address"
 msgstr "Adresse"
 
-#: aleksis/core/forms.py:54 aleksis/core/forms.py:568
+#: aleksis/core/forms.py:54 aleksis/core/forms.py:563
 msgid "Contact data"
 msgstr "Kontaktdaten"
 
@@ -124,121 +124,121 @@ msgstr "Neuer Benutzer"
 msgid "Create a new account"
 msgstr "Neues Benutzerkonto erstellen"
 
-#: aleksis/core/forms.py:135
+#: aleksis/core/forms.py:130
 msgid "You cannot set a new username when also selecting an existing user."
 msgstr "Sie können keine neuen Benutzer erstellen, wenn Sie gleichzeitig einen existierenden Benutzer auswählen."
 
-#: aleksis/core/forms.py:139
+#: aleksis/core/forms.py:134
 msgid "This username is already in use."
 msgstr "Dieser Benutzername wird bereits genutzt."
 
-#: aleksis/core/forms.py:156 aleksis/core/models.py:130
+#: aleksis/core/forms.py:151 aleksis/core/models.py:130
 msgid "School term"
 msgstr "Schuljahr"
 
-#: aleksis/core/forms.py:157
+#: aleksis/core/forms.py:152
 msgid "Common data"
 msgstr "Allgemeine Daten"
 
-#: aleksis/core/forms.py:158 aleksis/core/forms.py:210
+#: aleksis/core/forms.py:153 aleksis/core/forms.py:205
 #: aleksis/core/menus.py:254 aleksis/core/models.py:153
 #: aleksis/core/templates/core/person/list.html:8
 #: aleksis/core/templates/core/person/list.html:9
 msgid "Persons"
 msgstr "Personen"
 
-#: aleksis/core/forms.py:159 aleksis/core/forms.py:570
+#: aleksis/core/forms.py:154 aleksis/core/forms.py:565
 msgid "Additional data"
 msgstr "Zusätzliche Datne"
 
-#: aleksis/core/forms.py:160 aleksis/core/models.py:206
-#: aleksis/core/models.py:501
+#: aleksis/core/forms.py:155 aleksis/core/models.py:206
+#: aleksis/core/models.py:514
 msgid "Photo"
 msgstr "Foto"
 
-#: aleksis/core/forms.py:202 aleksis/core/forms.py:205
+#: aleksis/core/forms.py:197 aleksis/core/forms.py:200
 #: aleksis/core/models.py:73
 msgid "Date"
 msgstr "Datum"
 
-#: aleksis/core/forms.py:203 aleksis/core/forms.py:206
+#: aleksis/core/forms.py:198 aleksis/core/forms.py:201
 #: aleksis/core/models.py:81
 msgid "Time"
 msgstr "Zeit"
 
-#: aleksis/core/forms.py:236
+#: aleksis/core/forms.py:231
 msgid "From when until when should the announcement be displayed?"
 msgstr "Von wann bis wann soll die Ankündigung angezeigt werden?"
 
-#: aleksis/core/forms.py:239
+#: aleksis/core/forms.py:234
 msgid "Who should see the announcement?"
 msgstr "Wer soll die Ankündigung sehen?"
 
-#: aleksis/core/forms.py:240
+#: aleksis/core/forms.py:235
 msgid "Write your announcement:"
 msgstr "Schreiben Sie ihre Ankündigung:"
 
-#: aleksis/core/forms.py:279
+#: aleksis/core/forms.py:274
 msgid "You are not allowed to create announcements which are only valid in the past."
 msgstr "Sie dürfen keine Ankündigungen erstellen, die nur für die Vergangenheit gültig sind."
 
-#: aleksis/core/forms.py:283
+#: aleksis/core/forms.py:278
 msgid "The from date and time must be earlier then the until date and time."
 msgstr "Das Startdatum und die Startzeit müssen vor dem Enddatum und der Endzeit sein."
 
-#: aleksis/core/forms.py:292
+#: aleksis/core/forms.py:287
 msgid "You need at least one recipient."
 msgstr "Sie benötigen mindestens einen Empfänger."
 
-#: aleksis/core/forms.py:401
+#: aleksis/core/forms.py:396
 msgid "Invitation code"
 msgstr "Einladungscode"
 
-#: aleksis/core/forms.py:402
+#: aleksis/core/forms.py:397
 msgid "Please enter your invitation code."
 msgstr "Bitte geben Sie Ihren Einladungscode ein."
 
-#: aleksis/core/forms.py:434
+#: aleksis/core/forms.py:429
 msgid "Who should get the permission?"
 msgstr "Wer soll die Berechtigung erhalten?"
 
-#: aleksis/core/forms.py:435
+#: aleksis/core/forms.py:430
 msgid "On what?"
 msgstr "Auf was?"
 
-#: aleksis/core/forms.py:461
+#: aleksis/core/forms.py:456
 msgid "Select objects which the permission should be granted for:"
 msgstr "Wählen Sie die Objekte aus, für welche die Berechtigung vergeben werden soll:"
 
-#: aleksis/core/forms.py:464
+#: aleksis/core/forms.py:459
 msgid "Grant the permission for all objects"
 msgstr "Vergebe die Berechtigung für alle Objekte"
 
-#: aleksis/core/forms.py:472
+#: aleksis/core/forms.py:467
 msgid "You must select at least one group or person which should get the permission."
 msgstr "Sie müssen mindestens eine Gruppe oder Person auswählen, welche die Berechtigung erhalten soll."
 
-#: aleksis/core/forms.py:477
+#: aleksis/core/forms.py:472
 msgid "You must grant the permission to all objects and/or to some objects."
 msgstr "Sie müssen die Berechtigung auf alle Objekte und/oder für einige Objekte vergeben."
 
-#: aleksis/core/forms.py:564
+#: aleksis/core/forms.py:559
 msgid "Adress data"
 msgstr "Adressdaten"
 
-#: aleksis/core/forms.py:576
+#: aleksis/core/forms.py:571
 msgid "Account data"
 msgstr "Kontodaten"
 
-#: aleksis/core/forms.py:583
+#: aleksis/core/forms.py:578
 msgid "Password"
 msgstr "Passwort"
 
-#: aleksis/core/forms.py:586
+#: aleksis/core/forms.py:581
 msgid "Password (again)"
 msgstr "Passwort wiederholen"
 
-#: aleksis/core/forms.py:752
+#: aleksis/core/forms.py:747
 msgid "No valid selection."
 msgstr "Keine gültige Auswahl."
 
@@ -246,24 +246,22 @@ msgstr "Keine gültige Auswahl."
 msgid "There are unresolved data problems."
 msgstr "Es gibt ungelöste Datenprobleme."
 
-#: aleksis/core/health_checks.py:44
-#, python-brace-format
-msgid "Last backup {time_gone_since_backup}!"
-msgstr "Letztes Backup: {time_gone_since_backup}!"
+#: aleksis/core/health_checks.py:40
+msgid "Error accessing backup storage: {}"
+msgstr "Fehler beim Zugriff auf Backup-Storage: {}"
+
+#: aleksis/core/health_checks.py:50
+msgid "Last backup {}!"
+msgstr "Letztes Backup {}!"
 
-#: aleksis/core/health_checks.py:46
+#: aleksis/core/health_checks.py:52
 msgid "No backup found!"
 msgstr "Kein Backup gefunden!"
 
-#: aleksis/core/health_checks.py:73
+#: aleksis/core/health_checks.py:79
 msgid "No backup result found!"
 msgstr "Kein Backupergebnis gefunden!"
 
-#: aleksis/core/health_checks.py:75
-#, python-brace-format
-msgid "{task.status} - {task.result}"
-msgstr "{task.status} - {task.result}"
-
 #: aleksis/core/menus.py:9 aleksis/core/templates/two_factor/core/login.html:6
 #: aleksis/core/templates/two_factor/core/login.html:32
 #: aleksis/core/templates/two_factor/core/login.html:95
@@ -283,7 +281,7 @@ msgstr "Einladung akzeptieren"
 msgid "Dashboard"
 msgstr "Dashboard"
 
-#: aleksis/core/menus.py:41 aleksis/core/models.py:721
+#: aleksis/core/menus.py:41 aleksis/core/models.py:734
 #: aleksis/core/preferences.py:29
 #: aleksis/core/templates/core/notifications.html:4
 #: aleksis/core/templates/core/notifications.html:5
@@ -341,7 +339,7 @@ msgstr "Autorisierte Anwendungen"
 msgid "Admin"
 msgstr "Admin"
 
-#: aleksis/core/menus.py:141 aleksis/core/models.py:821
+#: aleksis/core/menus.py:141 aleksis/core/models.py:834
 #: aleksis/core/templates/core/announcement/list.html:7
 #: aleksis/core/templates/core/announcement/list.html:8
 msgid "Announcements"
@@ -399,7 +397,7 @@ msgstr "OAuth2-Anwendungen"
 msgid "People"
 msgstr "Leute"
 
-#: aleksis/core/menus.py:276 aleksis/core/models.py:1075
+#: aleksis/core/menus.py:276 aleksis/core/models.py:1055
 #: aleksis/core/templates/core/group_type/list.html:8
 #: aleksis/core/templates/core/group_type/list.html:9
 msgid "Group types"
@@ -409,7 +407,7 @@ msgstr "Gruppentypen"
 msgid "Groups and child groups"
 msgstr "Gruppen und Kindgruppen"
 
-#: aleksis/core/menus.py:298 aleksis/core/models.py:497
+#: aleksis/core/menus.py:298 aleksis/core/models.py:510
 #: aleksis/core/templates/core/additional_field/list.html:8
 #: aleksis/core/templates/core/additional_field/list.html:9
 msgid "Additional fields"
@@ -469,7 +467,7 @@ msgstr "Text (mehrzeilig)"
 msgid "URL / Link"
 msgstr "URL / Link"
 
-#: aleksis/core/models.py:94 aleksis/core/models.py:1044
+#: aleksis/core/models.py:94 aleksis/core/models.py:1024
 msgid "Name"
 msgstr "Name"
 
@@ -489,7 +487,7 @@ msgstr "Das Startdatum muss vor dem Enddatum liegen."
 msgid "There is already a school term for this time or a part of this time."
 msgstr "Es gibt bereits ein Schuljahr für diesen Zeitraum oder einen Teilzeitraum."
 
-#: aleksis/core/models.py:152 aleksis/core/models.py:993
+#: aleksis/core/models.py:152 aleksis/core/models.py:973
 msgid "Person"
 msgstr "Person"
 
@@ -525,7 +523,7 @@ msgstr "weiblich"
 msgid "male"
 msgstr "männlich"
 
-#: aleksis/core/models.py:178 aleksis/core/models.py:1238
+#: aleksis/core/models.py:178 aleksis/core/models.py:1219
 msgid "Linked user"
 msgstr "Verknüpfter Benutzer"
 
@@ -541,7 +539,7 @@ msgstr "Nachname"
 msgid "Additional name(s)"
 msgstr "Zusätzliche Namen"
 
-#: aleksis/core/models.py:188 aleksis/core/models.py:466
+#: aleksis/core/models.py:188 aleksis/core/models.py:479
 msgid "Short name"
 msgstr "Kurzname"
 
@@ -561,11 +559,11 @@ msgstr "Postleitzahl"
 msgid "Place"
 msgstr "Ort"
 
-#: aleksis/core/models.py:196
+#: aleksis/core/models.py:196 aleksis/core/templates/core/person/full.html:172
 msgid "Home phone"
 msgstr "Festnetz"
 
-#: aleksis/core/models.py:197
+#: aleksis/core/models.py:197 aleksis/core/templates/core/person/full.html:182
 msgid "Mobile phone"
 msgstr "Handy"
 
@@ -581,19 +579,19 @@ msgstr "Geburtsort"
 msgid "Sex"
 msgstr "Geschlecht"
 
-#: aleksis/core/models.py:210 aleksis/core/models.py:505
+#: aleksis/core/models.py:210 aleksis/core/models.py:518
 msgid "This is an official photo, used for official documents and for internal use cases."
 msgstr "Dies ist ein offizielles Foto, genutzt für offizielle Dokumente und interne Zwecke."
 
-#: aleksis/core/models.py:215 aleksis/core/models.py:509
+#: aleksis/core/models.py:215 aleksis/core/models.py:522
 msgid "Display picture / Avatar"
 msgstr "Bild/Avatar anzeigen"
 
-#: aleksis/core/models.py:218 aleksis/core/models.py:512
+#: aleksis/core/models.py:218 aleksis/core/models.py:525
 msgid "This is a picture or an avatar for public display."
 msgstr "Dies ist ein Bild oder ein Avatar für die öffentliche Darstellung."
 
-#: aleksis/core/models.py:223 aleksis/core/templates/core/person/full.html:231
+#: aleksis/core/models.py:223 aleksis/core/templates/core/person/full.html:239
 msgid "Guardians / Parents"
 msgstr "Erziehungsberechtigte / Eltern"
 
@@ -601,364 +599,368 @@ msgstr "Erziehungsberechtigte / Eltern"
 msgid "Primary group"
 msgstr "Primärgruppe"
 
-#: aleksis/core/models.py:233 aleksis/core/models.py:679
-#: aleksis/core/models.py:703 aleksis/core/models.py:788
-#: aleksis/core/models.py:1068
+#: aleksis/core/models.py:233 aleksis/core/models.py:692
+#: aleksis/core/models.py:716 aleksis/core/models.py:801
+#: aleksis/core/models.py:1048
 msgid "Description"
 msgstr "Beschreibung"
 
-#: aleksis/core/models.py:421
+#: aleksis/core/models.py:434
 msgid "Title of field"
 msgstr "Feldtitel"
 
-#: aleksis/core/models.py:423
+#: aleksis/core/models.py:436
 msgid "Type of field"
 msgstr "Feldtyp"
 
-#: aleksis/core/models.py:430
+#: aleksis/core/models.py:443
 msgid "Addtitional field for groups"
 msgstr "Zusätzliche Felder für Gruppen"
 
-#: aleksis/core/models.py:431
+#: aleksis/core/models.py:444
 msgid "Addtitional fields for groups"
 msgstr "Zusätzliche Felder für Gruppen"
 
-#: aleksis/core/models.py:451
+#: aleksis/core/models.py:464
 msgid "Can assign child groups to groups"
 msgstr "Kann Kindgruppen zu Gruppen zuordnen"
 
-#: aleksis/core/models.py:452
+#: aleksis/core/models.py:465
 msgid "Can view statistics about group."
 msgstr "Kann Statistiken über Gruppen sehen."
 
-#: aleksis/core/models.py:464
+#: aleksis/core/models.py:477
 msgid "Long name"
 msgstr "Langname"
 
-#: aleksis/core/models.py:474 aleksis/core/templates/core/group/full.html:85
+#: aleksis/core/models.py:487 aleksis/core/templates/core/group/full.html:85
 msgid "Members"
 msgstr "Mitglieder"
 
-#: aleksis/core/models.py:477 aleksis/core/templates/core/group/full.html:82
+#: aleksis/core/models.py:490 aleksis/core/templates/core/group/full.html:82
 msgid "Owners"
 msgstr "Leiter/-innen"
 
-#: aleksis/core/models.py:484 aleksis/core/templates/core/group/full.html:55
+#: aleksis/core/models.py:497 aleksis/core/templates/core/group/full.html:55
 msgid "Parent groups"
 msgstr "Ãœbergeordnete Gruppen"
 
-#: aleksis/core/models.py:492
+#: aleksis/core/models.py:505
 msgid "Type of group"
 msgstr "Gruppentyp"
 
-#: aleksis/core/models.py:678 aleksis/core/models.py:702
-#: aleksis/core/models.py:787
+#: aleksis/core/models.py:691 aleksis/core/models.py:715
+#: aleksis/core/models.py:800
 #: aleksis/core/templates/core/announcement/list.html:18
 msgid "Title"
 msgstr "Titel"
 
-#: aleksis/core/models.py:681
+#: aleksis/core/models.py:694
 msgid "Application"
 msgstr "Anwendung"
 
-#: aleksis/core/models.py:687
+#: aleksis/core/models.py:700
 msgid "Activity"
 msgstr "Aktivität"
 
-#: aleksis/core/models.py:688
+#: aleksis/core/models.py:701
 msgid "Activities"
 msgstr "Aktivitäten"
 
-#: aleksis/core/models.py:694
+#: aleksis/core/models.py:707
 msgid "Sender"
 msgstr "Absender"
 
-#: aleksis/core/models.py:699
+#: aleksis/core/models.py:712
 msgid "Recipient"
 msgstr "Empfänger"
 
-#: aleksis/core/models.py:704 aleksis/core/models.py:1045
+#: aleksis/core/models.py:717 aleksis/core/models.py:1025
 msgid "Link"
 msgstr "Link"
 
-#: aleksis/core/models.py:706
+#: aleksis/core/models.py:719
 msgid "Read"
 msgstr "Gelesen"
 
-#: aleksis/core/models.py:707
+#: aleksis/core/models.py:720
 msgid "Sent"
 msgstr "Versandt"
 
-#: aleksis/core/models.py:720
+#: aleksis/core/models.py:733
 msgid "Notification"
 msgstr "Benachrichtigung"
 
-#: aleksis/core/models.py:789
+#: aleksis/core/models.py:802
 msgid "Link to detailed view"
 msgstr "Link zur detaillierten Ansicht"
 
-#: aleksis/core/models.py:792
+#: aleksis/core/models.py:805
 msgid "Date and time from when to show"
 msgstr "Datum und Uhrzeit des Anzeigestarts"
 
-#: aleksis/core/models.py:795
+#: aleksis/core/models.py:808
 msgid "Date and time until when to show"
 msgstr "Anzeigezeitraum"
 
-#: aleksis/core/models.py:820
+#: aleksis/core/models.py:833
 msgid "Announcement"
 msgstr "Ankündigung"
 
-#: aleksis/core/models.py:858
+#: aleksis/core/models.py:871
 msgid "Announcement recipient"
 msgstr "Empfänger der Ankündigung"
 
-#: aleksis/core/models.py:859
+#: aleksis/core/models.py:872
 msgid "Announcement recipients"
 msgstr "Empfänger der Ankündigung"
 
-#: aleksis/core/models.py:914
+#: aleksis/core/models.py:894
 msgid "Widget Title"
 msgstr "Widget-Titel"
 
-#: aleksis/core/models.py:915
+#: aleksis/core/models.py:895
 msgid "Activate Widget"
 msgstr "Widget aktivieren"
 
-#: aleksis/core/models.py:916
+#: aleksis/core/models.py:896
 msgid "Widget is broken"
 msgstr "Widget ist kaputt"
 
-#: aleksis/core/models.py:919
+#: aleksis/core/models.py:899
 msgid "Size on mobile devices"
 msgstr "Größe auf Mobilgeräten"
 
-#: aleksis/core/models.py:920
+#: aleksis/core/models.py:900
 msgid "<= 600 px, 12 columns"
 msgstr "<= 600 px, 12 Spalten"
 
-#: aleksis/core/models.py:925
+#: aleksis/core/models.py:905
 msgid "Size on tablet devices"
 msgstr "Größe auf Tablets"
 
-#: aleksis/core/models.py:926
+#: aleksis/core/models.py:906
 msgid "> 600 px, 12 columns"
 msgstr "> 600px, 12 Spalten"
 
-#: aleksis/core/models.py:931
+#: aleksis/core/models.py:911
 msgid "Size on desktop devices"
 msgstr "Größe auf Desktopgeräten"
 
-#: aleksis/core/models.py:932
+#: aleksis/core/models.py:912
 msgid "> 992 px, 12 columns"
 msgstr "> 992 px, 12 Spalten"
 
-#: aleksis/core/models.py:937
+#: aleksis/core/models.py:917
 msgid "Size on large desktop devices"
 msgstr "Größe auf großen Desktopgeräten"
 
-#: aleksis/core/models.py:938
+#: aleksis/core/models.py:918
 msgid "> 1200 px>, 12 columns"
 msgstr "> 1200 px, 12 Spalten"
 
-#: aleksis/core/models.py:969
+#: aleksis/core/models.py:949
 msgid "Can edit default dashboard"
 msgstr "Kann Standarddashboard bearbeiten"
 
-#: aleksis/core/models.py:970
+#: aleksis/core/models.py:950
 msgid "Dashboard Widget"
 msgstr "Dashboard-Widget"
 
-#: aleksis/core/models.py:971
+#: aleksis/core/models.py:951
 msgid "Dashboard Widgets"
 msgstr "Dashboard-Widgets"
 
-#: aleksis/core/models.py:977
+#: aleksis/core/models.py:957
 msgid "URL"
 msgstr "URL"
 
-#: aleksis/core/models.py:978
+#: aleksis/core/models.py:958
 msgid "Icon URL"
 msgstr "Symbol-URL"
 
-#: aleksis/core/models.py:984
+#: aleksis/core/models.py:964
 msgid "External link widget"
 msgstr "Externer-Link-Widget"
 
-#: aleksis/core/models.py:985
+#: aleksis/core/models.py:965
 msgid "External link widgets"
 msgstr "Externer-Link-Widgets"
 
-#: aleksis/core/models.py:990
+#: aleksis/core/models.py:970
 msgid "Dashboard widget"
 msgstr "Dashboard-Widget"
 
-#: aleksis/core/models.py:995
+#: aleksis/core/models.py:975
 msgid "Order"
 msgstr "Reihenfolge"
 
-#: aleksis/core/models.py:996
+#: aleksis/core/models.py:976
 msgid "Part of the default dashboard"
 msgstr "Teil des Standarddashboards"
 
-#: aleksis/core/models.py:1011
+#: aleksis/core/models.py:991
 msgid "Dashboard widget order"
 msgstr "Reihenfolge der Dashboard-Widgets"
 
-#: aleksis/core/models.py:1012
+#: aleksis/core/models.py:992
 msgid "Dashboard widget orders"
 msgstr "Reihenfolgen der Dashboard-Widgets"
 
-#: aleksis/core/models.py:1018
+#: aleksis/core/models.py:998
 msgid "Menu ID"
 msgstr "Menü-ID"
 
-#: aleksis/core/models.py:1031
+#: aleksis/core/models.py:1011
 msgid "Custom menu"
 msgstr "Benutzerdefiniertes Menü"
 
-#: aleksis/core/models.py:1032
+#: aleksis/core/models.py:1012
 msgid "Custom menus"
 msgstr "Benutzerdefinierte Menüs"
 
-#: aleksis/core/models.py:1042
+#: aleksis/core/models.py:1022
 msgid "Menu"
 msgstr "Menü"
 
-#: aleksis/core/models.py:1046 aleksis/core/models.py:1285
+#: aleksis/core/models.py:1026 aleksis/core/models.py:1266
 #: aleksis/core/templates/oauth2_provider/application/detail.html:26
 msgid "Icon"
 msgstr "Symbol"
 
-#: aleksis/core/models.py:1052
+#: aleksis/core/models.py:1032
 msgid "Custom menu item"
 msgstr "Benutzerdefiniertes Menüelement"
 
-#: aleksis/core/models.py:1053
+#: aleksis/core/models.py:1033
 msgid "Custom menu items"
 msgstr "Benutzerdefinierte Menüelemente"
 
-#: aleksis/core/models.py:1067
+#: aleksis/core/models.py:1047
 msgid "Title of type"
 msgstr "Titel des Typs"
 
-#: aleksis/core/models.py:1074 aleksis/core/templates/core/group/full.html:47
+#: aleksis/core/models.py:1054 aleksis/core/templates/core/group/full.html:47
 msgid "Group type"
 msgstr "Gruppentyp"
 
-#: aleksis/core/models.py:1088
+#: aleksis/core/models.py:1068
 msgid "Can view system status"
 msgstr "Kann Systemstatus sehen"
 
-#: aleksis/core/models.py:1089
+#: aleksis/core/models.py:1069
 msgid "Can manage data"
 msgstr "Kann Daten verwalten"
 
-#: aleksis/core/models.py:1090
+#: aleksis/core/models.py:1070
 msgid "Can impersonate"
 msgstr "Kann sich verkleiden"
 
-#: aleksis/core/models.py:1091
+#: aleksis/core/models.py:1071
 msgid "Can use search"
 msgstr "Kann Suche benutzen"
 
-#: aleksis/core/models.py:1092
+#: aleksis/core/models.py:1072
 msgid "Can change site preferences"
 msgstr "Kann Konfiguration ändern"
 
-#: aleksis/core/models.py:1093
+#: aleksis/core/models.py:1073
 msgid "Can change person preferences"
 msgstr "Kann Einstellungen einer Person verändern"
 
-#: aleksis/core/models.py:1094
+#: aleksis/core/models.py:1074
 msgid "Can change group preferences"
 msgstr "Kann Einstellungen einer Gruppe verändern"
 
-#: aleksis/core/models.py:1095
+#: aleksis/core/models.py:1075
 msgid "Can test PDF generation"
 msgstr "Kann die PDF-Generierung testen"
 
-#: aleksis/core/models.py:1131
+#: aleksis/core/models.py:1076
+msgid "Can invite persons"
+msgstr "Kann Personen einladen"
+
+#: aleksis/core/models.py:1112
 msgid "Related data check task"
 msgstr "Zugehörige Datenprüfungsaufgabe"
 
-#: aleksis/core/models.py:1139
+#: aleksis/core/models.py:1120
 msgid "Issue solved"
 msgstr "Problem gelöst"
 
-#: aleksis/core/models.py:1140
+#: aleksis/core/models.py:1121
 msgid "Notification sent"
 msgstr "Benachrichtigung gesendet"
 
-#: aleksis/core/models.py:1153
+#: aleksis/core/models.py:1134
 msgid "Data check result"
 msgstr "Datenprüfungsergebnis"
 
-#: aleksis/core/models.py:1154
+#: aleksis/core/models.py:1135
 msgid "Data check results"
 msgstr "Datenprüfungsergebnisse"
 
-#: aleksis/core/models.py:1156
+#: aleksis/core/models.py:1137
 msgid "Can run data checks"
 msgstr "Kann Datenprüfungen ausführen"
 
-#: aleksis/core/models.py:1157
+#: aleksis/core/models.py:1138
 msgid "Can solve data check problems"
 msgstr "Kann Datenprüfungsprobleme lösen"
 
-#: aleksis/core/models.py:1164
+#: aleksis/core/models.py:1145
 msgid "E-Mail address"
 msgstr "E-Mail-Adresse"
 
-#: aleksis/core/models.py:1188
+#: aleksis/core/models.py:1169
 msgid "Owner"
 msgstr "Leiter"
 
-#: aleksis/core/models.py:1192
+#: aleksis/core/models.py:1173
 msgid "File expires at"
 msgstr "Datei abgelaufen am"
 
-#: aleksis/core/models.py:1194
+#: aleksis/core/models.py:1175
 msgid "Generated HTML file"
 msgstr "Generierte HTML-Datei"
 
-#: aleksis/core/models.py:1196
+#: aleksis/core/models.py:1177
 msgid "Generated PDF file"
 msgstr "Generierte PDF-Datei"
 
-#: aleksis/core/models.py:1203
+#: aleksis/core/models.py:1184
 msgid "PDF file"
 msgstr "PDF-Datei"
 
-#: aleksis/core/models.py:1204
+#: aleksis/core/models.py:1185
 msgid "PDF files"
 msgstr "PDF-Dateien"
 
-#: aleksis/core/models.py:1209
+#: aleksis/core/models.py:1190
 msgid "Task result"
 msgstr "Task-Ergebnis"
 
-#: aleksis/core/models.py:1212
+#: aleksis/core/models.py:1193
 msgid "Task user"
 msgstr "Task-Benutzer"
 
-#: aleksis/core/models.py:1224
+#: aleksis/core/models.py:1205
 msgid "Task user assignment"
 msgstr "Task-Benutzer-Zuordnung"
 
-#: aleksis/core/models.py:1225
+#: aleksis/core/models.py:1206
 msgid "Task user assignments"
 msgstr "Task-Benutzer-Zuordnungen"
 
-#: aleksis/core/models.py:1241
+#: aleksis/core/models.py:1222
 msgid "Additional attributes"
 msgstr "Zusätzliche Attribute"
 
-#: aleksis/core/models.py:1279
+#: aleksis/core/models.py:1260
 msgid "Allowed scopes that clients can request"
 msgstr "Erlaubte Scopes, die ein Client anfordern kann"
 
-#: aleksis/core/models.py:1289
+#: aleksis/core/models.py:1270
 msgid "This image will be shown as icon in the authorization flow. It should be squared."
 msgstr "Dieses Bild wird im Autorisierungs-Vorgang als Symbol angezeigt werden. Es sollte rechteckig sein."
 
@@ -994,7 +996,7 @@ msgstr "Authentifizierung"
 msgid "Internationalisation"
 msgstr "Internationalisierung"
 
-#: aleksis/core/preferences.py:44
+#: aleksis/core/preferences.py:43
 msgid "Site title"
 msgstr "Seitentitel"
 
@@ -1002,11 +1004,11 @@ msgstr "Seitentitel"
 msgid "Site description"
 msgstr "Seitenbeschreibung"
 
-#: aleksis/core/preferences.py:66
+#: aleksis/core/preferences.py:65
 msgid "Primary colour"
 msgstr "Primärfarbe"
 
-#: aleksis/core/preferences.py:78
+#: aleksis/core/preferences.py:77
 msgid "Secondary colour"
 msgstr "Akzentfarbe"
 
@@ -1014,147 +1016,151 @@ msgstr "Akzentfarbe"
 msgid "Logo"
 msgstr "Logo"
 
-#: aleksis/core/preferences.py:99
+#: aleksis/core/preferences.py:100
 msgid "Favicon"
 msgstr "Favicon"
 
-#: aleksis/core/preferences.py:109
+#: aleksis/core/preferences.py:111
 msgid "PWA-Icon"
 msgstr "PWA-Icon"
 
-#: aleksis/core/preferences.py:120
+#: aleksis/core/preferences.py:121
+msgid "PWA-Icon is maskable"
+msgstr "PWA-Symbol ist maskable"
+
+#: aleksis/core/preferences.py:133
 msgid "Mail out name"
 msgstr "Ausgangsmailname"
 
-#: aleksis/core/preferences.py:131
+#: aleksis/core/preferences.py:144
 msgid "Mail out address"
 msgstr "E-Mail-Ausgangsadresse"
 
-#: aleksis/core/preferences.py:143
+#: aleksis/core/preferences.py:157
 msgid "Link to privacy policy"
 msgstr "Link zur Datenschutzerklärung"
 
-#: aleksis/core/preferences.py:155
+#: aleksis/core/preferences.py:169
 msgid "Link to imprint"
 msgstr "Link zum Impressum"
 
-#: aleksis/core/preferences.py:167
+#: aleksis/core/preferences.py:180
 msgid "Name format for addressing"
 msgstr "Namensformat für Anreden"
 
-#: aleksis/core/preferences.py:183
+#: aleksis/core/preferences.py:197
 msgid "Channels to use for notifications"
 msgstr "Aktivierte Benachrichtungskanäle"
 
-#: aleksis/core/preferences.py:195
+#: aleksis/core/preferences.py:209
 msgid "Regular expression to match primary group, e.g. '^Class .*'"
 msgstr "Regulärer Ausdruck um Primärgruppen zu finden, z. B.  '^Class .*'"
 
-#: aleksis/core/preferences.py:206
+#: aleksis/core/preferences.py:220
 msgid "Field on person to match primary group against"
 msgstr "Feld um Primärgruppen zu finden"
 
-#: aleksis/core/preferences.py:218
+#: aleksis/core/preferences.py:232
 msgid "Automatically create new persons for new users"
 msgstr "Erstelle automatisch neue Personen für neue Benutzer"
 
-#: aleksis/core/preferences.py:227
+#: aleksis/core/preferences.py:241
 msgid "Automatically link existing persons to new users by their e-mail address"
 msgstr "Verknüpfe existierende Personen automatisch mit neuen Personen anhand ihrer E-Mail-Adresse"
 
-#: aleksis/core/preferences.py:238
+#: aleksis/core/preferences.py:252
 msgid "Display name of the school"
 msgstr "Sichtbarer Name der Schule"
 
-#: aleksis/core/preferences.py:249
+#: aleksis/core/preferences.py:263
 msgid "Official name of the school, e.g. as given by supervisory authority"
 msgstr "Offizieller Name der Schule, wie er z.B. von der Behörde vorgegeben ist"
 
-#: aleksis/core/preferences.py:257
+#: aleksis/core/preferences.py:271
 msgid "Allow users to change their passwords"
 msgstr "Erlaube Benutzern, ihr Passwort zu ändern"
 
-#: aleksis/core/preferences.py:265
+#: aleksis/core/preferences.py:279
 msgid "Enable signup"
 msgstr "Registrierung aktivieren"
 
-#: aleksis/core/preferences.py:273
+#: aleksis/core/preferences.py:287
 msgid "Enable invitations"
 msgstr "Einladungen aktivieren"
 
-#: aleksis/core/preferences.py:281
+#: aleksis/core/preferences.py:295
 msgid "Length of invite code. (Default 3: abcde-acbde-abcde)"
 msgstr "Länge des Einladungscodes. (Standard: 3: abcde-acbde-abcde)"
 
-#: aleksis/core/preferences.py:289
+#: aleksis/core/preferences.py:303
 msgid "Size of packets. (Default 5: abcde)"
 msgstr "Größe der Pakete. (Standard 5: abcde)"
 
-#: aleksis/core/preferences.py:300
+#: aleksis/core/preferences.py:314
 msgid "Allowed Grant Flows for OAuth applications"
 msgstr "Erlaubte Grant Flows für OAuth-Anwendungen"
 
-#: aleksis/core/preferences.py:313
+#: aleksis/core/preferences.py:328
 msgid "Available languages"
 msgstr "Verfügbare Sprachen"
 
-#: aleksis/core/preferences.py:325
+#: aleksis/core/preferences.py:341
 msgid "Send emails if data checks detect problems"
 msgstr "E-Mails versenden, wenn Datenprüfungen Probleme finden"
 
-#: aleksis/core/preferences.py:336
+#: aleksis/core/preferences.py:352
 msgid "Email recipients for data checks problem emails"
 msgstr "E-Mailempfänger für Datenprüfungsproblem-E-Mails"
 
-#: aleksis/core/preferences.py:347
+#: aleksis/core/preferences.py:363
 msgid "Email recipient groups for data checks problem emails"
 msgstr "E-Mail-Empfängergruppen für Datenprüfungsproblem-E-Mails"
 
-#: aleksis/core/preferences.py:356
+#: aleksis/core/preferences.py:372
 msgid "Show dashboard to users without login"
 msgstr "Zeige Dashboard für Benutzer ohne Login"
 
-#: aleksis/core/preferences.py:365
+#: aleksis/core/preferences.py:381
 msgid "Allow users to edit their dashboard"
 msgstr "Erlaube Benutzern, ihr Dashboard zu bearbeiten"
 
-#: aleksis/core/preferences.py:376
+#: aleksis/core/preferences.py:392
 msgid "Fields on person model which are editable by themselves."
 msgstr "Felder des Personen-Models welche von ihnen selbst editierbar sind."
 
-#: aleksis/core/preferences.py:390
+#: aleksis/core/preferences.py:407
 msgid "Editable fields on person model which should trigger a notification on change"
 msgstr "Editierbare Felder des Personen-Models welche eine Benachrichtigung für Änderungen auslösen soll"
 
-#: aleksis/core/preferences.py:403
+#: aleksis/core/preferences.py:421
 msgid "Contact for notification if a person changes their data"
 msgstr "Kontakt für Benachrichtigung, wenn eine Person ihre Daten ändert"
 
-#: aleksis/core/preferences.py:413
+#: aleksis/core/preferences.py:432
 msgid "PDF file expiration duration"
 msgstr "PDF-Datei-Ablaufdauer"
 
-#: aleksis/core/preferences.py:414
+#: aleksis/core/preferences.py:433
 msgid "in minutes"
 msgstr "in Minuten"
 
-#: aleksis/core/preferences.py:424
+#: aleksis/core/preferences.py:443
 msgid "Automatically update the dashboard and its widgets"
 msgstr "Automatisch das Dashboard und seine Widgets aktualisieren"
 
-#: aleksis/core/preferences.py:434
+#: aleksis/core/preferences.py:453
 msgid "Automatically update the dashboard and its widgets sitewide"
 msgstr "Automatisch das Dashboard und seine Widgets aktualisieren (auf der ganzen Seite)"
 
-#: aleksis/core/preferences.py:444
+#: aleksis/core/preferences.py:463
 msgid "Country for phone number parsing"
 msgstr "Land für das Einlesen von Telefonnummern"
 
-#: aleksis/core/settings.py:518
+#: aleksis/core/settings.py:526
 msgid "English"
 msgstr "Englisch"
 
-#: aleksis/core/settings.py:519
+#: aleksis/core/settings.py:527
 msgid "German"
 msgstr "Deutsch"
 
@@ -1559,7 +1565,7 @@ msgstr "Impressum"
 msgid "Privacy Policy"
 msgstr "Datenschutzerklärung"
 
-#: aleksis/core/templates/core/base_print.html:72
+#: aleksis/core/templates/core/base_print.html:74
 msgid "Powered by AlekSIS®"
 msgstr "Betrieben mit AlekSIS®"
 
@@ -2273,19 +2279,11 @@ msgstr "Benutzer einladen"
 msgid "Contact details"
 msgstr "Kontaktdetails"
 
-#: aleksis/core/templates/core/person/full.html:168
-msgid "home number"
-msgstr "Festnetznummer"
-
-#: aleksis/core/templates/core/person/full.html:174
-msgid "mobile number"
-msgstr "Handynummer"
-
-#: aleksis/core/templates/core/person/full.html:216
+#: aleksis/core/templates/core/person/full.html:224
 msgid "This person didn't upload a personal photo."
 msgstr "Diese Person hat kein persönliches Foto hochgeladen."
 
-#: aleksis/core/templates/core/person/full.html:224
+#: aleksis/core/templates/core/person/full.html:232
 msgid "Children"
 msgstr "Kinder"
 
@@ -2643,9 +2641,7 @@ msgstr "Celery-Task %(task_name)s fehlgeschlagen!"
 #: aleksis/core/templates/templated_email/celery_failure.email:7
 #, python-format
 msgid "the celery task %(task_name)s failed with following information:"
-msgstr ""
-"der Celery-Task  %(task_name)s ist mit folgenden Informationen "
-"fehlgeschlagen:"
+msgstr "der Celery-Task  %(task_name)s ist mit folgenden Informationen fehlgeschlagen:"
 
 #: aleksis/core/templates/templated_email/celery_failure.email:10
 #: aleksis/core/templates/templated_email/celery_failure.email:29
@@ -2675,8 +2671,7 @@ msgid ""
 "    "
 msgstr ""
 "\n"
-"      der Celery-Task  %(task_name)s ist mit folgenden Informationen "
-"fehlgeschlagen:\n"
+"      der Celery-Task  %(task_name)s ist mit folgenden Informationen fehlgeschlagen:\n"
 "    "
 
 #: aleksis/core/templates/templated_email/data_checks.email:3
@@ -2689,8 +2684,7 @@ msgid ""
 "Please take some time to inspect them and solve the issues or mark them as ignored."
 msgstr ""
 "das System hat einige neue Probleme mit Ihren Daten entdeckt.\n"
-"Bitte nehmen Sie sich etwas Zeit, diese zu überprüfen und sie zu lösen oder "
-"als ignoriert zu markieren."
+"Bitte nehmen Sie sich etwas Zeit, diese zu überprüfen und sie zu lösen oder als ignoriert zu markieren."
 
 #: aleksis/core/templates/templated_email/data_checks.email:15
 msgid ""
@@ -3233,23 +3227,23 @@ msgstr "E-Mail"
 msgid "SMS"
 msgstr "SMS"
 
-#: aleksis/core/util/pdf.py:113
+#: aleksis/core/util/pdf.py:118
 msgid "Progress: Generate PDF file"
 msgstr "Fortschritt: PDF-Datei generieren"
 
-#: aleksis/core/util/pdf.py:114
+#: aleksis/core/util/pdf.py:119
 msgid "Generating PDF file …"
 msgstr "PDF-Datei wird generiert …"
 
-#: aleksis/core/util/pdf.py:115
+#: aleksis/core/util/pdf.py:120
 msgid "The PDF file has been generated successfully."
 msgstr "Die PDF-Datei wurde erfolgreich generiert."
 
-#: aleksis/core/util/pdf.py:116
+#: aleksis/core/util/pdf.py:121
 msgid "There was a problem while generating the PDF file."
 msgstr "Es ist ein Fehler beim Generieren der PDF-Datei aufgetreten."
 
-#: aleksis/core/util/pdf.py:119
+#: aleksis/core/util/pdf.py:124
 msgid "Download PDF"
 msgstr "PDF herunterladen"
 
@@ -3399,14 +3393,28 @@ msgstr "Das Drittanbieter-Konto konnte nicht deaktiviert werden, weil es die ein
 msgid "The third-party account has been successfully disconnected."
 msgstr "Das Drittanbieter-Konto wurde erfolgreich getrennt."
 
-#: aleksis/core/views.py:1443
+#: aleksis/core/views.py:1445
 msgid "Person was invited successfully."
 msgstr "Person wurde erfolgreich eingeladen."
 
-#: aleksis/core/views.py:1445
+#: aleksis/core/views.py:1447
 msgid "Person was already invited."
 msgstr "Person wurde bereits eingeladen."
 
+#, python-brace-format
+#~ msgid "Last backup {time_gone_since_backup}!"
+#~ msgstr "Letztes Backup: {time_gone_since_backup}!"
+
+#, python-brace-format
+#~ msgid "{task.status} - {task.result}"
+#~ msgstr "{task.status} - {task.result}"
+
+#~ msgid "home number"
+#~ msgstr "Festnetznummer"
+
+#~ msgid "mobile number"
+#~ msgstr "Handynummer"
+
 #~ msgid "Hello,"
 #~ msgstr "Hallo,"
 
diff --git a/aleksis/core/locale/de_DE/LC_MESSAGES/djangojs.po b/aleksis/core/locale/de_DE/LC_MESSAGES/djangojs.po
index f408d36477e025333a264786ae5122993426604a..8ff775a37b0165883f3c2b0f3ff393c1478fd510 100644
--- a/aleksis/core/locale/de_DE/LC_MESSAGES/djangojs.po
+++ b/aleksis/core/locale/de_DE/LC_MESSAGES/djangojs.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2022-01-10 17:26+0100\n"
+"POT-Creation-Date: 2022-01-31 17:03+0100\n"
 "PO-Revision-Date: 2021-10-28 14:37+0000\n"
 "Last-Translator: Jonathan Weth <teckids@jonathanweth.de>\n"
 "Language-Team: German <https://translate.edugit.org/projects/aleksis/aleksis-core-js/de/>\n"
@@ -18,18 +18,18 @@ msgstr ""
 "Plural-Forms: nplurals=2; plural=n != 1;\n"
 "X-Generator: Weblate 4.8\n"
 
-#: aleksis/core/static/js/main.js:15
+#: aleksis/core/static/js/main.js:66
 msgid "Today"
 msgstr "Heute"
 
-#: aleksis/core/static/js/main.js:16
+#: aleksis/core/static/js/main.js:67
 msgid "Cancel"
 msgstr "Abbrechen"
 
-#: aleksis/core/static/js/main.js:17
+#: aleksis/core/static/js/main.js:68
 msgid "OK"
 msgstr "OK"
 
-#: aleksis/core/static/js/main.js:131
+#: aleksis/core/static/js/main.js:191
 msgid "This page may contain outdated information since there is no internet connection."
 msgstr "Diese Seite enthält vielleicht veraltete Informationen, da es keine Internetverbindung gibt."
diff --git a/aleksis/core/locale/fr/LC_MESSAGES/django.po b/aleksis/core/locale/fr/LC_MESSAGES/django.po
index eed24941dfdaf06338ec18052826aae3605eb234..f6af991023e49cc6e460b705e34b730af558f233 100644
--- a/aleksis/core/locale/fr/LC_MESSAGES/django.po
+++ b/aleksis/core/locale/fr/LC_MESSAGES/django.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: AlekSIS (School Information System) 0.1\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2022-01-10 17:26+0100\n"
+"POT-Creation-Date: 2022-01-31 17:03+0100\n"
 "PO-Revision-Date: 2021-06-16 12:00+0000\n"
 "Last-Translator: Jonathan Weth <teckids@jonathanweth.de>\n"
 "Language-Team: French <https://translate.edugit.org/projects/aleksis/aleksis/fr/>\n"
@@ -18,55 +18,55 @@ msgstr ""
 "Plural-Forms: nplurals=2; plural=n > 1;\n"
 "X-Generator: Weblate 4.4\n"
 
-#: aleksis/core/apps.py:154
+#: aleksis/core/apps.py:166
 msgid "OpenID Connect scope"
 msgstr ""
 
-#: aleksis/core/apps.py:155
+#: aleksis/core/apps.py:167
 msgid "Given name, family name, link to profile and picture if existing."
 msgstr ""
 
-#: aleksis/core/apps.py:156
+#: aleksis/core/apps.py:168
 msgid "Full home postal address"
 msgstr ""
 
-#: aleksis/core/apps.py:157
+#: aleksis/core/apps.py:169
 #, fuzzy
 #| msgid "Contact details"
 msgid "Email address"
 msgstr "Détails de contact"
 
-#: aleksis/core/apps.py:158
+#: aleksis/core/apps.py:170
 msgid "Home and mobile phone"
 msgstr ""
 
-#: aleksis/core/apps.py:159 aleksis/core/forms.py:223 aleksis/core/menus.py:265
-#: aleksis/core/models.py:449 aleksis/core/templates/core/group/list.html:8
+#: aleksis/core/apps.py:171 aleksis/core/forms.py:218 aleksis/core/menus.py:265
+#: aleksis/core/models.py:462 aleksis/core/templates/core/group/list.html:8
 #: aleksis/core/templates/core/group/list.html:9
-#: aleksis/core/templates/core/person/full.html:242
+#: aleksis/core/templates/core/person/full.html:250
 #, fuzzy
 #| msgid "Group"
 msgid "Groups"
 msgstr "Groupe"
 
-#: aleksis/core/data_checks.py:55
+#: aleksis/core/data_checks.py:56
 msgid "Ignore problem"
 msgstr ""
 
-#: aleksis/core/data_checks.py:184
+#: aleksis/core/data_checks.py:185
 #, python-brace-format
 msgid "Solve option '{solve_option_obj.verbose_name}' "
 msgstr ""
 
-#: aleksis/core/data_checks.py:290
+#: aleksis/core/data_checks.py:291
 msgid "Deactivate DashboardWidget"
 msgstr ""
 
-#: aleksis/core/data_checks.py:302
+#: aleksis/core/data_checks.py:303
 msgid "Ensure that there are no broken DashboardWidgets."
 msgstr ""
 
-#: aleksis/core/data_checks.py:303
+#: aleksis/core/data_checks.py:304
 msgid "The DashboardWidget was reported broken automatically."
 msgstr ""
 
@@ -97,15 +97,15 @@ msgstr ""
 msgid "Content type"
 msgstr ""
 
-#: aleksis/core/filters.py:113 aleksis/core/models.py:675
+#: aleksis/core/filters.py:113 aleksis/core/models.py:688
 msgid "User"
 msgstr ""
 
-#: aleksis/core/filters.py:135 aleksis/core/models.py:448
+#: aleksis/core/filters.py:135 aleksis/core/models.py:461
 msgid "Group"
 msgstr "groupe"
 
-#: aleksis/core/forms.py:48 aleksis/core/forms.py:559
+#: aleksis/core/forms.py:48 aleksis/core/forms.py:554
 msgid "Base data"
 msgstr ""
 
@@ -113,7 +113,7 @@ msgstr ""
 msgid "Address"
 msgstr ""
 
-#: aleksis/core/forms.py:54 aleksis/core/forms.py:568
+#: aleksis/core/forms.py:54 aleksis/core/forms.py:563
 #, fuzzy
 #| msgid "Contact details"
 msgid "Contact data"
@@ -133,25 +133,25 @@ msgstr ""
 msgid "Create a new account"
 msgstr ""
 
-#: aleksis/core/forms.py:135
+#: aleksis/core/forms.py:130
 msgid "You cannot set a new username when also selecting an existing user."
 msgstr ""
 
-#: aleksis/core/forms.py:139
+#: aleksis/core/forms.py:134
 msgid "This username is already in use."
 msgstr "Cet nom est deja en utilisation."
 
-#: aleksis/core/forms.py:156 aleksis/core/models.py:130
+#: aleksis/core/forms.py:151 aleksis/core/models.py:130
 msgid "School term"
 msgstr ""
 
-#: aleksis/core/forms.py:157
+#: aleksis/core/forms.py:152
 #, fuzzy
 #| msgid "Contact details"
 msgid "Common data"
 msgstr "Détails de contact"
 
-#: aleksis/core/forms.py:158 aleksis/core/forms.py:210
+#: aleksis/core/forms.py:153 aleksis/core/forms.py:205
 #: aleksis/core/menus.py:254 aleksis/core/models.py:153
 #: aleksis/core/templates/core/person/list.html:8
 #: aleksis/core/templates/core/person/list.html:9
@@ -160,102 +160,102 @@ msgstr "Détails de contact"
 msgid "Persons"
 msgstr "Personne"
 
-#: aleksis/core/forms.py:159 aleksis/core/forms.py:570
+#: aleksis/core/forms.py:154 aleksis/core/forms.py:565
 #, fuzzy
 #| msgid "Contact details"
 msgid "Additional data"
 msgstr "Détails de contact"
 
-#: aleksis/core/forms.py:160 aleksis/core/models.py:206
-#: aleksis/core/models.py:501
+#: aleksis/core/forms.py:155 aleksis/core/models.py:206
+#: aleksis/core/models.py:514
 msgid "Photo"
 msgstr ""
 
-#: aleksis/core/forms.py:202 aleksis/core/forms.py:205
+#: aleksis/core/forms.py:197 aleksis/core/forms.py:200
 #: aleksis/core/models.py:73
 msgid "Date"
 msgstr "Date"
 
-#: aleksis/core/forms.py:203 aleksis/core/forms.py:206
+#: aleksis/core/forms.py:198 aleksis/core/forms.py:201
 #: aleksis/core/models.py:81
 msgid "Time"
 msgstr ""
 
-#: aleksis/core/forms.py:236
+#: aleksis/core/forms.py:231
 msgid "From when until when should the announcement be displayed?"
 msgstr ""
 
-#: aleksis/core/forms.py:239
+#: aleksis/core/forms.py:234
 msgid "Who should see the announcement?"
 msgstr ""
 
-#: aleksis/core/forms.py:240
+#: aleksis/core/forms.py:235
 msgid "Write your announcement:"
 msgstr ""
 
-#: aleksis/core/forms.py:279
+#: aleksis/core/forms.py:274
 msgid "You are not allowed to create announcements which are only valid in the past."
 msgstr ""
 
-#: aleksis/core/forms.py:283
+#: aleksis/core/forms.py:278
 msgid "The from date and time must be earlier then the until date and time."
 msgstr ""
 
-#: aleksis/core/forms.py:292
+#: aleksis/core/forms.py:287
 msgid "You need at least one recipient."
 msgstr ""
 
-#: aleksis/core/forms.py:401
+#: aleksis/core/forms.py:396
 msgid "Invitation code"
 msgstr ""
 
-#: aleksis/core/forms.py:402
+#: aleksis/core/forms.py:397
 msgid "Please enter your invitation code."
 msgstr ""
 
-#: aleksis/core/forms.py:434
+#: aleksis/core/forms.py:429
 msgid "Who should get the permission?"
 msgstr ""
 
-#: aleksis/core/forms.py:435
+#: aleksis/core/forms.py:430
 msgid "On what?"
 msgstr ""
 
-#: aleksis/core/forms.py:461
+#: aleksis/core/forms.py:456
 msgid "Select objects which the permission should be granted for:"
 msgstr ""
 
-#: aleksis/core/forms.py:464
+#: aleksis/core/forms.py:459
 msgid "Grant the permission for all objects"
 msgstr ""
 
-#: aleksis/core/forms.py:472
+#: aleksis/core/forms.py:467
 msgid "You must select at least one group or person which should get the permission."
 msgstr ""
 
-#: aleksis/core/forms.py:477
+#: aleksis/core/forms.py:472
 msgid "You must grant the permission to all objects and/or to some objects."
 msgstr ""
 
-#: aleksis/core/forms.py:564
+#: aleksis/core/forms.py:559
 msgid "Adress data"
 msgstr ""
 
-#: aleksis/core/forms.py:576
+#: aleksis/core/forms.py:571
 #, fuzzy
 #| msgid "Contact details"
 msgid "Account data"
 msgstr "Détails de contact"
 
-#: aleksis/core/forms.py:583
+#: aleksis/core/forms.py:578
 msgid "Password"
 msgstr ""
 
-#: aleksis/core/forms.py:586
+#: aleksis/core/forms.py:581
 msgid "Password (again)"
 msgstr ""
 
-#: aleksis/core/forms.py:752
+#: aleksis/core/forms.py:747
 msgid "No valid selection."
 msgstr ""
 
@@ -263,22 +263,20 @@ msgstr ""
 msgid "There are unresolved data problems."
 msgstr ""
 
-#: aleksis/core/health_checks.py:44
-#, python-brace-format
-msgid "Last backup {time_gone_since_backup}!"
+#: aleksis/core/health_checks.py:40
+msgid "Error accessing backup storage: {}"
 msgstr ""
 
-#: aleksis/core/health_checks.py:46
-msgid "No backup found!"
+#: aleksis/core/health_checks.py:50
+msgid "Last backup {}!"
 msgstr ""
 
-#: aleksis/core/health_checks.py:73
-msgid "No backup result found!"
+#: aleksis/core/health_checks.py:52
+msgid "No backup found!"
 msgstr ""
 
-#: aleksis/core/health_checks.py:75
-#, python-brace-format
-msgid "{task.status} - {task.result}"
+#: aleksis/core/health_checks.py:79
+msgid "No backup result found!"
 msgstr ""
 
 #: aleksis/core/menus.py:9 aleksis/core/templates/two_factor/core/login.html:6
@@ -300,7 +298,7 @@ msgstr ""
 msgid "Dashboard"
 msgstr ""
 
-#: aleksis/core/menus.py:41 aleksis/core/models.py:721
+#: aleksis/core/menus.py:41 aleksis/core/models.py:734
 #: aleksis/core/preferences.py:29
 #: aleksis/core/templates/core/notifications.html:4
 #: aleksis/core/templates/core/notifications.html:5
@@ -358,7 +356,7 @@ msgstr ""
 msgid "Admin"
 msgstr ""
 
-#: aleksis/core/menus.py:141 aleksis/core/models.py:821
+#: aleksis/core/menus.py:141 aleksis/core/models.py:834
 #: aleksis/core/templates/core/announcement/list.html:7
 #: aleksis/core/templates/core/announcement/list.html:8
 msgid "Announcements"
@@ -416,7 +414,7 @@ msgstr ""
 msgid "People"
 msgstr ""
 
-#: aleksis/core/menus.py:276 aleksis/core/models.py:1075
+#: aleksis/core/menus.py:276 aleksis/core/models.py:1055
 #: aleksis/core/templates/core/group_type/list.html:8
 #: aleksis/core/templates/core/group_type/list.html:9
 #, fuzzy
@@ -428,7 +426,7 @@ msgstr "Groupe"
 msgid "Groups and child groups"
 msgstr ""
 
-#: aleksis/core/menus.py:298 aleksis/core/models.py:497
+#: aleksis/core/menus.py:298 aleksis/core/models.py:510
 #: aleksis/core/templates/core/additional_field/list.html:8
 #: aleksis/core/templates/core/additional_field/list.html:9
 msgid "Additional fields"
@@ -490,7 +488,7 @@ msgstr ""
 msgid "URL / Link"
 msgstr ""
 
-#: aleksis/core/models.py:94 aleksis/core/models.py:1044
+#: aleksis/core/models.py:94 aleksis/core/models.py:1024
 msgid "Name"
 msgstr ""
 
@@ -512,7 +510,7 @@ msgstr ""
 msgid "There is already a school term for this time or a part of this time."
 msgstr ""
 
-#: aleksis/core/models.py:152 aleksis/core/models.py:993
+#: aleksis/core/models.py:152 aleksis/core/models.py:973
 msgid "Person"
 msgstr "Personne"
 
@@ -560,7 +558,7 @@ msgstr ""
 msgid "male"
 msgstr ""
 
-#: aleksis/core/models.py:178 aleksis/core/models.py:1238
+#: aleksis/core/models.py:178 aleksis/core/models.py:1219
 msgid "Linked user"
 msgstr ""
 
@@ -576,7 +574,7 @@ msgstr "Nom de famille"
 msgid "Additional name(s)"
 msgstr ""
 
-#: aleksis/core/models.py:188 aleksis/core/models.py:466
+#: aleksis/core/models.py:188 aleksis/core/models.py:479
 #, fuzzy
 #| msgid "First name"
 msgid "Short name"
@@ -598,11 +596,11 @@ msgstr ""
 msgid "Place"
 msgstr ""
 
-#: aleksis/core/models.py:196
+#: aleksis/core/models.py:196 aleksis/core/templates/core/person/full.html:172
 msgid "Home phone"
 msgstr ""
 
-#: aleksis/core/models.py:197
+#: aleksis/core/models.py:197 aleksis/core/templates/core/person/full.html:182
 msgid "Mobile phone"
 msgstr ""
 
@@ -620,19 +618,19 @@ msgstr "Date d'anniversaire"
 msgid "Sex"
 msgstr "Sexe"
 
-#: aleksis/core/models.py:210 aleksis/core/models.py:505
+#: aleksis/core/models.py:210 aleksis/core/models.py:518
 msgid "This is an official photo, used for official documents and for internal use cases."
 msgstr ""
 
-#: aleksis/core/models.py:215 aleksis/core/models.py:509
+#: aleksis/core/models.py:215 aleksis/core/models.py:522
 msgid "Display picture / Avatar"
 msgstr ""
 
-#: aleksis/core/models.py:218 aleksis/core/models.py:512
+#: aleksis/core/models.py:218 aleksis/core/models.py:525
 msgid "This is a picture or an avatar for public display."
 msgstr ""
 
-#: aleksis/core/models.py:223 aleksis/core/templates/core/person/full.html:231
+#: aleksis/core/models.py:223 aleksis/core/templates/core/person/full.html:239
 msgid "Guardians / Parents"
 msgstr ""
 
@@ -640,380 +638,386 @@ msgstr ""
 msgid "Primary group"
 msgstr ""
 
-#: aleksis/core/models.py:233 aleksis/core/models.py:679
-#: aleksis/core/models.py:703 aleksis/core/models.py:788
-#: aleksis/core/models.py:1068
+#: aleksis/core/models.py:233 aleksis/core/models.py:692
+#: aleksis/core/models.py:716 aleksis/core/models.py:801
+#: aleksis/core/models.py:1048
 msgid "Description"
 msgstr "Description"
 
-#: aleksis/core/models.py:421
+#: aleksis/core/models.py:434
 msgid "Title of field"
 msgstr ""
 
-#: aleksis/core/models.py:423
+#: aleksis/core/models.py:436
 msgid "Type of field"
 msgstr ""
 
-#: aleksis/core/models.py:430
+#: aleksis/core/models.py:443
 msgid "Addtitional field for groups"
 msgstr ""
 
-#: aleksis/core/models.py:431
+#: aleksis/core/models.py:444
 msgid "Addtitional fields for groups"
 msgstr ""
 
-#: aleksis/core/models.py:451
+#: aleksis/core/models.py:464
 msgid "Can assign child groups to groups"
 msgstr ""
 
-#: aleksis/core/models.py:452
+#: aleksis/core/models.py:465
 #, fuzzy
 #| msgid "Contact details"
 msgid "Can view statistics about group."
 msgstr "Détails de contact"
 
-#: aleksis/core/models.py:464
+#: aleksis/core/models.py:477
 #, fuzzy
 #| msgid "Last name"
 msgid "Long name"
 msgstr "Nom de famille"
 
-#: aleksis/core/models.py:474 aleksis/core/templates/core/group/full.html:85
+#: aleksis/core/models.py:487 aleksis/core/templates/core/group/full.html:85
 msgid "Members"
 msgstr ""
 
-#: aleksis/core/models.py:477 aleksis/core/templates/core/group/full.html:82
+#: aleksis/core/models.py:490 aleksis/core/templates/core/group/full.html:82
 msgid "Owners"
 msgstr "Propriétaires"
 
-#: aleksis/core/models.py:484 aleksis/core/templates/core/group/full.html:55
+#: aleksis/core/models.py:497 aleksis/core/templates/core/group/full.html:55
 msgid "Parent groups"
 msgstr ""
 
-#: aleksis/core/models.py:492
+#: aleksis/core/models.py:505
 msgid "Type of group"
 msgstr ""
 
-#: aleksis/core/models.py:678 aleksis/core/models.py:702
-#: aleksis/core/models.py:787
+#: aleksis/core/models.py:691 aleksis/core/models.py:715
+#: aleksis/core/models.py:800
 #: aleksis/core/templates/core/announcement/list.html:18
 msgid "Title"
 msgstr ""
 
-#: aleksis/core/models.py:681
+#: aleksis/core/models.py:694
 msgid "Application"
 msgstr ""
 
-#: aleksis/core/models.py:687
+#: aleksis/core/models.py:700
 msgid "Activity"
 msgstr ""
 
-#: aleksis/core/models.py:688
+#: aleksis/core/models.py:701
 msgid "Activities"
 msgstr ""
 
-#: aleksis/core/models.py:694
+#: aleksis/core/models.py:707
 msgid "Sender"
 msgstr ""
 
-#: aleksis/core/models.py:699
+#: aleksis/core/models.py:712
 msgid "Recipient"
 msgstr ""
 
-#: aleksis/core/models.py:704 aleksis/core/models.py:1045
+#: aleksis/core/models.py:717 aleksis/core/models.py:1025
 msgid "Link"
 msgstr ""
 
-#: aleksis/core/models.py:706
+#: aleksis/core/models.py:719
 msgid "Read"
 msgstr ""
 
-#: aleksis/core/models.py:707
+#: aleksis/core/models.py:720
 msgid "Sent"
 msgstr ""
 
-#: aleksis/core/models.py:720
+#: aleksis/core/models.py:733
 msgid "Notification"
 msgstr ""
 
-#: aleksis/core/models.py:789
+#: aleksis/core/models.py:802
 msgid "Link to detailed view"
 msgstr ""
 
-#: aleksis/core/models.py:792
+#: aleksis/core/models.py:805
 msgid "Date and time from when to show"
 msgstr ""
 
-#: aleksis/core/models.py:795
+#: aleksis/core/models.py:808
 msgid "Date and time until when to show"
 msgstr ""
 
-#: aleksis/core/models.py:820
+#: aleksis/core/models.py:833
 msgid "Announcement"
 msgstr ""
 
-#: aleksis/core/models.py:858
+#: aleksis/core/models.py:871
 msgid "Announcement recipient"
 msgstr ""
 
-#: aleksis/core/models.py:859
+#: aleksis/core/models.py:872
 msgid "Announcement recipients"
 msgstr ""
 
-#: aleksis/core/models.py:914
+#: aleksis/core/models.py:894
 msgid "Widget Title"
 msgstr ""
 
-#: aleksis/core/models.py:915
+#: aleksis/core/models.py:895
 msgid "Activate Widget"
 msgstr ""
 
-#: aleksis/core/models.py:916
+#: aleksis/core/models.py:896
 msgid "Widget is broken"
 msgstr ""
 
-#: aleksis/core/models.py:919
+#: aleksis/core/models.py:899
 msgid "Size on mobile devices"
 msgstr ""
 
-#: aleksis/core/models.py:920
+#: aleksis/core/models.py:900
 msgid "<= 600 px, 12 columns"
 msgstr ""
 
-#: aleksis/core/models.py:925
+#: aleksis/core/models.py:905
 msgid "Size on tablet devices"
 msgstr ""
 
-#: aleksis/core/models.py:926
+#: aleksis/core/models.py:906
 msgid "> 600 px, 12 columns"
 msgstr ""
 
-#: aleksis/core/models.py:931
+#: aleksis/core/models.py:911
 msgid "Size on desktop devices"
 msgstr ""
 
-#: aleksis/core/models.py:932
+#: aleksis/core/models.py:912
 msgid "> 992 px, 12 columns"
 msgstr ""
 
-#: aleksis/core/models.py:937
+#: aleksis/core/models.py:917
 msgid "Size on large desktop devices"
 msgstr ""
 
-#: aleksis/core/models.py:938
+#: aleksis/core/models.py:918
 msgid "> 1200 px>, 12 columns"
 msgstr ""
 
-#: aleksis/core/models.py:969
+#: aleksis/core/models.py:949
 msgid "Can edit default dashboard"
 msgstr ""
 
-#: aleksis/core/models.py:970
+#: aleksis/core/models.py:950
 msgid "Dashboard Widget"
 msgstr ""
 
-#: aleksis/core/models.py:971
+#: aleksis/core/models.py:951
 msgid "Dashboard Widgets"
 msgstr ""
 
-#: aleksis/core/models.py:977
+#: aleksis/core/models.py:957
 msgid "URL"
 msgstr ""
 
-#: aleksis/core/models.py:978
+#: aleksis/core/models.py:958
 msgid "Icon URL"
 msgstr ""
 
-#: aleksis/core/models.py:984
+#: aleksis/core/models.py:964
 msgid "External link widget"
 msgstr ""
 
-#: aleksis/core/models.py:985
+#: aleksis/core/models.py:965
 msgid "External link widgets"
 msgstr ""
 
-#: aleksis/core/models.py:990
+#: aleksis/core/models.py:970
 msgid "Dashboard widget"
 msgstr ""
 
-#: aleksis/core/models.py:995
+#: aleksis/core/models.py:975
 msgid "Order"
 msgstr ""
 
-#: aleksis/core/models.py:996
+#: aleksis/core/models.py:976
 msgid "Part of the default dashboard"
 msgstr ""
 
-#: aleksis/core/models.py:1011
+#: aleksis/core/models.py:991
 msgid "Dashboard widget order"
 msgstr ""
 
-#: aleksis/core/models.py:1012
+#: aleksis/core/models.py:992
 msgid "Dashboard widget orders"
 msgstr ""
 
-#: aleksis/core/models.py:1018
+#: aleksis/core/models.py:998
 msgid "Menu ID"
 msgstr ""
 
-#: aleksis/core/models.py:1031
+#: aleksis/core/models.py:1011
 msgid "Custom menu"
 msgstr ""
 
-#: aleksis/core/models.py:1032
+#: aleksis/core/models.py:1012
 msgid "Custom menus"
 msgstr ""
 
-#: aleksis/core/models.py:1042
+#: aleksis/core/models.py:1022
 msgid "Menu"
 msgstr ""
 
-#: aleksis/core/models.py:1046 aleksis/core/models.py:1285
+#: aleksis/core/models.py:1026 aleksis/core/models.py:1266
 #: aleksis/core/templates/oauth2_provider/application/detail.html:26
 msgid "Icon"
 msgstr ""
 
-#: aleksis/core/models.py:1052
+#: aleksis/core/models.py:1032
 msgid "Custom menu item"
 msgstr ""
 
-#: aleksis/core/models.py:1053
+#: aleksis/core/models.py:1033
 msgid "Custom menu items"
 msgstr ""
 
-#: aleksis/core/models.py:1067
+#: aleksis/core/models.py:1047
 msgid "Title of type"
 msgstr ""
 
-#: aleksis/core/models.py:1074 aleksis/core/templates/core/group/full.html:47
+#: aleksis/core/models.py:1054 aleksis/core/templates/core/group/full.html:47
 #, fuzzy
 #| msgid "Group"
 msgid "Group type"
 msgstr "Groupe"
 
-#: aleksis/core/models.py:1088
+#: aleksis/core/models.py:1068
 #, fuzzy
 #| msgid "Contact details"
 msgid "Can view system status"
 msgstr "Détails de contact"
 
-#: aleksis/core/models.py:1089
+#: aleksis/core/models.py:1069
 msgid "Can manage data"
 msgstr ""
 
-#: aleksis/core/models.py:1090
+#: aleksis/core/models.py:1070
 #, fuzzy
 #| msgid "Contact details"
 msgid "Can impersonate"
 msgstr "Détails de contact"
 
-#: aleksis/core/models.py:1091
+#: aleksis/core/models.py:1071
 msgid "Can use search"
 msgstr ""
 
-#: aleksis/core/models.py:1092
+#: aleksis/core/models.py:1072
 msgid "Can change site preferences"
 msgstr ""
 
-#: aleksis/core/models.py:1093
+#: aleksis/core/models.py:1073
 msgid "Can change person preferences"
 msgstr ""
 
-#: aleksis/core/models.py:1094
+#: aleksis/core/models.py:1074
 msgid "Can change group preferences"
 msgstr ""
 
-#: aleksis/core/models.py:1095
+#: aleksis/core/models.py:1075
 msgid "Can test PDF generation"
 msgstr ""
 
-#: aleksis/core/models.py:1131
+#: aleksis/core/models.py:1076
+#, fuzzy
+#| msgid "Contact details"
+msgid "Can invite persons"
+msgstr "Détails de contact"
+
+#: aleksis/core/models.py:1112
 msgid "Related data check task"
 msgstr ""
 
-#: aleksis/core/models.py:1139
+#: aleksis/core/models.py:1120
 msgid "Issue solved"
 msgstr ""
 
-#: aleksis/core/models.py:1140
+#: aleksis/core/models.py:1121
 msgid "Notification sent"
 msgstr ""
 
-#: aleksis/core/models.py:1153
+#: aleksis/core/models.py:1134
 msgid "Data check result"
 msgstr ""
 
-#: aleksis/core/models.py:1154
+#: aleksis/core/models.py:1135
 msgid "Data check results"
 msgstr ""
 
-#: aleksis/core/models.py:1156
+#: aleksis/core/models.py:1137
 msgid "Can run data checks"
 msgstr ""
 
-#: aleksis/core/models.py:1157
+#: aleksis/core/models.py:1138
 msgid "Can solve data check problems"
 msgstr ""
 
-#: aleksis/core/models.py:1164
+#: aleksis/core/models.py:1145
 #, fuzzy
 #| msgid "Contact details"
 msgid "E-Mail address"
 msgstr "Détails de contact"
 
-#: aleksis/core/models.py:1188
+#: aleksis/core/models.py:1169
 #, fuzzy
 #| msgid "Owners"
 msgid "Owner"
 msgstr "Propriétaires"
 
-#: aleksis/core/models.py:1192
+#: aleksis/core/models.py:1173
 msgid "File expires at"
 msgstr ""
 
-#: aleksis/core/models.py:1194
+#: aleksis/core/models.py:1175
 msgid "Generated HTML file"
 msgstr ""
 
-#: aleksis/core/models.py:1196
+#: aleksis/core/models.py:1177
 msgid "Generated PDF file"
 msgstr ""
 
-#: aleksis/core/models.py:1203
+#: aleksis/core/models.py:1184
 msgid "PDF file"
 msgstr ""
 
-#: aleksis/core/models.py:1204
+#: aleksis/core/models.py:1185
 msgid "PDF files"
 msgstr ""
 
-#: aleksis/core/models.py:1209
+#: aleksis/core/models.py:1190
 msgid "Task result"
 msgstr ""
 
-#: aleksis/core/models.py:1212
+#: aleksis/core/models.py:1193
 msgid "Task user"
 msgstr ""
 
-#: aleksis/core/models.py:1224
+#: aleksis/core/models.py:1205
 msgid "Task user assignment"
 msgstr ""
 
-#: aleksis/core/models.py:1225
+#: aleksis/core/models.py:1206
 msgid "Task user assignments"
 msgstr ""
 
-#: aleksis/core/models.py:1241
+#: aleksis/core/models.py:1222
 #, fuzzy
 #| msgid "Contact details"
 msgid "Additional attributes"
 msgstr "Détails de contact"
 
-#: aleksis/core/models.py:1279
+#: aleksis/core/models.py:1260
 msgid "Allowed scopes that clients can request"
 msgstr ""
 
-#: aleksis/core/models.py:1289
+#: aleksis/core/models.py:1270
 msgid "This image will be shown as icon in the authorization flow. It should be squared."
 msgstr ""
 
@@ -1051,7 +1055,7 @@ msgstr ""
 msgid "Internationalisation"
 msgstr ""
 
-#: aleksis/core/preferences.py:44
+#: aleksis/core/preferences.py:43
 msgid "Site title"
 msgstr ""
 
@@ -1061,11 +1065,11 @@ msgstr ""
 msgid "Site description"
 msgstr "Description"
 
-#: aleksis/core/preferences.py:66
+#: aleksis/core/preferences.py:65
 msgid "Primary colour"
 msgstr ""
 
-#: aleksis/core/preferences.py:78
+#: aleksis/core/preferences.py:77
 msgid "Secondary colour"
 msgstr ""
 
@@ -1073,151 +1077,155 @@ msgstr ""
 msgid "Logo"
 msgstr ""
 
-#: aleksis/core/preferences.py:99
+#: aleksis/core/preferences.py:100
 msgid "Favicon"
 msgstr ""
 
-#: aleksis/core/preferences.py:109
+#: aleksis/core/preferences.py:111
 msgid "PWA-Icon"
 msgstr ""
 
-#: aleksis/core/preferences.py:120
+#: aleksis/core/preferences.py:121
+msgid "PWA-Icon is maskable"
+msgstr ""
+
+#: aleksis/core/preferences.py:133
 #, fuzzy
 #| msgid "Last name"
 msgid "Mail out name"
 msgstr "Nom de famille"
 
-#: aleksis/core/preferences.py:131
+#: aleksis/core/preferences.py:144
 msgid "Mail out address"
 msgstr ""
 
-#: aleksis/core/preferences.py:143
+#: aleksis/core/preferences.py:157
 msgid "Link to privacy policy"
 msgstr ""
 
-#: aleksis/core/preferences.py:155
+#: aleksis/core/preferences.py:169
 msgid "Link to imprint"
 msgstr ""
 
-#: aleksis/core/preferences.py:167
+#: aleksis/core/preferences.py:180
 msgid "Name format for addressing"
 msgstr ""
 
-#: aleksis/core/preferences.py:183
+#: aleksis/core/preferences.py:197
 msgid "Channels to use for notifications"
 msgstr ""
 
-#: aleksis/core/preferences.py:195
+#: aleksis/core/preferences.py:209
 msgid "Regular expression to match primary group, e.g. '^Class .*'"
 msgstr ""
 
-#: aleksis/core/preferences.py:206
+#: aleksis/core/preferences.py:220
 msgid "Field on person to match primary group against"
 msgstr ""
 
-#: aleksis/core/preferences.py:218
+#: aleksis/core/preferences.py:232
 msgid "Automatically create new persons for new users"
 msgstr ""
 
-#: aleksis/core/preferences.py:227
+#: aleksis/core/preferences.py:241
 msgid "Automatically link existing persons to new users by their e-mail address"
 msgstr ""
 
-#: aleksis/core/preferences.py:238
+#: aleksis/core/preferences.py:252
 msgid "Display name of the school"
 msgstr ""
 
-#: aleksis/core/preferences.py:249
+#: aleksis/core/preferences.py:263
 msgid "Official name of the school, e.g. as given by supervisory authority"
 msgstr ""
 
-#: aleksis/core/preferences.py:257
+#: aleksis/core/preferences.py:271
 msgid "Allow users to change their passwords"
 msgstr ""
 
-#: aleksis/core/preferences.py:265
+#: aleksis/core/preferences.py:279
 msgid "Enable signup"
 msgstr ""
 
-#: aleksis/core/preferences.py:273
+#: aleksis/core/preferences.py:287
 msgid "Enable invitations"
 msgstr ""
 
-#: aleksis/core/preferences.py:281
+#: aleksis/core/preferences.py:295
 msgid "Length of invite code. (Default 3: abcde-acbde-abcde)"
 msgstr ""
 
-#: aleksis/core/preferences.py:289
+#: aleksis/core/preferences.py:303
 msgid "Size of packets. (Default 5: abcde)"
 msgstr ""
 
-#: aleksis/core/preferences.py:300
+#: aleksis/core/preferences.py:314
 #, fuzzy
 #| msgid "Contact details"
 msgid "Allowed Grant Flows for OAuth applications"
 msgstr "Détails de contact"
 
-#: aleksis/core/preferences.py:313
+#: aleksis/core/preferences.py:328
 msgid "Available languages"
 msgstr ""
 
-#: aleksis/core/preferences.py:325
+#: aleksis/core/preferences.py:341
 msgid "Send emails if data checks detect problems"
 msgstr ""
 
-#: aleksis/core/preferences.py:336
+#: aleksis/core/preferences.py:352
 msgid "Email recipients for data checks problem emails"
 msgstr ""
 
-#: aleksis/core/preferences.py:347
+#: aleksis/core/preferences.py:363
 msgid "Email recipient groups for data checks problem emails"
 msgstr ""
 
-#: aleksis/core/preferences.py:356
+#: aleksis/core/preferences.py:372
 msgid "Show dashboard to users without login"
 msgstr ""
 
-#: aleksis/core/preferences.py:365
+#: aleksis/core/preferences.py:381
 msgid "Allow users to edit their dashboard"
 msgstr ""
 
-#: aleksis/core/preferences.py:376
+#: aleksis/core/preferences.py:392
 msgid "Fields on person model which are editable by themselves."
 msgstr ""
 
-#: aleksis/core/preferences.py:390
+#: aleksis/core/preferences.py:407
 msgid "Editable fields on person model which should trigger a notification on change"
 msgstr ""
 
-#: aleksis/core/preferences.py:403
+#: aleksis/core/preferences.py:421
 msgid "Contact for notification if a person changes their data"
 msgstr ""
 
-#: aleksis/core/preferences.py:413
+#: aleksis/core/preferences.py:432
 msgid "PDF file expiration duration"
 msgstr ""
 
-#: aleksis/core/preferences.py:414
+#: aleksis/core/preferences.py:433
 msgid "in minutes"
 msgstr ""
 
-#: aleksis/core/preferences.py:424
+#: aleksis/core/preferences.py:443
 msgid "Automatically update the dashboard and its widgets"
 msgstr ""
 
-#: aleksis/core/preferences.py:434
+#: aleksis/core/preferences.py:453
 msgid "Automatically update the dashboard and its widgets sitewide"
 msgstr ""
 
-#: aleksis/core/preferences.py:444
+#: aleksis/core/preferences.py:463
 msgid "Country for phone number parsing"
 msgstr ""
 
-#: aleksis/core/settings.py:518
+#: aleksis/core/settings.py:526
 msgid "English"
 msgstr ""
 
-#: aleksis/core/settings.py:519
+#: aleksis/core/settings.py:527
 msgid "German"
 msgstr ""
 
@@ -1564,7 +1572,7 @@ msgstr ""
 msgid "Privacy Policy"
 msgstr ""
 
-#: aleksis/core/templates/core/base_print.html:72
+#: aleksis/core/templates/core/base_print.html:74
 msgid "Powered by AlekSIS®"
 msgstr ""
 
@@ -2209,19 +2217,11 @@ msgstr ""
 msgid "Contact details"
 msgstr "Détails de contact"
 
-#: aleksis/core/templates/core/person/full.html:168
-msgid "home number"
-msgstr ""
-
-#: aleksis/core/templates/core/person/full.html:174
-msgid "mobile number"
-msgstr ""
-
-#: aleksis/core/templates/core/person/full.html:216
+#: aleksis/core/templates/core/person/full.html:224
 msgid "This person didn't upload a personal photo."
 msgstr ""
 
-#: aleksis/core/templates/core/person/full.html:224
+#: aleksis/core/templates/core/person/full.html:232
 msgid "Children"
 msgstr ""
 
@@ -3035,23 +3035,23 @@ msgstr ""
 msgid "SMS"
 msgstr ""
 
-#: aleksis/core/util/pdf.py:113
+#: aleksis/core/util/pdf.py:118
 msgid "Progress: Generate PDF file"
 msgstr ""
 
-#: aleksis/core/util/pdf.py:114
+#: aleksis/core/util/pdf.py:119
 msgid "Generating PDF file …"
 msgstr ""
 
-#: aleksis/core/util/pdf.py:115
+#: aleksis/core/util/pdf.py:120
 msgid "The PDF file has been generated successfully."
 msgstr ""
 
-#: aleksis/core/util/pdf.py:116
+#: aleksis/core/util/pdf.py:121
 msgid "There was a problem while generating the PDF file."
 msgstr ""
 
-#: aleksis/core/util/pdf.py:119
+#: aleksis/core/util/pdf.py:124
 msgid "Download PDF"
 msgstr ""
 
@@ -3201,11 +3201,11 @@ msgstr ""
 msgid "The third-party account has been successfully disconnected."
 msgstr ""
 
-#: aleksis/core/views.py:1443
+#: aleksis/core/views.py:1445
 msgid "Person was invited successfully."
 msgstr ""
 
-#: aleksis/core/views.py:1445
+#: aleksis/core/views.py:1447
 #, fuzzy
 #| msgid "This username is already in use."
 msgid "Person was already invited."
diff --git a/aleksis/core/locale/fr/LC_MESSAGES/djangojs.po b/aleksis/core/locale/fr/LC_MESSAGES/djangojs.po
index bc7dfc0233fb5fa726011468c71c4f4b782ac71d..bcaf32c82d64028ea3c98b6a83b591efd6c44e9b 100644
--- a/aleksis/core/locale/fr/LC_MESSAGES/djangojs.po
+++ b/aleksis/core/locale/fr/LC_MESSAGES/djangojs.po
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2022-01-10 17:26+0100\n"
+"POT-Creation-Date: 2022-01-31 17:03+0100\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"
@@ -18,18 +18,18 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n > 1);\n"
 
-#: aleksis/core/static/js/main.js:15
+#: aleksis/core/static/js/main.js:66
 msgid "Today"
 msgstr ""
 
-#: aleksis/core/static/js/main.js:16
+#: aleksis/core/static/js/main.js:67
 msgid "Cancel"
 msgstr ""
 
-#: aleksis/core/static/js/main.js:17
+#: aleksis/core/static/js/main.js:68
 msgid "OK"
 msgstr ""
 
-#: aleksis/core/static/js/main.js:131
+#: aleksis/core/static/js/main.js:191
 msgid "This page may contain outdated information since there is no internet connection."
 msgstr ""
diff --git a/aleksis/core/locale/la/LC_MESSAGES/django.po b/aleksis/core/locale/la/LC_MESSAGES/django.po
index 4f1582caa962701748b4076076a616abcf2a3889..42102a24126b6d5d152efc1b08140f00b93a45f5 100644
--- a/aleksis/core/locale/la/LC_MESSAGES/django.po
+++ b/aleksis/core/locale/la/LC_MESSAGES/django.po
@@ -7,7 +7,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2022-01-10 17:26+0100\n"
+"POT-Creation-Date: 2022-01-31 17:03+0100\n"
 "PO-Revision-Date: 2020-12-19 12:57+0000\n"
 "Last-Translator: Julian <leuckerj@gmail.com>\n"
 "Language-Team: Latin <https://translate.edugit.org/projects/aleksis/aleksis/la/>\n"
@@ -18,59 +18,59 @@ msgstr ""
 "Plural-Forms: nplurals=2; plural=n != 1;\n"
 "X-Generator: Weblate 4.3.2\n"
 
-#: aleksis/core/apps.py:154
+#: aleksis/core/apps.py:166
 msgid "OpenID Connect scope"
 msgstr ""
 
-#: aleksis/core/apps.py:155
+#: aleksis/core/apps.py:167
 msgid "Given name, family name, link to profile and picture if existing."
 msgstr ""
 
-#: aleksis/core/apps.py:156
+#: aleksis/core/apps.py:168
 #, fuzzy
 #| msgid "E-mail address"
 msgid "Full home postal address"
 msgstr "Inscriptio electronica"
 
-#: aleksis/core/apps.py:157
+#: aleksis/core/apps.py:169
 #, fuzzy
 #| msgid "E-mail address"
 msgid "Email address"
 msgstr "Inscriptio electronica"
 
-#: aleksis/core/apps.py:158
+#: aleksis/core/apps.py:170
 #, fuzzy
 #| msgid "Mobile phone"
 msgid "Home and mobile phone"
 msgstr "Numerus telephoni mobilis"
 
-#: aleksis/core/apps.py:159 aleksis/core/forms.py:223 aleksis/core/menus.py:265
-#: aleksis/core/models.py:449 aleksis/core/templates/core/group/list.html:8
+#: aleksis/core/apps.py:171 aleksis/core/forms.py:218 aleksis/core/menus.py:265
+#: aleksis/core/models.py:462 aleksis/core/templates/core/group/list.html:8
 #: aleksis/core/templates/core/group/list.html:9
-#: aleksis/core/templates/core/person/full.html:242
+#: aleksis/core/templates/core/person/full.html:250
 msgid "Groups"
 msgstr "Greges"
 
-#: aleksis/core/data_checks.py:55
+#: aleksis/core/data_checks.py:56
 msgid "Ignore problem"
 msgstr ""
 
-#: aleksis/core/data_checks.py:184
+#: aleksis/core/data_checks.py:185
 #, python-brace-format
 msgid "Solve option '{solve_option_obj.verbose_name}' "
 msgstr ""
 
-#: aleksis/core/data_checks.py:290
+#: aleksis/core/data_checks.py:291
 #, fuzzy
 #| msgid "Dashboard"
 msgid "Deactivate DashboardWidget"
 msgstr "Forum"
 
-#: aleksis/core/data_checks.py:302
+#: aleksis/core/data_checks.py:303
 msgid "Ensure that there are no broken DashboardWidgets."
 msgstr ""
 
-#: aleksis/core/data_checks.py:303
+#: aleksis/core/data_checks.py:304
 msgid "The DashboardWidget was reported broken automatically."
 msgstr ""
 
@@ -101,15 +101,15 @@ msgstr ""
 msgid "Content type"
 msgstr ""
 
-#: aleksis/core/filters.py:113 aleksis/core/models.py:675
+#: aleksis/core/filters.py:113 aleksis/core/models.py:688
 msgid "User"
 msgstr ""
 
-#: aleksis/core/filters.py:135 aleksis/core/models.py:448
+#: aleksis/core/filters.py:135 aleksis/core/models.py:461
 msgid "Group"
 msgstr "Grex"
 
-#: aleksis/core/forms.py:48 aleksis/core/forms.py:559
+#: aleksis/core/forms.py:48 aleksis/core/forms.py:554
 msgid "Base data"
 msgstr ""
 
@@ -119,7 +119,7 @@ msgstr ""
 msgid "Address"
 msgstr "Inscriptio electronica"
 
-#: aleksis/core/forms.py:54 aleksis/core/forms.py:568
+#: aleksis/core/forms.py:54 aleksis/core/forms.py:563
 msgid "Contact data"
 msgstr ""
 
@@ -137,131 +137,131 @@ msgstr ""
 msgid "Create a new account"
 msgstr "Personae et computi"
 
-#: aleksis/core/forms.py:135
+#: aleksis/core/forms.py:130
 msgid "You cannot set a new username when also selecting an existing user."
 msgstr ""
 
-#: aleksis/core/forms.py:139
+#: aleksis/core/forms.py:134
 msgid "This username is already in use."
 msgstr ""
 
-#: aleksis/core/forms.py:156 aleksis/core/models.py:130
+#: aleksis/core/forms.py:151 aleksis/core/models.py:130
 msgid "School term"
 msgstr "Anus scolae"
 
-#: aleksis/core/forms.py:157
+#: aleksis/core/forms.py:152
 #, fuzzy
 #| msgid "Data management"
 msgid "Common data"
 msgstr "Adminstratio datarum"
 
-#: aleksis/core/forms.py:158 aleksis/core/forms.py:210
+#: aleksis/core/forms.py:153 aleksis/core/forms.py:205
 #: aleksis/core/menus.py:254 aleksis/core/models.py:153
 #: aleksis/core/templates/core/person/list.html:8
 #: aleksis/core/templates/core/person/list.html:9
 msgid "Persons"
 msgstr "personae"
 
-#: aleksis/core/forms.py:159 aleksis/core/forms.py:570
+#: aleksis/core/forms.py:154 aleksis/core/forms.py:565
 #, fuzzy
 #| msgid "Additional name(s)"
 msgid "Additional data"
 msgstr "addita nomines"
 
-#: aleksis/core/forms.py:160 aleksis/core/models.py:206
-#: aleksis/core/models.py:501
+#: aleksis/core/forms.py:155 aleksis/core/models.py:206
+#: aleksis/core/models.py:514
 msgid "Photo"
 msgstr "Photographia"
 
-#: aleksis/core/forms.py:202 aleksis/core/forms.py:205
+#: aleksis/core/forms.py:197 aleksis/core/forms.py:200
 #: aleksis/core/models.py:73
 msgid "Date"
 msgstr "dies"
 
-#: aleksis/core/forms.py:203 aleksis/core/forms.py:206
+#: aleksis/core/forms.py:198 aleksis/core/forms.py:201
 #: aleksis/core/models.py:81
 msgid "Time"
 msgstr "tempus"
 
-#: aleksis/core/forms.py:236
+#: aleksis/core/forms.py:231
 msgid "From when until when should the announcement be displayed?"
 msgstr ""
 
-#: aleksis/core/forms.py:239
+#: aleksis/core/forms.py:234
 msgid "Who should see the announcement?"
 msgstr "Quis nuntium videatne?"
 
-#: aleksis/core/forms.py:240
+#: aleksis/core/forms.py:235
 msgid "Write your announcement:"
 msgstr "Scribe nuntium:"
 
-#: aleksis/core/forms.py:279
+#: aleksis/core/forms.py:274
 msgid "You are not allowed to create announcements which are only valid in the past."
 msgstr ""
 
-#: aleksis/core/forms.py:283
+#: aleksis/core/forms.py:278
 msgid "The from date and time must be earlier then the until date and time."
 msgstr ""
 
-#: aleksis/core/forms.py:292
+#: aleksis/core/forms.py:287
 msgid "You need at least one recipient."
 msgstr ""
 
-#: aleksis/core/forms.py:401
+#: aleksis/core/forms.py:396
 msgid "Invitation code"
 msgstr ""
 
-#: aleksis/core/forms.py:402
+#: aleksis/core/forms.py:397
 msgid "Please enter your invitation code."
 msgstr ""
 
-#: aleksis/core/forms.py:434
+#: aleksis/core/forms.py:429
 #, fuzzy
 #| msgid "Who should see the announcement?"
 msgid "Who should get the permission?"
 msgstr "Quis nuntium videatne?"
 
-#: aleksis/core/forms.py:435
+#: aleksis/core/forms.py:430
 msgid "On what?"
 msgstr ""
 
-#: aleksis/core/forms.py:461
+#: aleksis/core/forms.py:456
 msgid "Select objects which the permission should be granted for:"
 msgstr ""
 
-#: aleksis/core/forms.py:464
+#: aleksis/core/forms.py:459
 msgid "Grant the permission for all objects"
 msgstr ""
 
-#: aleksis/core/forms.py:472
+#: aleksis/core/forms.py:467
 msgid "You must select at least one group or person which should get the permission."
 msgstr ""
 
-#: aleksis/core/forms.py:477
+#: aleksis/core/forms.py:472
 msgid "You must grant the permission to all objects and/or to some objects."
 msgstr ""
 
-#: aleksis/core/forms.py:564
+#: aleksis/core/forms.py:559
 #, fuzzy
 #| msgid "E-mail address"
 msgid "Adress data"
 msgstr "Inscriptio electronica"
 
-#: aleksis/core/forms.py:576
+#: aleksis/core/forms.py:571
 #, fuzzy
 #| msgid "Data management"
 msgid "Account data"
 msgstr "Adminstratio datarum"
 
-#: aleksis/core/forms.py:583
+#: aleksis/core/forms.py:578
 msgid "Password"
 msgstr ""
 
-#: aleksis/core/forms.py:586
+#: aleksis/core/forms.py:581
 msgid "Password (again)"
 msgstr ""
 
-#: aleksis/core/forms.py:752
+#: aleksis/core/forms.py:747
 msgid "No valid selection."
 msgstr ""
 
@@ -271,22 +271,20 @@ msgstr ""
 msgid "There are unresolved data problems."
 msgstr "Scribe nuntium:"
 
-#: aleksis/core/health_checks.py:44
-#, python-brace-format
-msgid "Last backup {time_gone_since_backup}!"
+#: aleksis/core/health_checks.py:40
+msgid "Error accessing backup storage: {}"
 msgstr ""
 
-#: aleksis/core/health_checks.py:46
-msgid "No backup found!"
+#: aleksis/core/health_checks.py:50
+msgid "Last backup {}!"
 msgstr ""
 
-#: aleksis/core/health_checks.py:73
-msgid "No backup result found!"
+#: aleksis/core/health_checks.py:52
+msgid "No backup found!"
 msgstr ""
 
-#: aleksis/core/health_checks.py:75
-#, python-brace-format
-msgid "{task.status} - {task.result}"
+#: aleksis/core/health_checks.py:79
+msgid "No backup result found!"
 msgstr ""
 
 #: aleksis/core/menus.py:9 aleksis/core/templates/two_factor/core/login.html:6
@@ -310,7 +308,7 @@ msgstr "Muta informationes scolae"
 msgid "Dashboard"
 msgstr "Forum"
 
-#: aleksis/core/menus.py:41 aleksis/core/models.py:721
+#: aleksis/core/menus.py:41 aleksis/core/models.py:734
 #: aleksis/core/preferences.py:29
 #: aleksis/core/templates/core/notifications.html:4
 #: aleksis/core/templates/core/notifications.html:5
@@ -372,7 +370,7 @@ msgstr "Nuntii"
 msgid "Admin"
 msgstr "Administratio"
 
-#: aleksis/core/menus.py:141 aleksis/core/models.py:821
+#: aleksis/core/menus.py:141 aleksis/core/models.py:834
 #: aleksis/core/templates/core/announcement/list.html:7
 #: aleksis/core/templates/core/announcement/list.html:8
 msgid "Announcements"
@@ -438,7 +436,7 @@ msgstr "Nuntii"
 msgid "People"
 msgstr "Personae"
 
-#: aleksis/core/menus.py:276 aleksis/core/models.py:1075
+#: aleksis/core/menus.py:276 aleksis/core/models.py:1055
 #: aleksis/core/templates/core/group_type/list.html:8
 #: aleksis/core/templates/core/group_type/list.html:9
 #, fuzzy
@@ -450,7 +448,7 @@ msgstr "Greges"
 msgid "Groups and child groups"
 msgstr ""
 
-#: aleksis/core/menus.py:298 aleksis/core/models.py:497
+#: aleksis/core/menus.py:298 aleksis/core/models.py:510
 #: aleksis/core/templates/core/additional_field/list.html:8
 #: aleksis/core/templates/core/additional_field/list.html:9
 #, fuzzy
@@ -518,7 +516,7 @@ msgstr ""
 msgid "URL / Link"
 msgstr ""
 
-#: aleksis/core/models.py:94 aleksis/core/models.py:1044
+#: aleksis/core/models.py:94 aleksis/core/models.py:1024
 msgid "Name"
 msgstr "Nomen"
 
@@ -538,7 +536,7 @@ msgstr ""
 msgid "There is already a school term for this time or a part of this time."
 msgstr ""
 
-#: aleksis/core/models.py:152 aleksis/core/models.py:993
+#: aleksis/core/models.py:152 aleksis/core/models.py:973
 msgid "Person"
 msgstr "Persona"
 
@@ -586,7 +584,7 @@ msgstr "femininum"
 msgid "male"
 msgstr "maskulinum"
 
-#: aleksis/core/models.py:178 aleksis/core/models.py:1238
+#: aleksis/core/models.py:178 aleksis/core/models.py:1219
 msgid "Linked user"
 msgstr ""
 
@@ -602,7 +600,7 @@ msgstr "Secondus nomen"
 msgid "Additional name(s)"
 msgstr "addita nomines"
 
-#: aleksis/core/models.py:188 aleksis/core/models.py:466
+#: aleksis/core/models.py:188 aleksis/core/models.py:479
 msgid "Short name"
 msgstr "Breve nomen"
 
@@ -622,11 +620,11 @@ msgstr "Numerus directorius"
 msgid "Place"
 msgstr "Urbs"
 
-#: aleksis/core/models.py:196
+#: aleksis/core/models.py:196 aleksis/core/templates/core/person/full.html:172
 msgid "Home phone"
 msgstr "Numerus telephoni domi"
 
-#: aleksis/core/models.py:197
+#: aleksis/core/models.py:197 aleksis/core/templates/core/person/full.html:182
 msgid "Mobile phone"
 msgstr "Numerus telephoni mobilis"
 
@@ -644,19 +642,19 @@ msgstr "Dies natalis"
 msgid "Sex"
 msgstr "Genus"
 
-#: aleksis/core/models.py:210 aleksis/core/models.py:505
+#: aleksis/core/models.py:210 aleksis/core/models.py:518
 msgid "This is an official photo, used for official documents and for internal use cases."
 msgstr ""
 
-#: aleksis/core/models.py:215 aleksis/core/models.py:509
+#: aleksis/core/models.py:215 aleksis/core/models.py:522
 msgid "Display picture / Avatar"
 msgstr ""
 
-#: aleksis/core/models.py:218 aleksis/core/models.py:512
+#: aleksis/core/models.py:218 aleksis/core/models.py:525
 msgid "This is a picture or an avatar for public display."
 msgstr ""
 
-#: aleksis/core/models.py:223 aleksis/core/templates/core/person/full.html:231
+#: aleksis/core/models.py:223 aleksis/core/templates/core/person/full.html:239
 msgid "Guardians / Parents"
 msgstr "Parentes"
 
@@ -664,412 +662,418 @@ msgstr "Parentes"
 msgid "Primary group"
 msgstr ""
 
-#: aleksis/core/models.py:233 aleksis/core/models.py:679
-#: aleksis/core/models.py:703 aleksis/core/models.py:788
-#: aleksis/core/models.py:1068
+#: aleksis/core/models.py:233 aleksis/core/models.py:692
+#: aleksis/core/models.py:716 aleksis/core/models.py:801
+#: aleksis/core/models.py:1048
 msgid "Description"
 msgstr "Descriptio"
 
-#: aleksis/core/models.py:421
+#: aleksis/core/models.py:434
 msgid "Title of field"
 msgstr ""
 
-#: aleksis/core/models.py:423
+#: aleksis/core/models.py:436
 msgid "Type of field"
 msgstr ""
 
-#: aleksis/core/models.py:430
+#: aleksis/core/models.py:443
 #, fuzzy
 #| msgid "Additional name(s)"
 msgid "Addtitional field for groups"
 msgstr "addita nomines"
 
-#: aleksis/core/models.py:431
+#: aleksis/core/models.py:444
 #, fuzzy
 #| msgid "Additional name(s)"
 msgid "Addtitional fields for groups"
 msgstr "addita nomines"
 
-#: aleksis/core/models.py:451
+#: aleksis/core/models.py:464
 msgid "Can assign child groups to groups"
 msgstr ""
 
-#: aleksis/core/models.py:452
+#: aleksis/core/models.py:465
 #, fuzzy
 #| msgid "Persons and accounts"
 msgid "Can view statistics about group."
 msgstr "Personae et computi"
 
-#: aleksis/core/models.py:464
+#: aleksis/core/models.py:477
 #, fuzzy
 #| msgid "Last name"
 msgid "Long name"
 msgstr "Secondus nomen"
 
-#: aleksis/core/models.py:474 aleksis/core/templates/core/group/full.html:85
+#: aleksis/core/models.py:487 aleksis/core/templates/core/group/full.html:85
 msgid "Members"
 msgstr ""
 
-#: aleksis/core/models.py:477 aleksis/core/templates/core/group/full.html:82
+#: aleksis/core/models.py:490 aleksis/core/templates/core/group/full.html:82
 msgid "Owners"
 msgstr ""
 
-#: aleksis/core/models.py:484 aleksis/core/templates/core/group/full.html:55
+#: aleksis/core/models.py:497 aleksis/core/templates/core/group/full.html:55
 msgid "Parent groups"
 msgstr ""
 
-#: aleksis/core/models.py:492
+#: aleksis/core/models.py:505
 msgid "Type of group"
 msgstr ""
 
-#: aleksis/core/models.py:678 aleksis/core/models.py:702
-#: aleksis/core/models.py:787
+#: aleksis/core/models.py:691 aleksis/core/models.py:715
+#: aleksis/core/models.py:800
 #: aleksis/core/templates/core/announcement/list.html:18
 msgid "Title"
 msgstr "Titulus"
 
-#: aleksis/core/models.py:681
+#: aleksis/core/models.py:694
 msgid "Application"
 msgstr ""
 
-#: aleksis/core/models.py:687
+#: aleksis/core/models.py:700
 msgid "Activity"
 msgstr ""
 
-#: aleksis/core/models.py:688
+#: aleksis/core/models.py:701
 msgid "Activities"
 msgstr ""
 
-#: aleksis/core/models.py:694
+#: aleksis/core/models.py:707
 msgid "Sender"
 msgstr "Mittens"
 
-#: aleksis/core/models.py:699
+#: aleksis/core/models.py:712
 msgid "Recipient"
 msgstr ""
 
-#: aleksis/core/models.py:704 aleksis/core/models.py:1045
+#: aleksis/core/models.py:717 aleksis/core/models.py:1025
 msgid "Link"
 msgstr ""
 
-#: aleksis/core/models.py:706
+#: aleksis/core/models.py:719
 msgid "Read"
 msgstr ""
 
-#: aleksis/core/models.py:707
+#: aleksis/core/models.py:720
 msgid "Sent"
 msgstr ""
 
-#: aleksis/core/models.py:720
+#: aleksis/core/models.py:733
 #, fuzzy
 #| msgid "Notifications"
 msgid "Notification"
 msgstr "Nuntii"
 
-#: aleksis/core/models.py:789
+#: aleksis/core/models.py:802
 msgid "Link to detailed view"
 msgstr ""
 
-#: aleksis/core/models.py:792
+#: aleksis/core/models.py:805
 msgid "Date and time from when to show"
 msgstr ""
 
-#: aleksis/core/models.py:795
+#: aleksis/core/models.py:808
 msgid "Date and time until when to show"
 msgstr ""
 
-#: aleksis/core/models.py:820
+#: aleksis/core/models.py:833
 #, fuzzy
 #| msgid "Announcements"
 msgid "Announcement"
 msgstr "Nuntii"
 
-#: aleksis/core/models.py:858
+#: aleksis/core/models.py:871
 #, fuzzy
 #| msgid "Announcements"
 msgid "Announcement recipient"
 msgstr "Nuntii"
 
-#: aleksis/core/models.py:859
+#: aleksis/core/models.py:872
 #, fuzzy
 #| msgid "Announcements"
 msgid "Announcement recipients"
 msgstr "Nuntii"
 
-#: aleksis/core/models.py:914
+#: aleksis/core/models.py:894
 #, fuzzy
 #| msgid "Site title"
 msgid "Widget Title"
 msgstr "Titulus paginae"
 
-#: aleksis/core/models.py:915
+#: aleksis/core/models.py:895
 msgid "Activate Widget"
 msgstr ""
 
-#: aleksis/core/models.py:916
+#: aleksis/core/models.py:896
 #, fuzzy
 #| msgid "Site title"
 msgid "Widget is broken"
 msgstr "Titulus paginae"
 
-#: aleksis/core/models.py:919
+#: aleksis/core/models.py:899
 msgid "Size on mobile devices"
 msgstr ""
 
-#: aleksis/core/models.py:920
+#: aleksis/core/models.py:900
 msgid "<= 600 px, 12 columns"
 msgstr ""
 
-#: aleksis/core/models.py:925
+#: aleksis/core/models.py:905
 msgid "Size on tablet devices"
 msgstr ""
 
-#: aleksis/core/models.py:926
+#: aleksis/core/models.py:906
 msgid "> 600 px, 12 columns"
 msgstr ""
 
-#: aleksis/core/models.py:931
+#: aleksis/core/models.py:911
 msgid "Size on desktop devices"
 msgstr ""
 
-#: aleksis/core/models.py:932
+#: aleksis/core/models.py:912
 msgid "> 992 px, 12 columns"
 msgstr ""
 
-#: aleksis/core/models.py:937
+#: aleksis/core/models.py:917
 msgid "Size on large desktop devices"
 msgstr ""
 
-#: aleksis/core/models.py:938
+#: aleksis/core/models.py:918
 msgid "> 1200 px>, 12 columns"
 msgstr ""
 
-#: aleksis/core/models.py:969
+#: aleksis/core/models.py:949
 #, fuzzy
 #| msgid "Dashboard"
 msgid "Can edit default dashboard"
 msgstr "Forum"
 
-#: aleksis/core/models.py:970
+#: aleksis/core/models.py:950
 #, fuzzy
 #| msgid "Dashboard"
 msgid "Dashboard Widget"
 msgstr "Forum"
 
-#: aleksis/core/models.py:971
+#: aleksis/core/models.py:951
 #, fuzzy
 #| msgid "Dashboard"
 msgid "Dashboard Widgets"
 msgstr "Forum"
 
-#: aleksis/core/models.py:977
+#: aleksis/core/models.py:957
 msgid "URL"
 msgstr ""
 
-#: aleksis/core/models.py:978
+#: aleksis/core/models.py:958
 #, fuzzy
 #| msgid "Icon"
 msgid "Icon URL"
 msgstr "Nota"
 
-#: aleksis/core/models.py:984
+#: aleksis/core/models.py:964
 msgid "External link widget"
 msgstr ""
 
-#: aleksis/core/models.py:985
+#: aleksis/core/models.py:965
 msgid "External link widgets"
 msgstr ""
 
-#: aleksis/core/models.py:990
+#: aleksis/core/models.py:970
 #, fuzzy
 #| msgid "Dashboard"
 msgid "Dashboard widget"
 msgstr "Forum"
 
-#: aleksis/core/models.py:995
+#: aleksis/core/models.py:975
 msgid "Order"
 msgstr ""
 
-#: aleksis/core/models.py:996
+#: aleksis/core/models.py:976
 msgid "Part of the default dashboard"
 msgstr ""
 
-#: aleksis/core/models.py:1011
+#: aleksis/core/models.py:991
 #, fuzzy
 #| msgid "Dashboard"
 msgid "Dashboard widget order"
 msgstr "Forum"
 
-#: aleksis/core/models.py:1012
+#: aleksis/core/models.py:992
 #, fuzzy
 #| msgid "Dashboard"
 msgid "Dashboard widget orders"
 msgstr "Forum"
 
-#: aleksis/core/models.py:1018
+#: aleksis/core/models.py:998
 msgid "Menu ID"
 msgstr ""
 
-#: aleksis/core/models.py:1031
+#: aleksis/core/models.py:1011
 msgid "Custom menu"
 msgstr ""
 
-#: aleksis/core/models.py:1032
+#: aleksis/core/models.py:1012
 msgid "Custom menus"
 msgstr ""
 
-#: aleksis/core/models.py:1042
+#: aleksis/core/models.py:1022
 msgid "Menu"
 msgstr ""
 
-#: aleksis/core/models.py:1046 aleksis/core/models.py:1285
+#: aleksis/core/models.py:1026 aleksis/core/models.py:1266
 #: aleksis/core/templates/oauth2_provider/application/detail.html:26
 msgid "Icon"
 msgstr "Nota"
 
-#: aleksis/core/models.py:1052
+#: aleksis/core/models.py:1032
 msgid "Custom menu item"
 msgstr ""
 
-#: aleksis/core/models.py:1053
+#: aleksis/core/models.py:1033
 msgid "Custom menu items"
 msgstr ""
 
-#: aleksis/core/models.py:1067
+#: aleksis/core/models.py:1047
 msgid "Title of type"
 msgstr ""
 
-#: aleksis/core/models.py:1074 aleksis/core/templates/core/group/full.html:47
+#: aleksis/core/models.py:1054 aleksis/core/templates/core/group/full.html:47
 #, fuzzy
 #| msgid "Group"
 msgid "Group type"
 msgstr "Grex"
 
-#: aleksis/core/models.py:1088
+#: aleksis/core/models.py:1068
 #, fuzzy
 #| msgid "System status"
 msgid "Can view system status"
 msgstr "Status systemae"
 
-#: aleksis/core/models.py:1089
+#: aleksis/core/models.py:1069
 #, fuzzy
 #| msgid "Data management"
 msgid "Can manage data"
 msgstr "Adminstratio datarum"
 
-#: aleksis/core/models.py:1090
+#: aleksis/core/models.py:1070
 #, fuzzy
 #| msgid "Stop impersonation"
 msgid "Can impersonate"
 msgstr "Simulandum aliquem finire"
 
-#: aleksis/core/models.py:1091
+#: aleksis/core/models.py:1071
 msgid "Can use search"
 msgstr ""
 
-#: aleksis/core/models.py:1092
+#: aleksis/core/models.py:1072
 msgid "Can change site preferences"
 msgstr ""
 
-#: aleksis/core/models.py:1093
+#: aleksis/core/models.py:1073
 msgid "Can change person preferences"
 msgstr ""
 
-#: aleksis/core/models.py:1094
+#: aleksis/core/models.py:1074
 msgid "Can change group preferences"
 msgstr ""
 
-#: aleksis/core/models.py:1095
+#: aleksis/core/models.py:1075
 msgid "Can test PDF generation"
 msgstr ""
 
-#: aleksis/core/models.py:1131
+#: aleksis/core/models.py:1076
+#, fuzzy
+#| msgid "Stop impersonation"
+msgid "Can invite persons"
+msgstr "Simulandum aliquem finire"
+
+#: aleksis/core/models.py:1112
 msgid "Related data check task"
 msgstr ""
 
-#: aleksis/core/models.py:1139
+#: aleksis/core/models.py:1120
 msgid "Issue solved"
 msgstr ""
 
-#: aleksis/core/models.py:1140
+#: aleksis/core/models.py:1121
 #, fuzzy
 #| msgid "Notifications"
 msgid "Notification sent"
 msgstr "Nuntii"
 
-#: aleksis/core/models.py:1153
+#: aleksis/core/models.py:1134
 msgid "Data check result"
 msgstr ""
 
-#: aleksis/core/models.py:1154
+#: aleksis/core/models.py:1135
 msgid "Data check results"
 msgstr ""
 
-#: aleksis/core/models.py:1156
+#: aleksis/core/models.py:1137
 msgid "Can run data checks"
 msgstr ""
 
-#: aleksis/core/models.py:1157
+#: aleksis/core/models.py:1138
 msgid "Can solve data check problems"
 msgstr ""
 
-#: aleksis/core/models.py:1164
+#: aleksis/core/models.py:1145
 #, fuzzy
 #| msgid "E-mail address"
 msgid "E-Mail address"
 msgstr "Inscriptio electronica"
 
-#: aleksis/core/models.py:1188
+#: aleksis/core/models.py:1169
 msgid "Owner"
 msgstr ""
 
-#: aleksis/core/models.py:1192
+#: aleksis/core/models.py:1173
 msgid "File expires at"
 msgstr ""
 
-#: aleksis/core/models.py:1194
+#: aleksis/core/models.py:1175
 msgid "Generated HTML file"
 msgstr ""
 
-#: aleksis/core/models.py:1196
+#: aleksis/core/models.py:1177
 msgid "Generated PDF file"
 msgstr ""
 
-#: aleksis/core/models.py:1203
+#: aleksis/core/models.py:1184
 msgid "PDF file"
 msgstr ""
 
-#: aleksis/core/models.py:1204
+#: aleksis/core/models.py:1185
 msgid "PDF files"
 msgstr ""
 
-#: aleksis/core/models.py:1209
+#: aleksis/core/models.py:1190
 msgid "Task result"
 msgstr ""
 
-#: aleksis/core/models.py:1212
+#: aleksis/core/models.py:1193
 msgid "Task user"
 msgstr ""
 
-#: aleksis/core/models.py:1224
+#: aleksis/core/models.py:1205
 msgid "Task user assignment"
 msgstr ""
 
-#: aleksis/core/models.py:1225
+#: aleksis/core/models.py:1206
 msgid "Task user assignments"
 msgstr ""
 
-#: aleksis/core/models.py:1241
+#: aleksis/core/models.py:1222
 #, fuzzy
 #| msgid "Additional name(s)"
 msgid "Additional attributes"
 msgstr "addita nomines"
 
-#: aleksis/core/models.py:1279
+#: aleksis/core/models.py:1260
 msgid "Allowed scopes that clients can request"
 msgstr ""
 
-#: aleksis/core/models.py:1289
+#: aleksis/core/models.py:1270
 msgid "This image will be shown as icon in the authorization flow. It should be squared."
 msgstr ""
 
@@ -1111,7 +1115,7 @@ msgstr "Nuntii"
 msgid "Internationalisation"
 msgstr "Simulare aliquem"
 
-#: aleksis/core/preferences.py:44
+#: aleksis/core/preferences.py:43
 msgid "Site title"
 msgstr "Titulus paginae"
 
@@ -1119,11 +1123,11 @@ msgstr "Titulus paginae"
 msgid "Site description"
 msgstr "Descriptio paginae"
 
-#: aleksis/core/preferences.py:66
+#: aleksis/core/preferences.py:65
 msgid "Primary colour"
 msgstr ""
 
-#: aleksis/core/preferences.py:78
+#: aleksis/core/preferences.py:77
 msgid "Secondary colour"
 msgstr ""
 
@@ -1133,155 +1137,159 @@ msgstr ""
 msgid "Logo"
 msgstr "nomen retractare"
 
-#: aleksis/core/preferences.py:99
+#: aleksis/core/preferences.py:100
 msgid "Favicon"
 msgstr ""
 
-#: aleksis/core/preferences.py:109
+#: aleksis/core/preferences.py:111
 #, fuzzy
 #| msgid "Icon"
 msgid "PWA-Icon"
 msgstr "Nota"
 
-#: aleksis/core/preferences.py:120
+#: aleksis/core/preferences.py:121
+msgid "PWA-Icon is maskable"
+msgstr ""
+
+#: aleksis/core/preferences.py:133
 #, fuzzy
 #| msgid "Last name"
 msgid "Mail out name"
 msgstr "Secondus nomen"
 
-#: aleksis/core/preferences.py:131
+#: aleksis/core/preferences.py:144
 #, fuzzy
 #| msgid "E-mail address"
 msgid "Mail out address"
 msgstr "Inscriptio electronica"
 
-#: aleksis/core/preferences.py:143
+#: aleksis/core/preferences.py:157
 msgid "Link to privacy policy"
 msgstr ""
 
-#: aleksis/core/preferences.py:155
+#: aleksis/core/preferences.py:169
 msgid "Link to imprint"
 msgstr ""
 
-#: aleksis/core/preferences.py:167
+#: aleksis/core/preferences.py:180
 msgid "Name format for addressing"
 msgstr ""
 
-#: aleksis/core/preferences.py:183
+#: aleksis/core/preferences.py:197
 msgid "Channels to use for notifications"
 msgstr ""
 
-#: aleksis/core/preferences.py:195
+#: aleksis/core/preferences.py:209
 msgid "Regular expression to match primary group, e.g. '^Class .*'"
 msgstr ""
 
-#: aleksis/core/preferences.py:206
+#: aleksis/core/preferences.py:220
 msgid "Field on person to match primary group against"
 msgstr ""
 
-#: aleksis/core/preferences.py:218
+#: aleksis/core/preferences.py:232
 msgid "Automatically create new persons for new users"
 msgstr ""
 
-#: aleksis/core/preferences.py:227
+#: aleksis/core/preferences.py:241
 msgid "Automatically link existing persons to new users by their e-mail address"
 msgstr ""
 
-#: aleksis/core/preferences.py:238
+#: aleksis/core/preferences.py:252
 msgid "Display name of the school"
 msgstr ""
 
-#: aleksis/core/preferences.py:249
+#: aleksis/core/preferences.py:263
 msgid "Official name of the school, e.g. as given by supervisory authority"
 msgstr "Officialis nomen scolae, e. g."
 
-#: aleksis/core/preferences.py:257
+#: aleksis/core/preferences.py:271
 msgid "Allow users to change their passwords"
 msgstr ""
 
-#: aleksis/core/preferences.py:265
+#: aleksis/core/preferences.py:279
 msgid "Enable signup"
 msgstr ""
 
-#: aleksis/core/preferences.py:273
+#: aleksis/core/preferences.py:287
 msgid "Enable invitations"
 msgstr ""
 
-#: aleksis/core/preferences.py:281
+#: aleksis/core/preferences.py:295
 msgid "Length of invite code. (Default 3: abcde-acbde-abcde)"
 msgstr ""
 
-#: aleksis/core/preferences.py:289
+#: aleksis/core/preferences.py:303
 msgid "Size of packets. (Default 5: abcde)"
 msgstr ""
 
-#: aleksis/core/preferences.py:300
+#: aleksis/core/preferences.py:314
 #, fuzzy
 #| msgid "E-mail address"
 msgid "Allowed Grant Flows for OAuth applications"
 msgstr "Inscriptio electronica"
 
-#: aleksis/core/preferences.py:313
+#: aleksis/core/preferences.py:328
 msgid "Available languages"
 msgstr ""
 
-#: aleksis/core/preferences.py:325
+#: aleksis/core/preferences.py:341
 msgid "Send emails if data checks detect problems"
 msgstr ""
 
-#: aleksis/core/preferences.py:336
+#: aleksis/core/preferences.py:352
 msgid "Email recipients for data checks problem emails"
 msgstr ""
 
-#: aleksis/core/preferences.py:347
+#: aleksis/core/preferences.py:363
 msgid "Email recipient groups for data checks problem emails"
 msgstr ""
 
-#: aleksis/core/preferences.py:356
+#: aleksis/core/preferences.py:372
 msgid "Show dashboard to users without login"
 msgstr ""
 
-#: aleksis/core/preferences.py:365
+#: aleksis/core/preferences.py:381
 msgid "Allow users to edit their dashboard"
 msgstr ""
 
-#: aleksis/core/preferences.py:376
+#: aleksis/core/preferences.py:392
 msgid "Fields on person model which are editable by themselves."
 msgstr ""
 
-#: aleksis/core/preferences.py:390
+#: aleksis/core/preferences.py:407
 msgid "Editable fields on person model which should trigger a notification on change"
 msgstr ""
 
-#: aleksis/core/preferences.py:403
+#: aleksis/core/preferences.py:421
 msgid "Contact for notification if a person changes their data"
 msgstr ""
 
-#: aleksis/core/preferences.py:413
+#: aleksis/core/preferences.py:432
 msgid "PDF file expiration duration"
 msgstr ""
 
-#: aleksis/core/preferences.py:414
+#: aleksis/core/preferences.py:433
 msgid "in minutes"
 msgstr ""
 
-#: aleksis/core/preferences.py:424
+#: aleksis/core/preferences.py:443
 msgid "Automatically update the dashboard and its widgets"
 msgstr ""
 
-#: aleksis/core/preferences.py:434
+#: aleksis/core/preferences.py:453
 msgid "Automatically update the dashboard and its widgets sitewide"
 msgstr ""
 
-#: aleksis/core/preferences.py:444
+#: aleksis/core/preferences.py:463
 msgid "Country for phone number parsing"
 msgstr ""
 
-#: aleksis/core/settings.py:518
+#: aleksis/core/settings.py:526
 msgid "English"
 msgstr "Britannicus"
 
-#: aleksis/core/settings.py:519
+#: aleksis/core/settings.py:527
 msgid "German"
 msgstr "Germanus"
 
@@ -1648,7 +1656,7 @@ msgstr ""
 msgid "Privacy Policy"
 msgstr ""
 
-#: aleksis/core/templates/core/base_print.html:72
+#: aleksis/core/templates/core/base_print.html:74
 msgid "Powered by AlekSIS®"
 msgstr ""
 
@@ -2319,23 +2327,11 @@ msgstr "Simulare aliquem"
 msgid "Contact details"
 msgstr ""
 
-#: aleksis/core/templates/core/person/full.html:168
-#, fuzzy
-#| msgid "Street number"
-msgid "home number"
-msgstr "Numerus domini"
-
-#: aleksis/core/templates/core/person/full.html:174
-#, fuzzy
-#| msgid "Mobile phone"
-msgid "mobile number"
-msgstr "Numerus telephoni mobilis"
-
-#: aleksis/core/templates/core/person/full.html:216
+#: aleksis/core/templates/core/person/full.html:224
 msgid "This person didn't upload a personal photo."
 msgstr ""
 
-#: aleksis/core/templates/core/person/full.html:224
+#: aleksis/core/templates/core/person/full.html:232
 msgid "Children"
 msgstr ""
 
@@ -3164,23 +3160,23 @@ msgstr ""
 msgid "SMS"
 msgstr ""
 
-#: aleksis/core/util/pdf.py:113
+#: aleksis/core/util/pdf.py:118
 msgid "Progress: Generate PDF file"
 msgstr ""
 
-#: aleksis/core/util/pdf.py:114
+#: aleksis/core/util/pdf.py:119
 msgid "Generating PDF file …"
 msgstr ""
 
-#: aleksis/core/util/pdf.py:115
+#: aleksis/core/util/pdf.py:120
 msgid "The PDF file has been generated successfully."
 msgstr ""
 
-#: aleksis/core/util/pdf.py:116
+#: aleksis/core/util/pdf.py:121
 msgid "There was a problem while generating the PDF file."
 msgstr ""
 
-#: aleksis/core/util/pdf.py:119
+#: aleksis/core/util/pdf.py:124
 msgid "Download PDF"
 msgstr ""
 
@@ -3332,14 +3328,24 @@ msgstr ""
 msgid "The third-party account has been successfully disconnected."
 msgstr ""
 
-#: aleksis/core/views.py:1443
+#: aleksis/core/views.py:1445
 msgid "Person was invited successfully."
 msgstr ""
 
-#: aleksis/core/views.py:1445
+#: aleksis/core/views.py:1447
 msgid "Person was already invited."
 msgstr ""
 
+#, fuzzy
+#~| msgid "Street number"
+#~ msgid "home number"
+#~ msgstr "Numerus domini"
+
+#, fuzzy
+#~| msgid "Mobile phone"
+#~ msgid "mobile number"
+#~ msgstr "Numerus telephoni mobilis"
+
 #, fuzzy
 #~| msgid "Impersonation"
 #~ msgid "Is person active?"
diff --git a/aleksis/core/locale/la/LC_MESSAGES/djangojs.po b/aleksis/core/locale/la/LC_MESSAGES/djangojs.po
index db33a52583b3ad2cff7af57a8306fb4a5d4c6117..427b5fbc842fe8bbbc70d795633af5070b404ec7 100644
--- a/aleksis/core/locale/la/LC_MESSAGES/djangojs.po
+++ b/aleksis/core/locale/la/LC_MESSAGES/djangojs.po
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2022-01-10 17:26+0100\n"
+"POT-Creation-Date: 2022-01-31 17:03+0100\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"
@@ -17,18 +17,18 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: aleksis/core/static/js/main.js:15
+#: aleksis/core/static/js/main.js:66
 msgid "Today"
 msgstr ""
 
-#: aleksis/core/static/js/main.js:16
+#: aleksis/core/static/js/main.js:67
 msgid "Cancel"
 msgstr ""
 
-#: aleksis/core/static/js/main.js:17
+#: aleksis/core/static/js/main.js:68
 msgid "OK"
 msgstr ""
 
-#: aleksis/core/static/js/main.js:131
+#: aleksis/core/static/js/main.js:191
 msgid "This page may contain outdated information since there is no internet connection."
 msgstr ""
diff --git a/aleksis/core/locale/nb_NO/LC_MESSAGES/django.po b/aleksis/core/locale/nb_NO/LC_MESSAGES/django.po
index 4580225838ec69c174f44b1fc68987b36034e3c5..249af254d7bb7b5d21874acf1a8e96798066594e 100644
--- a/aleksis/core/locale/nb_NO/LC_MESSAGES/django.po
+++ b/aleksis/core/locale/nb_NO/LC_MESSAGES/django.po
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: AlekSIS (School Information System) 0.1\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2022-01-10 17:26+0100\n"
+"POT-Creation-Date: 2022-01-31 17:03+0100\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"
@@ -17,51 +17,51 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: aleksis/core/apps.py:154
+#: aleksis/core/apps.py:166
 msgid "OpenID Connect scope"
 msgstr ""
 
-#: aleksis/core/apps.py:155
+#: aleksis/core/apps.py:167
 msgid "Given name, family name, link to profile and picture if existing."
 msgstr ""
 
-#: aleksis/core/apps.py:156
+#: aleksis/core/apps.py:168
 msgid "Full home postal address"
 msgstr ""
 
-#: aleksis/core/apps.py:157
+#: aleksis/core/apps.py:169
 msgid "Email address"
 msgstr ""
 
-#: aleksis/core/apps.py:158
+#: aleksis/core/apps.py:170
 msgid "Home and mobile phone"
 msgstr ""
 
-#: aleksis/core/apps.py:159 aleksis/core/forms.py:223 aleksis/core/menus.py:265
-#: aleksis/core/models.py:449 aleksis/core/templates/core/group/list.html:8
+#: aleksis/core/apps.py:171 aleksis/core/forms.py:218 aleksis/core/menus.py:265
+#: aleksis/core/models.py:462 aleksis/core/templates/core/group/list.html:8
 #: aleksis/core/templates/core/group/list.html:9
-#: aleksis/core/templates/core/person/full.html:242
+#: aleksis/core/templates/core/person/full.html:250
 msgid "Groups"
 msgstr ""
 
-#: aleksis/core/data_checks.py:55
+#: aleksis/core/data_checks.py:56
 msgid "Ignore problem"
 msgstr ""
 
-#: aleksis/core/data_checks.py:184
+#: aleksis/core/data_checks.py:185
 #, python-brace-format
 msgid "Solve option '{solve_option_obj.verbose_name}' "
 msgstr ""
 
-#: aleksis/core/data_checks.py:290
+#: aleksis/core/data_checks.py:291
 msgid "Deactivate DashboardWidget"
 msgstr ""
 
-#: aleksis/core/data_checks.py:302
+#: aleksis/core/data_checks.py:303
 msgid "Ensure that there are no broken DashboardWidgets."
 msgstr ""
 
-#: aleksis/core/data_checks.py:303
+#: aleksis/core/data_checks.py:304
 msgid "The DashboardWidget was reported broken automatically."
 msgstr ""
 
@@ -90,15 +90,15 @@ msgstr ""
 msgid "Content type"
 msgstr ""
 
-#: aleksis/core/filters.py:113 aleksis/core/models.py:675
+#: aleksis/core/filters.py:113 aleksis/core/models.py:688
 msgid "User"
 msgstr ""
 
-#: aleksis/core/filters.py:135 aleksis/core/models.py:448
+#: aleksis/core/filters.py:135 aleksis/core/models.py:461
 msgid "Group"
 msgstr ""
 
-#: aleksis/core/forms.py:48 aleksis/core/forms.py:559
+#: aleksis/core/forms.py:48 aleksis/core/forms.py:554
 msgid "Base data"
 msgstr ""
 
@@ -106,7 +106,7 @@ msgstr ""
 msgid "Address"
 msgstr ""
 
-#: aleksis/core/forms.py:54 aleksis/core/forms.py:568
+#: aleksis/core/forms.py:54 aleksis/core/forms.py:563
 msgid "Contact data"
 msgstr ""
 
@@ -122,121 +122,121 @@ msgstr ""
 msgid "Create a new account"
 msgstr ""
 
-#: aleksis/core/forms.py:135
+#: aleksis/core/forms.py:130
 msgid "You cannot set a new username when also selecting an existing user."
 msgstr ""
 
-#: aleksis/core/forms.py:139
+#: aleksis/core/forms.py:134
 msgid "This username is already in use."
 msgstr ""
 
-#: aleksis/core/forms.py:156 aleksis/core/models.py:130
+#: aleksis/core/forms.py:151 aleksis/core/models.py:130
 msgid "School term"
 msgstr ""
 
-#: aleksis/core/forms.py:157
+#: aleksis/core/forms.py:152
 msgid "Common data"
 msgstr ""
 
-#: aleksis/core/forms.py:158 aleksis/core/forms.py:210
+#: aleksis/core/forms.py:153 aleksis/core/forms.py:205
 #: aleksis/core/menus.py:254 aleksis/core/models.py:153
 #: aleksis/core/templates/core/person/list.html:8
 #: aleksis/core/templates/core/person/list.html:9
 msgid "Persons"
 msgstr ""
 
-#: aleksis/core/forms.py:159 aleksis/core/forms.py:570
+#: aleksis/core/forms.py:154 aleksis/core/forms.py:565
 msgid "Additional data"
 msgstr ""
 
-#: aleksis/core/forms.py:160 aleksis/core/models.py:206
-#: aleksis/core/models.py:501
+#: aleksis/core/forms.py:155 aleksis/core/models.py:206
+#: aleksis/core/models.py:514
 msgid "Photo"
 msgstr ""
 
-#: aleksis/core/forms.py:202 aleksis/core/forms.py:205
+#: aleksis/core/forms.py:197 aleksis/core/forms.py:200
 #: aleksis/core/models.py:73
 msgid "Date"
 msgstr ""
 
-#: aleksis/core/forms.py:203 aleksis/core/forms.py:206
+#: aleksis/core/forms.py:198 aleksis/core/forms.py:201
 #: aleksis/core/models.py:81
 msgid "Time"
 msgstr ""
 
-#: aleksis/core/forms.py:236
+#: aleksis/core/forms.py:231
 msgid "From when until when should the announcement be displayed?"
 msgstr ""
 
-#: aleksis/core/forms.py:239
+#: aleksis/core/forms.py:234
 msgid "Who should see the announcement?"
 msgstr ""
 
-#: aleksis/core/forms.py:240
+#: aleksis/core/forms.py:235
 msgid "Write your announcement:"
 msgstr ""
 
-#: aleksis/core/forms.py:279
+#: aleksis/core/forms.py:274
 msgid "You are not allowed to create announcements which are only valid in the past."
 msgstr ""
 
-#: aleksis/core/forms.py:283
+#: aleksis/core/forms.py:278
 msgid "The from date and time must be earlier then the until date and time."
 msgstr ""
 
-#: aleksis/core/forms.py:292
+#: aleksis/core/forms.py:287
 msgid "You need at least one recipient."
 msgstr ""
 
-#: aleksis/core/forms.py:401
+#: aleksis/core/forms.py:396
 msgid "Invitation code"
 msgstr ""
 
-#: aleksis/core/forms.py:402
+#: aleksis/core/forms.py:397
 msgid "Please enter your invitation code."
 msgstr ""
 
-#: aleksis/core/forms.py:434
+#: aleksis/core/forms.py:429
 msgid "Who should get the permission?"
 msgstr ""
 
-#: aleksis/core/forms.py:435
+#: aleksis/core/forms.py:430
 msgid "On what?"
 msgstr ""
 
-#: aleksis/core/forms.py:461
+#: aleksis/core/forms.py:456
 msgid "Select objects which the permission should be granted for:"
 msgstr ""
 
-#: aleksis/core/forms.py:464
+#: aleksis/core/forms.py:459
 msgid "Grant the permission for all objects"
 msgstr ""
 
-#: aleksis/core/forms.py:472
+#: aleksis/core/forms.py:467
 msgid "You must select at least one group or person which should get the permission."
 msgstr ""
 
-#: aleksis/core/forms.py:477
+#: aleksis/core/forms.py:472
 msgid "You must grant the permission to all objects and/or to some objects."
 msgstr ""
 
-#: aleksis/core/forms.py:564
+#: aleksis/core/forms.py:559
 msgid "Adress data"
 msgstr ""
 
-#: aleksis/core/forms.py:576
+#: aleksis/core/forms.py:571
 msgid "Account data"
 msgstr ""
 
-#: aleksis/core/forms.py:583
+#: aleksis/core/forms.py:578
 msgid "Password"
 msgstr ""
 
-#: aleksis/core/forms.py:586
+#: aleksis/core/forms.py:581
 msgid "Password (again)"
 msgstr ""
 
-#: aleksis/core/forms.py:752
+#: aleksis/core/forms.py:747
 msgid "No valid selection."
 msgstr ""
 
@@ -244,22 +244,20 @@ msgstr ""
 msgid "There are unresolved data problems."
 msgstr ""
 
-#: aleksis/core/health_checks.py:44
-#, python-brace-format
-msgid "Last backup {time_gone_since_backup}!"
+#: aleksis/core/health_checks.py:40
+msgid "Error accessing backup storage: {}"
 msgstr ""
 
-#: aleksis/core/health_checks.py:46
-msgid "No backup found!"
+#: aleksis/core/health_checks.py:50
+msgid "Last backup {}!"
 msgstr ""
 
-#: aleksis/core/health_checks.py:73
-msgid "No backup result found!"
+#: aleksis/core/health_checks.py:52
+msgid "No backup found!"
 msgstr ""
 
-#: aleksis/core/health_checks.py:75
-#, python-brace-format
-msgid "{task.status} - {task.result}"
+#: aleksis/core/health_checks.py:79
+msgid "No backup result found!"
 msgstr ""
 
 #: aleksis/core/menus.py:9 aleksis/core/templates/two_factor/core/login.html:6
@@ -281,7 +279,7 @@ msgstr ""
 msgid "Dashboard"
 msgstr ""
 
-#: aleksis/core/menus.py:41 aleksis/core/models.py:721
+#: aleksis/core/menus.py:41 aleksis/core/models.py:734
 #: aleksis/core/preferences.py:29
 #: aleksis/core/templates/core/notifications.html:4
 #: aleksis/core/templates/core/notifications.html:5
@@ -339,7 +337,7 @@ msgstr ""
 msgid "Admin"
 msgstr ""
 
-#: aleksis/core/menus.py:141 aleksis/core/models.py:821
+#: aleksis/core/menus.py:141 aleksis/core/models.py:834
 #: aleksis/core/templates/core/announcement/list.html:7
 #: aleksis/core/templates/core/announcement/list.html:8
 msgid "Announcements"
@@ -397,7 +395,7 @@ msgstr ""
 msgid "People"
 msgstr ""
 
-#: aleksis/core/menus.py:276 aleksis/core/models.py:1075
+#: aleksis/core/menus.py:276 aleksis/core/models.py:1055
 #: aleksis/core/templates/core/group_type/list.html:8
 #: aleksis/core/templates/core/group_type/list.html:9
 msgid "Group types"
@@ -407,7 +405,7 @@ msgstr ""
 msgid "Groups and child groups"
 msgstr ""
 
-#: aleksis/core/menus.py:298 aleksis/core/models.py:497
+#: aleksis/core/menus.py:298 aleksis/core/models.py:510
 #: aleksis/core/templates/core/additional_field/list.html:8
 #: aleksis/core/templates/core/additional_field/list.html:9
 msgid "Additional fields"
@@ -467,7 +465,7 @@ msgstr ""
 msgid "URL / Link"
 msgstr ""
 
-#: aleksis/core/models.py:94 aleksis/core/models.py:1044
+#: aleksis/core/models.py:94 aleksis/core/models.py:1024
 msgid "Name"
 msgstr ""
 
@@ -487,7 +485,7 @@ msgstr ""
 msgid "There is already a school term for this time or a part of this time."
 msgstr ""
 
-#: aleksis/core/models.py:152 aleksis/core/models.py:993
+#: aleksis/core/models.py:152 aleksis/core/models.py:973
 msgid "Person"
 msgstr ""
 
@@ -523,7 +521,7 @@ msgstr ""
 msgid "male"
 msgstr ""
 
-#: aleksis/core/models.py:178 aleksis/core/models.py:1238
+#: aleksis/core/models.py:178 aleksis/core/models.py:1219
 msgid "Linked user"
 msgstr ""
 
@@ -539,7 +537,7 @@ msgstr ""
 msgid "Additional name(s)"
 msgstr ""
 
-#: aleksis/core/models.py:188 aleksis/core/models.py:466
+#: aleksis/core/models.py:188 aleksis/core/models.py:479
 msgid "Short name"
 msgstr ""
 
@@ -559,11 +557,11 @@ msgstr ""
 msgid "Place"
 msgstr ""
 
-#: aleksis/core/models.py:196
+#: aleksis/core/models.py:196 aleksis/core/templates/core/person/full.html:172
 msgid "Home phone"
 msgstr ""
 
-#: aleksis/core/models.py:197
+#: aleksis/core/models.py:197 aleksis/core/templates/core/person/full.html:182
 msgid "Mobile phone"
 msgstr ""
 
@@ -579,19 +577,19 @@ msgstr ""
 msgid "Sex"
 msgstr ""
 
-#: aleksis/core/models.py:210 aleksis/core/models.py:505
+#: aleksis/core/models.py:210 aleksis/core/models.py:518
 msgid "This is an official photo, used for official documents and for internal use cases."
 msgstr ""
 
-#: aleksis/core/models.py:215 aleksis/core/models.py:509
+#: aleksis/core/models.py:215 aleksis/core/models.py:522
 msgid "Display picture / Avatar"
 msgstr ""
 
-#: aleksis/core/models.py:218 aleksis/core/models.py:512
+#: aleksis/core/models.py:218 aleksis/core/models.py:525
 msgid "This is a picture or an avatar for public display."
 msgstr ""
 
-#: aleksis/core/models.py:223 aleksis/core/templates/core/person/full.html:231
+#: aleksis/core/models.py:223 aleksis/core/templates/core/person/full.html:239
 msgid "Guardians / Parents"
 msgstr ""
 
@@ -599,364 +597,368 @@ msgstr ""
 msgid "Primary group"
 msgstr ""
 
-#: aleksis/core/models.py:233 aleksis/core/models.py:679
-#: aleksis/core/models.py:703 aleksis/core/models.py:788
-#: aleksis/core/models.py:1068
+#: aleksis/core/models.py:233 aleksis/core/models.py:692
+#: aleksis/core/models.py:716 aleksis/core/models.py:801
+#: aleksis/core/models.py:1048
 msgid "Description"
 msgstr ""
 
-#: aleksis/core/models.py:421
+#: aleksis/core/models.py:434
 msgid "Title of field"
 msgstr ""
 
-#: aleksis/core/models.py:423
+#: aleksis/core/models.py:436
 msgid "Type of field"
 msgstr ""
 
-#: aleksis/core/models.py:430
+#: aleksis/core/models.py:443
 msgid "Addtitional field for groups"
 msgstr ""
 
-#: aleksis/core/models.py:431
+#: aleksis/core/models.py:444
 msgid "Addtitional fields for groups"
 msgstr ""
 
-#: aleksis/core/models.py:451
+#: aleksis/core/models.py:464
 msgid "Can assign child groups to groups"
 msgstr ""
 
-#: aleksis/core/models.py:452
+#: aleksis/core/models.py:465
 msgid "Can view statistics about group."
 msgstr ""
 
-#: aleksis/core/models.py:464
+#: aleksis/core/models.py:477
 msgid "Long name"
 msgstr ""
 
-#: aleksis/core/models.py:474 aleksis/core/templates/core/group/full.html:85
+#: aleksis/core/models.py:487 aleksis/core/templates/core/group/full.html:85
 msgid "Members"
 msgstr ""
 
-#: aleksis/core/models.py:477 aleksis/core/templates/core/group/full.html:82
+#: aleksis/core/models.py:490 aleksis/core/templates/core/group/full.html:82
 msgid "Owners"
 msgstr ""
 
-#: aleksis/core/models.py:484 aleksis/core/templates/core/group/full.html:55
+#: aleksis/core/models.py:497 aleksis/core/templates/core/group/full.html:55
 msgid "Parent groups"
 msgstr ""
 
-#: aleksis/core/models.py:492
+#: aleksis/core/models.py:505
 msgid "Type of group"
 msgstr ""
 
-#: aleksis/core/models.py:678 aleksis/core/models.py:702
-#: aleksis/core/models.py:787
+#: aleksis/core/models.py:691 aleksis/core/models.py:715
+#: aleksis/core/models.py:800
 #: aleksis/core/templates/core/announcement/list.html:18
 msgid "Title"
 msgstr ""
 
-#: aleksis/core/models.py:681
+#: aleksis/core/models.py:694
 msgid "Application"
 msgstr ""
 
-#: aleksis/core/models.py:687
+#: aleksis/core/models.py:700
 msgid "Activity"
 msgstr ""
 
-#: aleksis/core/models.py:688
+#: aleksis/core/models.py:701
 msgid "Activities"
 msgstr ""
 
-#: aleksis/core/models.py:694
+#: aleksis/core/models.py:707
 msgid "Sender"
 msgstr ""
 
-#: aleksis/core/models.py:699
+#: aleksis/core/models.py:712
 msgid "Recipient"
 msgstr ""
 
-#: aleksis/core/models.py:704 aleksis/core/models.py:1045
+#: aleksis/core/models.py:717 aleksis/core/models.py:1025
 msgid "Link"
 msgstr ""
 
-#: aleksis/core/models.py:706
+#: aleksis/core/models.py:719
 msgid "Read"
 msgstr ""
 
-#: aleksis/core/models.py:707
+#: aleksis/core/models.py:720
 msgid "Sent"
 msgstr ""
 
-#: aleksis/core/models.py:720
+#: aleksis/core/models.py:733
 msgid "Notification"
 msgstr ""
 
-#: aleksis/core/models.py:789
+#: aleksis/core/models.py:802
 msgid "Link to detailed view"
 msgstr ""
 
-#: aleksis/core/models.py:792
+#: aleksis/core/models.py:805
 msgid "Date and time from when to show"
 msgstr ""
 
-#: aleksis/core/models.py:795
+#: aleksis/core/models.py:808
 msgid "Date and time until when to show"
 msgstr ""
 
-#: aleksis/core/models.py:820
+#: aleksis/core/models.py:833
 msgid "Announcement"
 msgstr ""
 
-#: aleksis/core/models.py:858
+#: aleksis/core/models.py:871
 msgid "Announcement recipient"
 msgstr ""
 
-#: aleksis/core/models.py:859
+#: aleksis/core/models.py:872
 msgid "Announcement recipients"
 msgstr ""
 
-#: aleksis/core/models.py:914
+#: aleksis/core/models.py:894
 msgid "Widget Title"
 msgstr ""
 
-#: aleksis/core/models.py:915
+#: aleksis/core/models.py:895
 msgid "Activate Widget"
 msgstr ""
 
-#: aleksis/core/models.py:916
+#: aleksis/core/models.py:896
 msgid "Widget is broken"
 msgstr ""
 
-#: aleksis/core/models.py:919
+#: aleksis/core/models.py:899
 msgid "Size on mobile devices"
 msgstr ""
 
-#: aleksis/core/models.py:920
+#: aleksis/core/models.py:900
 msgid "<= 600 px, 12 columns"
 msgstr ""
 
-#: aleksis/core/models.py:925
+#: aleksis/core/models.py:905
 msgid "Size on tablet devices"
 msgstr ""
 
-#: aleksis/core/models.py:926
+#: aleksis/core/models.py:906
 msgid "> 600 px, 12 columns"
 msgstr ""
 
-#: aleksis/core/models.py:931
+#: aleksis/core/models.py:911
 msgid "Size on desktop devices"
 msgstr ""
 
-#: aleksis/core/models.py:932
+#: aleksis/core/models.py:912
 msgid "> 992 px, 12 columns"
 msgstr ""
 
-#: aleksis/core/models.py:937
+#: aleksis/core/models.py:917
 msgid "Size on large desktop devices"
 msgstr ""
 
-#: aleksis/core/models.py:938
+#: aleksis/core/models.py:918
 msgid "> 1200 px>, 12 columns"
 msgstr ""
 
-#: aleksis/core/models.py:969
+#: aleksis/core/models.py:949
 msgid "Can edit default dashboard"
 msgstr ""
 
-#: aleksis/core/models.py:970
+#: aleksis/core/models.py:950
 msgid "Dashboard Widget"
 msgstr ""
 
-#: aleksis/core/models.py:971
+#: aleksis/core/models.py:951
 msgid "Dashboard Widgets"
 msgstr ""
 
-#: aleksis/core/models.py:977
+#: aleksis/core/models.py:957
 msgid "URL"
 msgstr ""
 
-#: aleksis/core/models.py:978
+#: aleksis/core/models.py:958
 msgid "Icon URL"
 msgstr ""
 
-#: aleksis/core/models.py:984
+#: aleksis/core/models.py:964
 msgid "External link widget"
 msgstr ""
 
-#: aleksis/core/models.py:985
+#: aleksis/core/models.py:965
 msgid "External link widgets"
 msgstr ""
 
-#: aleksis/core/models.py:990
+#: aleksis/core/models.py:970
 msgid "Dashboard widget"
 msgstr ""
 
-#: aleksis/core/models.py:995
+#: aleksis/core/models.py:975
 msgid "Order"
 msgstr ""
 
-#: aleksis/core/models.py:996
+#: aleksis/core/models.py:976
 msgid "Part of the default dashboard"
 msgstr ""
 
-#: aleksis/core/models.py:1011
+#: aleksis/core/models.py:991
 msgid "Dashboard widget order"
 msgstr ""
 
-#: aleksis/core/models.py:1012
+#: aleksis/core/models.py:992
 msgid "Dashboard widget orders"
 msgstr ""
 
-#: aleksis/core/models.py:1018
+#: aleksis/core/models.py:998
 msgid "Menu ID"
 msgstr ""
 
-#: aleksis/core/models.py:1031
+#: aleksis/core/models.py:1011
 msgid "Custom menu"
 msgstr ""
 
-#: aleksis/core/models.py:1032
+#: aleksis/core/models.py:1012
 msgid "Custom menus"
 msgstr ""
 
-#: aleksis/core/models.py:1042
+#: aleksis/core/models.py:1022
 msgid "Menu"
 msgstr ""
 
-#: aleksis/core/models.py:1046 aleksis/core/models.py:1285
+#: aleksis/core/models.py:1026 aleksis/core/models.py:1266
 #: aleksis/core/templates/oauth2_provider/application/detail.html:26
 msgid "Icon"
 msgstr ""
 
-#: aleksis/core/models.py:1052
+#: aleksis/core/models.py:1032
 msgid "Custom menu item"
 msgstr ""
 
-#: aleksis/core/models.py:1053
+#: aleksis/core/models.py:1033
 msgid "Custom menu items"
 msgstr ""
 
-#: aleksis/core/models.py:1067
+#: aleksis/core/models.py:1047
 msgid "Title of type"
 msgstr ""
 
-#: aleksis/core/models.py:1074 aleksis/core/templates/core/group/full.html:47
+#: aleksis/core/models.py:1054 aleksis/core/templates/core/group/full.html:47
 msgid "Group type"
 msgstr ""
 
-#: aleksis/core/models.py:1088
+#: aleksis/core/models.py:1068
 msgid "Can view system status"
 msgstr ""
 
-#: aleksis/core/models.py:1089
+#: aleksis/core/models.py:1069
 msgid "Can manage data"
 msgstr ""
 
-#: aleksis/core/models.py:1090
+#: aleksis/core/models.py:1070
 msgid "Can impersonate"
 msgstr ""
 
-#: aleksis/core/models.py:1091
+#: aleksis/core/models.py:1071
 msgid "Can use search"
 msgstr ""
 
-#: aleksis/core/models.py:1092
+#: aleksis/core/models.py:1072
 msgid "Can change site preferences"
 msgstr ""
 
-#: aleksis/core/models.py:1093
+#: aleksis/core/models.py:1073
 msgid "Can change person preferences"
 msgstr ""
 
-#: aleksis/core/models.py:1094
+#: aleksis/core/models.py:1074
 msgid "Can change group preferences"
 msgstr ""
 
-#: aleksis/core/models.py:1095
+#: aleksis/core/models.py:1075
 msgid "Can test PDF generation"
 msgstr ""
 
-#: aleksis/core/models.py:1131
+#: aleksis/core/models.py:1076
+msgid "Can invite persons"
+msgstr ""
+
+#: aleksis/core/models.py:1112
 msgid "Related data check task"
 msgstr ""
 
-#: aleksis/core/models.py:1139
+#: aleksis/core/models.py:1120
 msgid "Issue solved"
 msgstr ""
 
-#: aleksis/core/models.py:1140
+#: aleksis/core/models.py:1121
 msgid "Notification sent"
 msgstr ""
 
-#: aleksis/core/models.py:1153
+#: aleksis/core/models.py:1134
 msgid "Data check result"
 msgstr ""
 
-#: aleksis/core/models.py:1154
+#: aleksis/core/models.py:1135
 msgid "Data check results"
 msgstr ""
 
-#: aleksis/core/models.py:1156
+#: aleksis/core/models.py:1137
 msgid "Can run data checks"
 msgstr ""
 
-#: aleksis/core/models.py:1157
+#: aleksis/core/models.py:1138
 msgid "Can solve data check problems"
 msgstr ""
 
-#: aleksis/core/models.py:1164
+#: aleksis/core/models.py:1145
 msgid "E-Mail address"
 msgstr ""
 
-#: aleksis/core/models.py:1188
+#: aleksis/core/models.py:1169
 msgid "Owner"
 msgstr ""
 
-#: aleksis/core/models.py:1192
+#: aleksis/core/models.py:1173
 msgid "File expires at"
 msgstr ""
 
-#: aleksis/core/models.py:1194
+#: aleksis/core/models.py:1175
 msgid "Generated HTML file"
 msgstr ""
 
-#: aleksis/core/models.py:1196
+#: aleksis/core/models.py:1177
 msgid "Generated PDF file"
 msgstr ""
 
-#: aleksis/core/models.py:1203
+#: aleksis/core/models.py:1184
 msgid "PDF file"
 msgstr ""
 
-#: aleksis/core/models.py:1204
+#: aleksis/core/models.py:1185
 msgid "PDF files"
 msgstr ""
 
-#: aleksis/core/models.py:1209
+#: aleksis/core/models.py:1190
 msgid "Task result"
 msgstr ""
 
-#: aleksis/core/models.py:1212
+#: aleksis/core/models.py:1193
 msgid "Task user"
 msgstr ""
 
-#: aleksis/core/models.py:1224
+#: aleksis/core/models.py:1205
 msgid "Task user assignment"
 msgstr ""
 
-#: aleksis/core/models.py:1225
+#: aleksis/core/models.py:1206
 msgid "Task user assignments"
 msgstr ""
 
-#: aleksis/core/models.py:1241
+#: aleksis/core/models.py:1222
 msgid "Additional attributes"
 msgstr ""
 
-#: aleksis/core/models.py:1279
+#: aleksis/core/models.py:1260
 msgid "Allowed scopes that clients can request"
 msgstr ""
 
-#: aleksis/core/models.py:1289
+#: aleksis/core/models.py:1270
 msgid "This image will be shown as icon in the authorization flow. It should be squared."
 msgstr ""
 
@@ -992,7 +994,7 @@ msgstr ""
 msgid "Internationalisation"
 msgstr ""
 
-#: aleksis/core/preferences.py:44
+#: aleksis/core/preferences.py:43
 msgid "Site title"
 msgstr ""
 
@@ -1000,11 +1002,11 @@ msgstr ""
 msgid "Site description"
 msgstr ""
 
-#: aleksis/core/preferences.py:66
+#: aleksis/core/preferences.py:65
 msgid "Primary colour"
 msgstr ""
 
-#: aleksis/core/preferences.py:78
+#: aleksis/core/preferences.py:77
 msgid "Secondary colour"
 msgstr ""
 
@@ -1012,147 +1014,151 @@ msgstr ""
 msgid "Logo"
 msgstr ""
 
-#: aleksis/core/preferences.py:99
+#: aleksis/core/preferences.py:100
 msgid "Favicon"
 msgstr ""
 
-#: aleksis/core/preferences.py:109
+#: aleksis/core/preferences.py:111
 msgid "PWA-Icon"
 msgstr ""
 
-#: aleksis/core/preferences.py:120
+#: aleksis/core/preferences.py:121
+msgid "PWA-Icon is maskable"
+msgstr ""
+
+#: aleksis/core/preferences.py:133
 msgid "Mail out name"
 msgstr ""
 
-#: aleksis/core/preferences.py:131
+#: aleksis/core/preferences.py:144
 msgid "Mail out address"
 msgstr ""
 
-#: aleksis/core/preferences.py:143
+#: aleksis/core/preferences.py:157
 msgid "Link to privacy policy"
 msgstr ""
 
-#: aleksis/core/preferences.py:155
+#: aleksis/core/preferences.py:169
 msgid "Link to imprint"
 msgstr ""
 
-#: aleksis/core/preferences.py:167
+#: aleksis/core/preferences.py:180
 msgid "Name format for addressing"
 msgstr ""
 
-#: aleksis/core/preferences.py:183
+#: aleksis/core/preferences.py:197
 msgid "Channels to use for notifications"
 msgstr ""
 
-#: aleksis/core/preferences.py:195
+#: aleksis/core/preferences.py:209
 msgid "Regular expression to match primary group, e.g. '^Class .*'"
 msgstr ""
 
-#: aleksis/core/preferences.py:206
+#: aleksis/core/preferences.py:220
 msgid "Field on person to match primary group against"
 msgstr ""
 
-#: aleksis/core/preferences.py:218
+#: aleksis/core/preferences.py:232
 msgid "Automatically create new persons for new users"
 msgstr ""
 
-#: aleksis/core/preferences.py:227
+#: aleksis/core/preferences.py:241
 msgid "Automatically link existing persons to new users by their e-mail address"
 msgstr ""
 
-#: aleksis/core/preferences.py:238
+#: aleksis/core/preferences.py:252
 msgid "Display name of the school"
 msgstr ""
 
-#: aleksis/core/preferences.py:249
+#: aleksis/core/preferences.py:263
 msgid "Official name of the school, e.g. as given by supervisory authority"
 msgstr ""
 
-#: aleksis/core/preferences.py:257
+#: aleksis/core/preferences.py:271
 msgid "Allow users to change their passwords"
 msgstr ""
 
-#: aleksis/core/preferences.py:265
+#: aleksis/core/preferences.py:279
 msgid "Enable signup"
 msgstr ""
 
-#: aleksis/core/preferences.py:273
+#: aleksis/core/preferences.py:287
 msgid "Enable invitations"
 msgstr ""
 
-#: aleksis/core/preferences.py:281
+#: aleksis/core/preferences.py:295
 msgid "Length of invite code. (Default 3: abcde-acbde-abcde)"
 msgstr ""
 
-#: aleksis/core/preferences.py:289
+#: aleksis/core/preferences.py:303
 msgid "Size of packets. (Default 5: abcde)"
 msgstr ""
 
-#: aleksis/core/preferences.py:300
+#: aleksis/core/preferences.py:314
 msgid "Allowed Grant Flows for OAuth applications"
 msgstr ""
 
-#: aleksis/core/preferences.py:313
+#: aleksis/core/preferences.py:328
 msgid "Available languages"
 msgstr ""
 
-#: aleksis/core/preferences.py:325
+#: aleksis/core/preferences.py:341
 msgid "Send emails if data checks detect problems"
 msgstr ""
 
-#: aleksis/core/preferences.py:336
+#: aleksis/core/preferences.py:352
 msgid "Email recipients for data checks problem emails"
 msgstr ""
 
-#: aleksis/core/preferences.py:347
+#: aleksis/core/preferences.py:363
 msgid "Email recipient groups for data checks problem emails"
 msgstr ""
 
-#: aleksis/core/preferences.py:356
+#: aleksis/core/preferences.py:372
 msgid "Show dashboard to users without login"
 msgstr ""
 
-#: aleksis/core/preferences.py:365
+#: aleksis/core/preferences.py:381
 msgid "Allow users to edit their dashboard"
 msgstr ""
 
-#: aleksis/core/preferences.py:376
+#: aleksis/core/preferences.py:392
 msgid "Fields on person model which are editable by themselves."
 msgstr ""
 
-#: aleksis/core/preferences.py:390
+#: aleksis/core/preferences.py:407
 msgid "Editable fields on person model which should trigger a notification on change"
 msgstr ""
 
-#: aleksis/core/preferences.py:403
+#: aleksis/core/preferences.py:421
 msgid "Contact for notification if a person changes their data"
 msgstr ""
 
-#: aleksis/core/preferences.py:413
+#: aleksis/core/preferences.py:432
 msgid "PDF file expiration duration"
 msgstr ""
 
-#: aleksis/core/preferences.py:414
+#: aleksis/core/preferences.py:433
 msgid "in minutes"
 msgstr ""
 
-#: aleksis/core/preferences.py:424
+#: aleksis/core/preferences.py:443
 msgid "Automatically update the dashboard and its widgets"
 msgstr ""
 
-#: aleksis/core/preferences.py:434
+#: aleksis/core/preferences.py:453
 msgid "Automatically update the dashboard and its widgets sitewide"
 msgstr ""
 
-#: aleksis/core/preferences.py:444
+#: aleksis/core/preferences.py:463
 msgid "Country for phone number parsing"
 msgstr ""
 
-#: aleksis/core/settings.py:518
+#: aleksis/core/settings.py:526
 msgid "English"
 msgstr ""
 
-#: aleksis/core/settings.py:519
+#: aleksis/core/settings.py:527
 msgid "German"
 msgstr ""
 
@@ -1499,7 +1505,7 @@ msgstr ""
 msgid "Privacy Policy"
 msgstr ""
 
-#: aleksis/core/templates/core/base_print.html:72
+#: aleksis/core/templates/core/base_print.html:74
 msgid "Powered by AlekSIS®"
 msgstr ""
 
@@ -2126,19 +2132,11 @@ msgstr ""
 msgid "Contact details"
 msgstr ""
 
-#: aleksis/core/templates/core/person/full.html:168
-msgid "home number"
-msgstr ""
-
-#: aleksis/core/templates/core/person/full.html:174
-msgid "mobile number"
-msgstr ""
-
-#: aleksis/core/templates/core/person/full.html:216
+#: aleksis/core/templates/core/person/full.html:224
 msgid "This person didn't upload a personal photo."
 msgstr ""
 
-#: aleksis/core/templates/core/person/full.html:224
+#: aleksis/core/templates/core/person/full.html:232
 msgid "Children"
 msgstr ""
 
@@ -2934,23 +2932,23 @@ msgstr ""
 msgid "SMS"
 msgstr ""
 
-#: aleksis/core/util/pdf.py:113
+#: aleksis/core/util/pdf.py:118
 msgid "Progress: Generate PDF file"
 msgstr ""
 
-#: aleksis/core/util/pdf.py:114
+#: aleksis/core/util/pdf.py:119
 msgid "Generating PDF file …"
 msgstr ""
 
-#: aleksis/core/util/pdf.py:115
+#: aleksis/core/util/pdf.py:120
 msgid "The PDF file has been generated successfully."
 msgstr ""
 
-#: aleksis/core/util/pdf.py:116
+#: aleksis/core/util/pdf.py:121
 msgid "There was a problem while generating the PDF file."
 msgstr ""
 
-#: aleksis/core/util/pdf.py:119
+#: aleksis/core/util/pdf.py:124
 msgid "Download PDF"
 msgstr ""
 
@@ -3100,11 +3098,11 @@ msgstr ""
 msgid "The third-party account has been successfully disconnected."
 msgstr ""
 
-#: aleksis/core/views.py:1443
+#: aleksis/core/views.py:1445
 msgid "Person was invited successfully."
 msgstr ""
 
-#: aleksis/core/views.py:1445
+#: aleksis/core/views.py:1447
 msgid "Person was already invited."
 msgstr ""
 
diff --git a/aleksis/core/locale/nb_NO/LC_MESSAGES/djangojs.po b/aleksis/core/locale/nb_NO/LC_MESSAGES/djangojs.po
index db33a52583b3ad2cff7af57a8306fb4a5d4c6117..427b5fbc842fe8bbbc70d795633af5070b404ec7 100644
--- a/aleksis/core/locale/nb_NO/LC_MESSAGES/djangojs.po
+++ b/aleksis/core/locale/nb_NO/LC_MESSAGES/djangojs.po
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2022-01-10 17:26+0100\n"
+"POT-Creation-Date: 2022-01-31 17:03+0100\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"
@@ -17,18 +17,18 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: aleksis/core/static/js/main.js:15
+#: aleksis/core/static/js/main.js:66
 msgid "Today"
 msgstr ""
 
-#: aleksis/core/static/js/main.js:16
+#: aleksis/core/static/js/main.js:67
 msgid "Cancel"
 msgstr ""
 
-#: aleksis/core/static/js/main.js:17
+#: aleksis/core/static/js/main.js:68
 msgid "OK"
 msgstr ""
 
-#: aleksis/core/static/js/main.js:131
+#: aleksis/core/static/js/main.js:191
 msgid "This page may contain outdated information since there is no internet connection."
 msgstr ""
diff --git a/aleksis/core/locale/tr_TR/LC_MESSAGES/django.po b/aleksis/core/locale/tr_TR/LC_MESSAGES/django.po
index f78ef84c77fa4eb24f5423ed5d4b2033998e122d..9437eabc1987ac629a51e68f29b3dcc250179441 100644
--- a/aleksis/core/locale/tr_TR/LC_MESSAGES/django.po
+++ b/aleksis/core/locale/tr_TR/LC_MESSAGES/django.po
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: AlekSIS (School Information System) 0.1\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2022-01-10 17:26+0100\n"
+"POT-Creation-Date: 2022-01-31 17:03+0100\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"
@@ -17,51 +17,51 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: aleksis/core/apps.py:154
+#: aleksis/core/apps.py:166
 msgid "OpenID Connect scope"
 msgstr ""
 
-#: aleksis/core/apps.py:155
+#: aleksis/core/apps.py:167
 msgid "Given name, family name, link to profile and picture if existing."
 msgstr ""
 
-#: aleksis/core/apps.py:156
+#: aleksis/core/apps.py:168
 msgid "Full home postal address"
 msgstr ""
 
-#: aleksis/core/apps.py:157
+#: aleksis/core/apps.py:169
 msgid "Email address"
 msgstr ""
 
-#: aleksis/core/apps.py:158
+#: aleksis/core/apps.py:170
 msgid "Home and mobile phone"
 msgstr ""
 
-#: aleksis/core/apps.py:159 aleksis/core/forms.py:223 aleksis/core/menus.py:265
-#: aleksis/core/models.py:449 aleksis/core/templates/core/group/list.html:8
+#: aleksis/core/apps.py:171 aleksis/core/forms.py:218 aleksis/core/menus.py:265
+#: aleksis/core/models.py:462 aleksis/core/templates/core/group/list.html:8
 #: aleksis/core/templates/core/group/list.html:9
-#: aleksis/core/templates/core/person/full.html:242
+#: aleksis/core/templates/core/person/full.html:250
 msgid "Groups"
 msgstr ""
 
-#: aleksis/core/data_checks.py:55
+#: aleksis/core/data_checks.py:56
 msgid "Ignore problem"
 msgstr ""
 
-#: aleksis/core/data_checks.py:184
+#: aleksis/core/data_checks.py:185
 #, python-brace-format
 msgid "Solve option '{solve_option_obj.verbose_name}' "
 msgstr ""
 
-#: aleksis/core/data_checks.py:290
+#: aleksis/core/data_checks.py:291
 msgid "Deactivate DashboardWidget"
 msgstr ""
 
-#: aleksis/core/data_checks.py:302
+#: aleksis/core/data_checks.py:303
 msgid "Ensure that there are no broken DashboardWidgets."
 msgstr ""
 
-#: aleksis/core/data_checks.py:303
+#: aleksis/core/data_checks.py:304
 msgid "The DashboardWidget was reported broken automatically."
 msgstr ""
 
@@ -90,15 +90,15 @@ msgstr ""
 msgid "Content type"
 msgstr ""
 
-#: aleksis/core/filters.py:113 aleksis/core/models.py:675
+#: aleksis/core/filters.py:113 aleksis/core/models.py:688
 msgid "User"
 msgstr ""
 
-#: aleksis/core/filters.py:135 aleksis/core/models.py:448
+#: aleksis/core/filters.py:135 aleksis/core/models.py:461
 msgid "Group"
 msgstr ""
 
-#: aleksis/core/forms.py:48 aleksis/core/forms.py:559
+#: aleksis/core/forms.py:48 aleksis/core/forms.py:554
 msgid "Base data"
 msgstr ""
 
@@ -106,7 +106,7 @@ msgstr ""
 msgid "Address"
 msgstr ""
 
-#: aleksis/core/forms.py:54 aleksis/core/forms.py:568
+#: aleksis/core/forms.py:54 aleksis/core/forms.py:563
 msgid "Contact data"
 msgstr ""
 
@@ -122,121 +122,121 @@ msgstr ""
 msgid "Create a new account"
 msgstr ""
 
-#: aleksis/core/forms.py:135
+#: aleksis/core/forms.py:130
 msgid "You cannot set a new username when also selecting an existing user."
 msgstr ""
 
-#: aleksis/core/forms.py:139
+#: aleksis/core/forms.py:134
 msgid "This username is already in use."
 msgstr ""
 
-#: aleksis/core/forms.py:156 aleksis/core/models.py:130
+#: aleksis/core/forms.py:151 aleksis/core/models.py:130
 msgid "School term"
 msgstr ""
 
-#: aleksis/core/forms.py:157
+#: aleksis/core/forms.py:152
 msgid "Common data"
 msgstr ""
 
-#: aleksis/core/forms.py:158 aleksis/core/forms.py:210
+#: aleksis/core/forms.py:153 aleksis/core/forms.py:205
 #: aleksis/core/menus.py:254 aleksis/core/models.py:153
 #: aleksis/core/templates/core/person/list.html:8
 #: aleksis/core/templates/core/person/list.html:9
 msgid "Persons"
 msgstr ""
 
-#: aleksis/core/forms.py:159 aleksis/core/forms.py:570
+#: aleksis/core/forms.py:154 aleksis/core/forms.py:565
 msgid "Additional data"
 msgstr ""
 
-#: aleksis/core/forms.py:160 aleksis/core/models.py:206
-#: aleksis/core/models.py:501
+#: aleksis/core/forms.py:155 aleksis/core/models.py:206
+#: aleksis/core/models.py:514
 msgid "Photo"
 msgstr ""
 
-#: aleksis/core/forms.py:202 aleksis/core/forms.py:205
+#: aleksis/core/forms.py:197 aleksis/core/forms.py:200
 #: aleksis/core/models.py:73
 msgid "Date"
 msgstr ""
 
-#: aleksis/core/forms.py:203 aleksis/core/forms.py:206
+#: aleksis/core/forms.py:198 aleksis/core/forms.py:201
 #: aleksis/core/models.py:81
 msgid "Time"
 msgstr ""
 
-#: aleksis/core/forms.py:236
+#: aleksis/core/forms.py:231
 msgid "From when until when should the announcement be displayed?"
 msgstr ""
 
-#: aleksis/core/forms.py:239
+#: aleksis/core/forms.py:234
 msgid "Who should see the announcement?"
 msgstr ""
 
-#: aleksis/core/forms.py:240
+#: aleksis/core/forms.py:235
 msgid "Write your announcement:"
 msgstr ""
 
-#: aleksis/core/forms.py:279
+#: aleksis/core/forms.py:274
 msgid "You are not allowed to create announcements which are only valid in the past."
 msgstr ""
 
-#: aleksis/core/forms.py:283
+#: aleksis/core/forms.py:278
 msgid "The from date and time must be earlier then the until date and time."
 msgstr ""
 
-#: aleksis/core/forms.py:292
+#: aleksis/core/forms.py:287
 msgid "You need at least one recipient."
 msgstr ""
 
-#: aleksis/core/forms.py:401
+#: aleksis/core/forms.py:396
 msgid "Invitation code"
 msgstr ""
 
-#: aleksis/core/forms.py:402
+#: aleksis/core/forms.py:397
 msgid "Please enter your invitation code."
 msgstr ""
 
-#: aleksis/core/forms.py:434
+#: aleksis/core/forms.py:429
 msgid "Who should get the permission?"
 msgstr ""
 
-#: aleksis/core/forms.py:435
+#: aleksis/core/forms.py:430
 msgid "On what?"
 msgstr ""
 
-#: aleksis/core/forms.py:461
+#: aleksis/core/forms.py:456
 msgid "Select objects which the permission should be granted for:"
 msgstr ""
 
-#: aleksis/core/forms.py:464
+#: aleksis/core/forms.py:459
 msgid "Grant the permission for all objects"
 msgstr ""
 
-#: aleksis/core/forms.py:472
+#: aleksis/core/forms.py:467
 msgid "You must select at least one group or person which should get the permission."
 msgstr ""
 
-#: aleksis/core/forms.py:477
+#: aleksis/core/forms.py:472
 msgid "You must grant the permission to all objects and/or to some objects."
 msgstr ""
 
-#: aleksis/core/forms.py:564
+#: aleksis/core/forms.py:559
 msgid "Adress data"
 msgstr ""
 
-#: aleksis/core/forms.py:576
+#: aleksis/core/forms.py:571
 msgid "Account data"
 msgstr ""
 
-#: aleksis/core/forms.py:583
+#: aleksis/core/forms.py:578
 msgid "Password"
 msgstr ""
 
-#: aleksis/core/forms.py:586
+#: aleksis/core/forms.py:581
 msgid "Password (again)"
 msgstr ""
 
-#: aleksis/core/forms.py:752
+#: aleksis/core/forms.py:747
 msgid "No valid selection."
 msgstr ""
 
@@ -244,22 +244,20 @@ msgstr ""
 msgid "There are unresolved data problems."
 msgstr ""
 
-#: aleksis/core/health_checks.py:44
-#, python-brace-format
-msgid "Last backup {time_gone_since_backup}!"
+#: aleksis/core/health_checks.py:40
+msgid "Error accessing backup storage: {}"
 msgstr ""
 
-#: aleksis/core/health_checks.py:46
-msgid "No backup found!"
+#: aleksis/core/health_checks.py:50
+msgid "Last backup {}!"
 msgstr ""
 
-#: aleksis/core/health_checks.py:73
-msgid "No backup result found!"
+#: aleksis/core/health_checks.py:52
+msgid "No backup found!"
 msgstr ""
 
-#: aleksis/core/health_checks.py:75
-#, python-brace-format
-msgid "{task.status} - {task.result}"
+#: aleksis/core/health_checks.py:79
+msgid "No backup result found!"
 msgstr ""
 
 #: aleksis/core/menus.py:9 aleksis/core/templates/two_factor/core/login.html:6
@@ -281,7 +279,7 @@ msgstr ""
 msgid "Dashboard"
 msgstr ""
 
-#: aleksis/core/menus.py:41 aleksis/core/models.py:721
+#: aleksis/core/menus.py:41 aleksis/core/models.py:734
 #: aleksis/core/preferences.py:29
 #: aleksis/core/templates/core/notifications.html:4
 #: aleksis/core/templates/core/notifications.html:5
@@ -339,7 +337,7 @@ msgstr ""
 msgid "Admin"
 msgstr ""
 
-#: aleksis/core/menus.py:141 aleksis/core/models.py:821
+#: aleksis/core/menus.py:141 aleksis/core/models.py:834
 #: aleksis/core/templates/core/announcement/list.html:7
 #: aleksis/core/templates/core/announcement/list.html:8
 msgid "Announcements"
@@ -397,7 +395,7 @@ msgstr ""
 msgid "People"
 msgstr ""
 
-#: aleksis/core/menus.py:276 aleksis/core/models.py:1075
+#: aleksis/core/menus.py:276 aleksis/core/models.py:1055
 #: aleksis/core/templates/core/group_type/list.html:8
 #: aleksis/core/templates/core/group_type/list.html:9
 msgid "Group types"
@@ -407,7 +405,7 @@ msgstr ""
 msgid "Groups and child groups"
 msgstr ""
 
-#: aleksis/core/menus.py:298 aleksis/core/models.py:497
+#: aleksis/core/menus.py:298 aleksis/core/models.py:510
 #: aleksis/core/templates/core/additional_field/list.html:8
 #: aleksis/core/templates/core/additional_field/list.html:9
 msgid "Additional fields"
@@ -467,7 +465,7 @@ msgstr ""
 msgid "URL / Link"
 msgstr ""
 
-#: aleksis/core/models.py:94 aleksis/core/models.py:1044
+#: aleksis/core/models.py:94 aleksis/core/models.py:1024
 msgid "Name"
 msgstr ""
 
@@ -487,7 +485,7 @@ msgstr ""
 msgid "There is already a school term for this time or a part of this time."
 msgstr ""
 
-#: aleksis/core/models.py:152 aleksis/core/models.py:993
+#: aleksis/core/models.py:152 aleksis/core/models.py:973
 msgid "Person"
 msgstr ""
 
@@ -523,7 +521,7 @@ msgstr ""
 msgid "male"
 msgstr ""
 
-#: aleksis/core/models.py:178 aleksis/core/models.py:1238
+#: aleksis/core/models.py:178 aleksis/core/models.py:1219
 msgid "Linked user"
 msgstr ""
 
@@ -539,7 +537,7 @@ msgstr ""
 msgid "Additional name(s)"
 msgstr ""
 
-#: aleksis/core/models.py:188 aleksis/core/models.py:466
+#: aleksis/core/models.py:188 aleksis/core/models.py:479
 msgid "Short name"
 msgstr ""
 
@@ -559,11 +557,11 @@ msgstr ""
 msgid "Place"
 msgstr ""
 
-#: aleksis/core/models.py:196
+#: aleksis/core/models.py:196 aleksis/core/templates/core/person/full.html:172
 msgid "Home phone"
 msgstr ""
 
-#: aleksis/core/models.py:197
+#: aleksis/core/models.py:197 aleksis/core/templates/core/person/full.html:182
 msgid "Mobile phone"
 msgstr ""
 
@@ -579,19 +577,19 @@ msgstr ""
 msgid "Sex"
 msgstr ""
 
-#: aleksis/core/models.py:210 aleksis/core/models.py:505
+#: aleksis/core/models.py:210 aleksis/core/models.py:518
 msgid "This is an official photo, used for official documents and for internal use cases."
 msgstr ""
 
-#: aleksis/core/models.py:215 aleksis/core/models.py:509
+#: aleksis/core/models.py:215 aleksis/core/models.py:522
 msgid "Display picture / Avatar"
 msgstr ""
 
-#: aleksis/core/models.py:218 aleksis/core/models.py:512
+#: aleksis/core/models.py:218 aleksis/core/models.py:525
 msgid "This is a picture or an avatar for public display."
 msgstr ""
 
-#: aleksis/core/models.py:223 aleksis/core/templates/core/person/full.html:231
+#: aleksis/core/models.py:223 aleksis/core/templates/core/person/full.html:239
 msgid "Guardians / Parents"
 msgstr ""
 
@@ -599,364 +597,368 @@ msgstr ""
 msgid "Primary group"
 msgstr ""
 
-#: aleksis/core/models.py:233 aleksis/core/models.py:679
-#: aleksis/core/models.py:703 aleksis/core/models.py:788
-#: aleksis/core/models.py:1068
+#: aleksis/core/models.py:233 aleksis/core/models.py:692
+#: aleksis/core/models.py:716 aleksis/core/models.py:801
+#: aleksis/core/models.py:1048
 msgid "Description"
 msgstr ""
 
-#: aleksis/core/models.py:421
+#: aleksis/core/models.py:434
 msgid "Title of field"
 msgstr ""
 
-#: aleksis/core/models.py:423
+#: aleksis/core/models.py:436
 msgid "Type of field"
 msgstr ""
 
-#: aleksis/core/models.py:430
+#: aleksis/core/models.py:443
 msgid "Addtitional field for groups"
 msgstr ""
 
-#: aleksis/core/models.py:431
+#: aleksis/core/models.py:444
 msgid "Addtitional fields for groups"
 msgstr ""
 
-#: aleksis/core/models.py:451
+#: aleksis/core/models.py:464
 msgid "Can assign child groups to groups"
 msgstr ""
 
-#: aleksis/core/models.py:452
+#: aleksis/core/models.py:465
 msgid "Can view statistics about group."
 msgstr ""
 
-#: aleksis/core/models.py:464
+#: aleksis/core/models.py:477
 msgid "Long name"
 msgstr ""
 
-#: aleksis/core/models.py:474 aleksis/core/templates/core/group/full.html:85
+#: aleksis/core/models.py:487 aleksis/core/templates/core/group/full.html:85
 msgid "Members"
 msgstr ""
 
-#: aleksis/core/models.py:477 aleksis/core/templates/core/group/full.html:82
+#: aleksis/core/models.py:490 aleksis/core/templates/core/group/full.html:82
 msgid "Owners"
 msgstr ""
 
-#: aleksis/core/models.py:484 aleksis/core/templates/core/group/full.html:55
+#: aleksis/core/models.py:497 aleksis/core/templates/core/group/full.html:55
 msgid "Parent groups"
 msgstr ""
 
-#: aleksis/core/models.py:492
+#: aleksis/core/models.py:505
 msgid "Type of group"
 msgstr ""
 
-#: aleksis/core/models.py:678 aleksis/core/models.py:702
-#: aleksis/core/models.py:787
+#: aleksis/core/models.py:691 aleksis/core/models.py:715
+#: aleksis/core/models.py:800
 #: aleksis/core/templates/core/announcement/list.html:18
 msgid "Title"
 msgstr ""
 
-#: aleksis/core/models.py:681
+#: aleksis/core/models.py:694
 msgid "Application"
 msgstr ""
 
-#: aleksis/core/models.py:687
+#: aleksis/core/models.py:700
 msgid "Activity"
 msgstr ""
 
-#: aleksis/core/models.py:688
+#: aleksis/core/models.py:701
 msgid "Activities"
 msgstr ""
 
-#: aleksis/core/models.py:694
+#: aleksis/core/models.py:707
 msgid "Sender"
 msgstr ""
 
-#: aleksis/core/models.py:699
+#: aleksis/core/models.py:712
 msgid "Recipient"
 msgstr ""
 
-#: aleksis/core/models.py:704 aleksis/core/models.py:1045
+#: aleksis/core/models.py:717 aleksis/core/models.py:1025
 msgid "Link"
 msgstr ""
 
-#: aleksis/core/models.py:706
+#: aleksis/core/models.py:719
 msgid "Read"
 msgstr ""
 
-#: aleksis/core/models.py:707
+#: aleksis/core/models.py:720
 msgid "Sent"
 msgstr ""
 
-#: aleksis/core/models.py:720
+#: aleksis/core/models.py:733
 msgid "Notification"
 msgstr ""
 
-#: aleksis/core/models.py:789
+#: aleksis/core/models.py:802
 msgid "Link to detailed view"
 msgstr ""
 
-#: aleksis/core/models.py:792
+#: aleksis/core/models.py:805
 msgid "Date and time from when to show"
 msgstr ""
 
-#: aleksis/core/models.py:795
+#: aleksis/core/models.py:808
 msgid "Date and time until when to show"
 msgstr ""
 
-#: aleksis/core/models.py:820
+#: aleksis/core/models.py:833
 msgid "Announcement"
 msgstr ""
 
-#: aleksis/core/models.py:858
+#: aleksis/core/models.py:871
 msgid "Announcement recipient"
 msgstr ""
 
-#: aleksis/core/models.py:859
+#: aleksis/core/models.py:872
 msgid "Announcement recipients"
 msgstr ""
 
-#: aleksis/core/models.py:914
+#: aleksis/core/models.py:894
 msgid "Widget Title"
 msgstr ""
 
-#: aleksis/core/models.py:915
+#: aleksis/core/models.py:895
 msgid "Activate Widget"
 msgstr ""
 
-#: aleksis/core/models.py:916
+#: aleksis/core/models.py:896
 msgid "Widget is broken"
 msgstr ""
 
-#: aleksis/core/models.py:919
+#: aleksis/core/models.py:899
 msgid "Size on mobile devices"
 msgstr ""
 
-#: aleksis/core/models.py:920
+#: aleksis/core/models.py:900
 msgid "<= 600 px, 12 columns"
 msgstr ""
 
-#: aleksis/core/models.py:925
+#: aleksis/core/models.py:905
 msgid "Size on tablet devices"
 msgstr ""
 
-#: aleksis/core/models.py:926
+#: aleksis/core/models.py:906
 msgid "> 600 px, 12 columns"
 msgstr ""
 
-#: aleksis/core/models.py:931
+#: aleksis/core/models.py:911
 msgid "Size on desktop devices"
 msgstr ""
 
-#: aleksis/core/models.py:932
+#: aleksis/core/models.py:912
 msgid "> 992 px, 12 columns"
 msgstr ""
 
-#: aleksis/core/models.py:937
+#: aleksis/core/models.py:917
 msgid "Size on large desktop devices"
 msgstr ""
 
-#: aleksis/core/models.py:938
+#: aleksis/core/models.py:918
 msgid "> 1200 px>, 12 columns"
 msgstr ""
 
-#: aleksis/core/models.py:969
+#: aleksis/core/models.py:949
 msgid "Can edit default dashboard"
 msgstr ""
 
-#: aleksis/core/models.py:970
+#: aleksis/core/models.py:950
 msgid "Dashboard Widget"
 msgstr ""
 
-#: aleksis/core/models.py:971
+#: aleksis/core/models.py:951
 msgid "Dashboard Widgets"
 msgstr ""
 
-#: aleksis/core/models.py:977
+#: aleksis/core/models.py:957
 msgid "URL"
 msgstr ""
 
-#: aleksis/core/models.py:978
+#: aleksis/core/models.py:958
 msgid "Icon URL"
 msgstr ""
 
-#: aleksis/core/models.py:984
+#: aleksis/core/models.py:964
 msgid "External link widget"
 msgstr ""
 
-#: aleksis/core/models.py:985
+#: aleksis/core/models.py:965
 msgid "External link widgets"
 msgstr ""
 
-#: aleksis/core/models.py:990
+#: aleksis/core/models.py:970
 msgid "Dashboard widget"
 msgstr ""
 
-#: aleksis/core/models.py:995
+#: aleksis/core/models.py:975
 msgid "Order"
 msgstr ""
 
-#: aleksis/core/models.py:996
+#: aleksis/core/models.py:976
 msgid "Part of the default dashboard"
 msgstr ""
 
-#: aleksis/core/models.py:1011
+#: aleksis/core/models.py:991
 msgid "Dashboard widget order"
 msgstr ""
 
-#: aleksis/core/models.py:1012
+#: aleksis/core/models.py:992
 msgid "Dashboard widget orders"
 msgstr ""
 
-#: aleksis/core/models.py:1018
+#: aleksis/core/models.py:998
 msgid "Menu ID"
 msgstr ""
 
-#: aleksis/core/models.py:1031
+#: aleksis/core/models.py:1011
 msgid "Custom menu"
 msgstr ""
 
-#: aleksis/core/models.py:1032
+#: aleksis/core/models.py:1012
 msgid "Custom menus"
 msgstr ""
 
-#: aleksis/core/models.py:1042
+#: aleksis/core/models.py:1022
 msgid "Menu"
 msgstr ""
 
-#: aleksis/core/models.py:1046 aleksis/core/models.py:1285
+#: aleksis/core/models.py:1026 aleksis/core/models.py:1266
 #: aleksis/core/templates/oauth2_provider/application/detail.html:26
 msgid "Icon"
 msgstr ""
 
-#: aleksis/core/models.py:1052
+#: aleksis/core/models.py:1032
 msgid "Custom menu item"
 msgstr ""
 
-#: aleksis/core/models.py:1053
+#: aleksis/core/models.py:1033
 msgid "Custom menu items"
 msgstr ""
 
-#: aleksis/core/models.py:1067
+#: aleksis/core/models.py:1047
 msgid "Title of type"
 msgstr ""
 
-#: aleksis/core/models.py:1074 aleksis/core/templates/core/group/full.html:47
+#: aleksis/core/models.py:1054 aleksis/core/templates/core/group/full.html:47
 msgid "Group type"
 msgstr ""
 
-#: aleksis/core/models.py:1088
+#: aleksis/core/models.py:1068
 msgid "Can view system status"
 msgstr ""
 
-#: aleksis/core/models.py:1089
+#: aleksis/core/models.py:1069
 msgid "Can manage data"
 msgstr ""
 
-#: aleksis/core/models.py:1090
+#: aleksis/core/models.py:1070
 msgid "Can impersonate"
 msgstr ""
 
-#: aleksis/core/models.py:1091
+#: aleksis/core/models.py:1071
 msgid "Can use search"
 msgstr ""
 
-#: aleksis/core/models.py:1092
+#: aleksis/core/models.py:1072
 msgid "Can change site preferences"
 msgstr ""
 
-#: aleksis/core/models.py:1093
+#: aleksis/core/models.py:1073
 msgid "Can change person preferences"
 msgstr ""
 
-#: aleksis/core/models.py:1094
+#: aleksis/core/models.py:1074
 msgid "Can change group preferences"
 msgstr ""
 
-#: aleksis/core/models.py:1095
+#: aleksis/core/models.py:1075
 msgid "Can test PDF generation"
 msgstr ""
 
-#: aleksis/core/models.py:1131
+#: aleksis/core/models.py:1076
+msgid "Can invite persons"
+msgstr ""
+
+#: aleksis/core/models.py:1112
 msgid "Related data check task"
 msgstr ""
 
-#: aleksis/core/models.py:1139
+#: aleksis/core/models.py:1120
 msgid "Issue solved"
 msgstr ""
 
-#: aleksis/core/models.py:1140
+#: aleksis/core/models.py:1121
 msgid "Notification sent"
 msgstr ""
 
-#: aleksis/core/models.py:1153
+#: aleksis/core/models.py:1134
 msgid "Data check result"
 msgstr ""
 
-#: aleksis/core/models.py:1154
+#: aleksis/core/models.py:1135
 msgid "Data check results"
 msgstr ""
 
-#: aleksis/core/models.py:1156
+#: aleksis/core/models.py:1137
 msgid "Can run data checks"
 msgstr ""
 
-#: aleksis/core/models.py:1157
+#: aleksis/core/models.py:1138
 msgid "Can solve data check problems"
 msgstr ""
 
-#: aleksis/core/models.py:1164
+#: aleksis/core/models.py:1145
 msgid "E-Mail address"
 msgstr ""
 
-#: aleksis/core/models.py:1188
+#: aleksis/core/models.py:1169
 msgid "Owner"
 msgstr ""
 
-#: aleksis/core/models.py:1192
+#: aleksis/core/models.py:1173
 msgid "File expires at"
 msgstr ""
 
-#: aleksis/core/models.py:1194
+#: aleksis/core/models.py:1175
 msgid "Generated HTML file"
 msgstr ""
 
-#: aleksis/core/models.py:1196
+#: aleksis/core/models.py:1177
 msgid "Generated PDF file"
 msgstr ""
 
-#: aleksis/core/models.py:1203
+#: aleksis/core/models.py:1184
 msgid "PDF file"
 msgstr ""
 
-#: aleksis/core/models.py:1204
+#: aleksis/core/models.py:1185
 msgid "PDF files"
 msgstr ""
 
-#: aleksis/core/models.py:1209
+#: aleksis/core/models.py:1190
 msgid "Task result"
 msgstr ""
 
-#: aleksis/core/models.py:1212
+#: aleksis/core/models.py:1193
 msgid "Task user"
 msgstr ""
 
-#: aleksis/core/models.py:1224
+#: aleksis/core/models.py:1205
 msgid "Task user assignment"
 msgstr ""
 
-#: aleksis/core/models.py:1225
+#: aleksis/core/models.py:1206
 msgid "Task user assignments"
 msgstr ""
 
-#: aleksis/core/models.py:1241
+#: aleksis/core/models.py:1222
 msgid "Additional attributes"
 msgstr ""
 
-#: aleksis/core/models.py:1279
+#: aleksis/core/models.py:1260
 msgid "Allowed scopes that clients can request"
 msgstr ""
 
-#: aleksis/core/models.py:1289
+#: aleksis/core/models.py:1270
 msgid "This image will be shown as icon in the authorization flow. It should be squared."
 msgstr ""
 
@@ -992,7 +994,7 @@ msgstr ""
 msgid "Internationalisation"
 msgstr ""
 
-#: aleksis/core/preferences.py:44
+#: aleksis/core/preferences.py:43
 msgid "Site title"
 msgstr ""
 
@@ -1000,11 +1002,11 @@ msgstr ""
 msgid "Site description"
 msgstr ""
 
-#: aleksis/core/preferences.py:66
+#: aleksis/core/preferences.py:65
 msgid "Primary colour"
 msgstr ""
 
-#: aleksis/core/preferences.py:78
+#: aleksis/core/preferences.py:77
 msgid "Secondary colour"
 msgstr ""
 
@@ -1012,147 +1014,151 @@ msgstr ""
 msgid "Logo"
 msgstr ""
 
-#: aleksis/core/preferences.py:99
+#: aleksis/core/preferences.py:100
 msgid "Favicon"
 msgstr ""
 
-#: aleksis/core/preferences.py:109
+#: aleksis/core/preferences.py:111
 msgid "PWA-Icon"
 msgstr ""
 
-#: aleksis/core/preferences.py:120
+#: aleksis/core/preferences.py:121
+msgid "PWA-Icon is maskable"
+msgstr ""
+
+#: aleksis/core/preferences.py:133
 msgid "Mail out name"
 msgstr ""
 
-#: aleksis/core/preferences.py:131
+#: aleksis/core/preferences.py:144
 msgid "Mail out address"
 msgstr ""
 
-#: aleksis/core/preferences.py:143
+#: aleksis/core/preferences.py:157
 msgid "Link to privacy policy"
 msgstr ""
 
-#: aleksis/core/preferences.py:155
+#: aleksis/core/preferences.py:169
 msgid "Link to imprint"
 msgstr ""
 
-#: aleksis/core/preferences.py:167
+#: aleksis/core/preferences.py:180
 msgid "Name format for addressing"
 msgstr ""
 
-#: aleksis/core/preferences.py:183
+#: aleksis/core/preferences.py:197
 msgid "Channels to use for notifications"
 msgstr ""
 
-#: aleksis/core/preferences.py:195
+#: aleksis/core/preferences.py:209
 msgid "Regular expression to match primary group, e.g. '^Class .*'"
 msgstr ""
 
-#: aleksis/core/preferences.py:206
+#: aleksis/core/preferences.py:220
 msgid "Field on person to match primary group against"
 msgstr ""
 
-#: aleksis/core/preferences.py:218
+#: aleksis/core/preferences.py:232
 msgid "Automatically create new persons for new users"
 msgstr ""
 
-#: aleksis/core/preferences.py:227
+#: aleksis/core/preferences.py:241
 msgid "Automatically link existing persons to new users by their e-mail address"
 msgstr ""
 
-#: aleksis/core/preferences.py:238
+#: aleksis/core/preferences.py:252
 msgid "Display name of the school"
 msgstr ""
 
-#: aleksis/core/preferences.py:249
+#: aleksis/core/preferences.py:263
 msgid "Official name of the school, e.g. as given by supervisory authority"
 msgstr ""
 
-#: aleksis/core/preferences.py:257
+#: aleksis/core/preferences.py:271
 msgid "Allow users to change their passwords"
 msgstr ""
 
-#: aleksis/core/preferences.py:265
+#: aleksis/core/preferences.py:279
 msgid "Enable signup"
 msgstr ""
 
-#: aleksis/core/preferences.py:273
+#: aleksis/core/preferences.py:287
 msgid "Enable invitations"
 msgstr ""
 
-#: aleksis/core/preferences.py:281
+#: aleksis/core/preferences.py:295
 msgid "Length of invite code. (Default 3: abcde-acbde-abcde)"
 msgstr ""
 
-#: aleksis/core/preferences.py:289
+#: aleksis/core/preferences.py:303
 msgid "Size of packets. (Default 5: abcde)"
 msgstr ""
 
-#: aleksis/core/preferences.py:300
+#: aleksis/core/preferences.py:314
 msgid "Allowed Grant Flows for OAuth applications"
 msgstr ""
 
-#: aleksis/core/preferences.py:313
+#: aleksis/core/preferences.py:328
 msgid "Available languages"
 msgstr ""
 
-#: aleksis/core/preferences.py:325
+#: aleksis/core/preferences.py:341
 msgid "Send emails if data checks detect problems"
 msgstr ""
 
-#: aleksis/core/preferences.py:336
+#: aleksis/core/preferences.py:352
 msgid "Email recipients for data checks problem emails"
 msgstr ""
 
-#: aleksis/core/preferences.py:347
+#: aleksis/core/preferences.py:363
 msgid "Email recipient groups for data checks problem emails"
 msgstr ""
 
-#: aleksis/core/preferences.py:356
+#: aleksis/core/preferences.py:372
 msgid "Show dashboard to users without login"
 msgstr ""
 
-#: aleksis/core/preferences.py:365
+#: aleksis/core/preferences.py:381
 msgid "Allow users to edit their dashboard"
 msgstr ""
 
-#: aleksis/core/preferences.py:376
+#: aleksis/core/preferences.py:392
 msgid "Fields on person model which are editable by themselves."
 msgstr ""
 
-#: aleksis/core/preferences.py:390
+#: aleksis/core/preferences.py:407
 msgid "Editable fields on person model which should trigger a notification on change"
 msgstr ""
 
-#: aleksis/core/preferences.py:403
+#: aleksis/core/preferences.py:421
 msgid "Contact for notification if a person changes their data"
 msgstr ""
 
-#: aleksis/core/preferences.py:413
+#: aleksis/core/preferences.py:432
 msgid "PDF file expiration duration"
 msgstr ""
 
-#: aleksis/core/preferences.py:414
+#: aleksis/core/preferences.py:433
 msgid "in minutes"
 msgstr ""
 
-#: aleksis/core/preferences.py:424
+#: aleksis/core/preferences.py:443
 msgid "Automatically update the dashboard and its widgets"
 msgstr ""
 
-#: aleksis/core/preferences.py:434
+#: aleksis/core/preferences.py:453
 msgid "Automatically update the dashboard and its widgets sitewide"
 msgstr ""
 
-#: aleksis/core/preferences.py:444
+#: aleksis/core/preferences.py:463
 msgid "Country for phone number parsing"
 msgstr ""
 
-#: aleksis/core/settings.py:518
+#: aleksis/core/settings.py:526
 msgid "English"
 msgstr ""
 
-#: aleksis/core/settings.py:519
+#: aleksis/core/settings.py:527
 msgid "German"
 msgstr ""
 
@@ -1499,7 +1505,7 @@ msgstr ""
 msgid "Privacy Policy"
 msgstr ""
 
-#: aleksis/core/templates/core/base_print.html:72
+#: aleksis/core/templates/core/base_print.html:74
 msgid "Powered by AlekSIS®"
 msgstr ""
 
@@ -2126,19 +2132,11 @@ msgstr ""
 msgid "Contact details"
 msgstr ""
 
-#: aleksis/core/templates/core/person/full.html:168
-msgid "home number"
-msgstr ""
-
-#: aleksis/core/templates/core/person/full.html:174
-msgid "mobile number"
-msgstr ""
-
-#: aleksis/core/templates/core/person/full.html:216
+#: aleksis/core/templates/core/person/full.html:224
 msgid "This person didn't upload a personal photo."
 msgstr ""
 
-#: aleksis/core/templates/core/person/full.html:224
+#: aleksis/core/templates/core/person/full.html:232
 msgid "Children"
 msgstr ""
 
@@ -2934,23 +2932,23 @@ msgstr ""
 msgid "SMS"
 msgstr ""
 
-#: aleksis/core/util/pdf.py:113
+#: aleksis/core/util/pdf.py:118
 msgid "Progress: Generate PDF file"
 msgstr ""
 
-#: aleksis/core/util/pdf.py:114
+#: aleksis/core/util/pdf.py:119
 msgid "Generating PDF file …"
 msgstr ""
 
-#: aleksis/core/util/pdf.py:115
+#: aleksis/core/util/pdf.py:120
 msgid "The PDF file has been generated successfully."
 msgstr ""
 
-#: aleksis/core/util/pdf.py:116
+#: aleksis/core/util/pdf.py:121
 msgid "There was a problem while generating the PDF file."
 msgstr ""
 
-#: aleksis/core/util/pdf.py:119
+#: aleksis/core/util/pdf.py:124
 msgid "Download PDF"
 msgstr ""
 
@@ -3100,10 +3098,10 @@ msgstr ""
 msgid "The third-party account has been successfully disconnected."
 msgstr ""
 
-#: aleksis/core/views.py:1443
+#: aleksis/core/views.py:1445
 msgid "Person was invited successfully."
 msgstr ""
 
-#: aleksis/core/views.py:1445
+#: aleksis/core/views.py:1447
 msgid "Person was already invited."
 msgstr ""
diff --git a/aleksis/core/locale/tr_TR/LC_MESSAGES/djangojs.po b/aleksis/core/locale/tr_TR/LC_MESSAGES/djangojs.po
index db33a52583b3ad2cff7af57a8306fb4a5d4c6117..427b5fbc842fe8bbbc70d795633af5070b404ec7 100644
--- a/aleksis/core/locale/tr_TR/LC_MESSAGES/djangojs.po
+++ b/aleksis/core/locale/tr_TR/LC_MESSAGES/djangojs.po
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2022-01-10 17:26+0100\n"
+"POT-Creation-Date: 2022-01-31 17:03+0100\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"
@@ -17,18 +17,18 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: aleksis/core/static/js/main.js:15
+#: aleksis/core/static/js/main.js:66
 msgid "Today"
 msgstr ""
 
-#: aleksis/core/static/js/main.js:16
+#: aleksis/core/static/js/main.js:67
 msgid "Cancel"
 msgstr ""
 
-#: aleksis/core/static/js/main.js:17
+#: aleksis/core/static/js/main.js:68
 msgid "OK"
 msgstr ""
 
-#: aleksis/core/static/js/main.js:131
+#: aleksis/core/static/js/main.js:191
 msgid "This page may contain outdated information since there is no internet connection."
 msgstr ""
diff --git a/aleksis/core/migrations/0035_preference_model_unique.py b/aleksis/core/migrations/0035_preference_model_unique.py
new file mode 100644
index 0000000000000000000000000000000000000000..b5227060eaf9ba46ec8a07261ec6a56cdeb256a7
--- /dev/null
+++ b/aleksis/core/migrations/0035_preference_model_unique.py
@@ -0,0 +1,51 @@
+# Generated by Django 3.2.11 on 2022-01-27 18:52
+
+from email.headerregistry import Group
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('sites', '0002_alter_domain_unique'),
+        ('core', '0034_invite_permission'),
+    ]
+
+    def _migrate_preference_models_to_unique(apps, schema_editor):
+        from aleksis.core.models import GroupPreferenceModel, PersonPreferenceModel, SitePreferenceModel
+
+        models = [GroupPreferenceModel, PersonPreferenceModel, SitePreferenceModel]
+
+        for model in models:
+            duplicates = {}
+            db_alias = schema_editor.connection.alias
+            for obj in model.objects.using(db_alias).all():
+                key = f"{obj.instance.pk}__{obj.section}__{obj.name}"
+                duplicates.setdefault(key, [])
+                duplicates[key].append(obj)
+
+            for key, objs in duplicates.items():
+                if len(objs) > 1:
+                    found = False
+                    for obj in objs:
+                        if obj.value == obj.preference.default or found:
+                            obj.delete()
+                        else:
+                            found = True
+
+
+    operations = [
+        migrations.RunPython(_migrate_preference_models_to_unique),
+        migrations.AlterUniqueTogether(
+            name='grouppreferencemodel',
+            unique_together={('instance', 'section', 'name')},
+        ),
+        migrations.AlterUniqueTogether(
+            name='personpreferencemodel',
+            unique_together={('instance', 'section', 'name')},
+        ),
+        migrations.AlterUniqueTogether(
+            name='sitepreferencemodel',
+            unique_together={('instance', 'section', 'name')},
+        ),
+    ]
diff --git a/aleksis/core/models.py b/aleksis/core/models.py
index f46a803b687cc9cde9a893c642586eac232fd84d..d8f63e606073f92e8db799206012cfc9a998a5d8 100644
--- a/aleksis/core/models.py
+++ b/aleksis/core/models.py
@@ -316,7 +316,7 @@ class Person(ExtensibleModel):
     def initials(self):
         return f"{self.first_name[0]}{self.last_name[0]}".upper()
 
-    user_info_tracker = FieldTracker(fields=("first_name", "last_name", "email"))
+    user_info_tracker = FieldTracker(fields=("first_name", "last_name", "email", "user_id"))
 
     @property
     def member_of_recursive(self) -> QuerySet:
@@ -336,16 +336,29 @@ class Person(ExtensibleModel):
 
     def save(self, *args, **kwargs):
         # Determine all fields that were changed since last load
-        dirty = self.pk is None or bool(self.user_info_tracker.changed())
+        changed = self.user_info_tracker.changed()
 
         super().save(*args, **kwargs)
 
-        if self.user and dirty:
-            # Synchronise user fields to linked User object to keep it up to date
-            self.user.first_name = self.first_name
-            self.user.last_name = self.last_name
-            self.user.email = self.email
-            self.user.save()
+        if self.pk is None or bool(changed):
+            if "user_id" in changed:
+                # Clear groups of previous Django user
+                previous_user = changed["user_id"]
+                if previous_user is not None:
+                    get_user_model().objects.get(pk=previous_user).groups.clear()
+
+            if self.user:
+                if "first_name" in changed or "last_name" in changed or "email" in changed:
+                    # Synchronise user fields to linked User object to keep it up to date
+                    self.user.first_name = self.first_name
+                    self.user.last_name = self.last_name
+                    self.user.email = self.email
+                    self.user.save()
+
+                if "user_id" in changed:
+                    # Synchronise groups to Django groups
+                    for group in self.member_of.union(self.owner_of.all()).all():
+                        group.save(force=True)
 
         # Select a primary group if none is set
         self.auto_select_primary_group()
@@ -1069,7 +1082,7 @@ class SitePreferenceModel(PerInstancePreferenceModel, PureDjangoModel):
 
     instance = models.ForeignKey(Site, on_delete=models.CASCADE)
 
-    class Meta:
+    class Meta(PerInstancePreferenceModel.Meta):
         app_label = "core"
 
 
@@ -1078,7 +1091,7 @@ class PersonPreferenceModel(PerInstancePreferenceModel, PureDjangoModel):
 
     instance = models.ForeignKey(Person, on_delete=models.CASCADE)
 
-    class Meta:
+    class Meta(PerInstancePreferenceModel.Meta):
         app_label = "core"
 
 
@@ -1087,7 +1100,7 @@ class GroupPreferenceModel(PerInstancePreferenceModel, PureDjangoModel):
 
     instance = models.ForeignKey(Group, on_delete=models.CASCADE)
 
-    class Meta:
+    class Meta(PerInstancePreferenceModel.Meta):
         app_label = "core"
 
 
diff --git a/aleksis/core/preferences.py b/aleksis/core/preferences.py
index fe29f220f211616bf57d08c04e87a95b60c84365..f1fb0227eab16a152f29918e91b37d0808471812 100644
--- a/aleksis/core/preferences.py
+++ b/aleksis/core/preferences.py
@@ -112,6 +112,17 @@ class PWAIcon(PublicFilePreferenceMixin, FilePreference):
     required = False
 
 
+@site_preferences_registry.register
+class PWAIconMaskable(BooleanPreference):
+    """PWA icon is maskable."""
+
+    section = theme
+    name = "pwa_icon_maskable"
+    verbose_name = _("PWA-Icon is maskable")
+    default = True
+    required = False
+
+
 @site_preferences_registry.register
 class MailOutName(StringPreference):
     """Mail out name of your AlekSIS instance."""
diff --git a/aleksis/core/settings.py b/aleksis/core/settings.py
index 2defba33645df5cf2f16be4a195a6385d00e0ce4..aaf341ef69d5618254053856f3d4b179db1e90c1 100644
--- a/aleksis/core/settings.py
+++ b/aleksis/core/settings.py
@@ -12,6 +12,7 @@ from .util.core_helpers import get_app_packages, merge_app_settings, monkey_patc
 monkey_patch()
 
 IN_PYTEST = "PYTEST_CURRENT_TEST" in os.environ or "TOX_ENV_DIR" in os.environ
+PYTEST_SETUP_DATABASES = [("default", "default_oot")]
 
 ENVVAR_PREFIX_FOR_DYNACONF = "ALEKSIS"
 DIRS_FOR_DYNACONF = ["/etc/aleksis"]
@@ -203,7 +204,7 @@ TEMPLATES = [
 
 # Attention: The following context processors must accept None
 # as first argument (in addition to a HttpRequest object)
-PDF_CONTEXT_PROCESSORS = [
+NON_REQUEST_CONTEXT_PROCESSORS = [
     "django.template.context_processors.i18n",
     "django.template.context_processors.tz",
     "aleksis.core.util.core_helpers.custom_information_processor",
@@ -227,6 +228,13 @@ DATABASES = {
     }
 }
 
+# Duplicate default database for out-of-transaction updates
+DATABASES["default_oot"] = DATABASES["default"].copy()
+DATABASE_ROUTERS = [
+    "aleksis.core.util.core_helpers.OOTRouter",
+]
+DATABASE_OOT_LABELS = ["django_celery_results"]
+
 merge_app_settings("DATABASES", DATABASES, False)
 
 REDIS_HOST = _settings.get("redis.host", "localhost")
@@ -704,7 +712,7 @@ if _settings.get("dev.uwsgi.celery", DEBUG):
     UWSGI["attach-daemon"].append("celery -A aleksis.core beat")
 
 DEFAULT_FAVICON_PATHS = {
-    "pwa_icon": os.path.join(STATIC_ROOT, "img/aleksis-icon.png"),
+    "pwa_icon": os.path.join(STATIC_ROOT, "img/aleksis-icon-maskable.png"),
     "favicon": os.path.join(STATIC_ROOT, "img/aleksis-favicon.png"),
 }
 PWA_ICONS_CONFIG = {
diff --git a/aleksis/core/static/img/aleksis-icon-maskable.png b/aleksis/core/static/img/aleksis-icon-maskable.png
new file mode 100644
index 0000000000000000000000000000000000000000..6ec3bb2c04392e646c7d00c5ba3a316ebf99486e
Binary files /dev/null and b/aleksis/core/static/img/aleksis-icon-maskable.png differ
diff --git a/aleksis/core/static/img/aleksis-icon-maskable.svg b/aleksis/core/static/img/aleksis-icon-maskable.svg
new file mode 100644
index 0000000000000000000000000000000000000000..e37f3c3606d748039e4dc03cc4b0f27f5de491e1
--- /dev/null
+++ b/aleksis/core/static/img/aleksis-icon-maskable.svg
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   id="svg8"
+   width="256"
+   height="256"
+   version="1.1"
+   viewBox="0 0 67.73 67.73"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:dc="http://purl.org/dc/elements/1.1/">
+  <title
+     id="title32">AlekSIS icon</title>
+  <defs
+     id="defs2">
+    <linearGradient
+       id="shadow-gradient"
+       x1="-19.53"
+       x2="165.4"
+       y1="-19.53"
+       y2="165.4"
+       gradientUnits="userSpaceOnUse"
+       gradientTransform="matrix(0.2646,0,0,0.2646,109.82466,-4.9393086)">
+      <stop
+         id="stop9444"
+         offset="0" />
+      <stop
+         id="stop9446"
+         stop-opacity="0"
+         offset="1" />
+    </linearGradient>
+  </defs>
+  <metadata
+     id="metadata5">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title>AlekSIS icon</dc:title>
+        <cc:license
+           rdf:resource="http://creativecommons.org/licenses/by-sa/4.0/" />
+        <dc:date>2020-02-29</dc:date>
+        <dc:creator>
+          <cc:Agent>
+            <dc:title>Dominik George</dc:title>
+          </cc:Agent>
+        </dc:creator>
+        <dc:contributor>
+          <cc:Agent>
+            <dc:title>Julian Leucker</dc:title>
+          </cc:Agent>
+        </dc:contributor>
+      </cc:Work>
+      <cc:License
+         rdf:about="http://creativecommons.org/licenses/by-sa/4.0/">
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Reproduction" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#Distribution" />
+        <cc:requires
+           rdf:resource="http://creativecommons.org/ns#Notice" />
+        <cc:requires
+           rdf:resource="http://creativecommons.org/ns#Attribution" />
+        <cc:permits
+           rdf:resource="http://creativecommons.org/ns#DerivativeWorks" />
+        <cc:requires
+           rdf:resource="http://creativecommons.org/ns#ShareAlike" />
+      </cc:License>
+    </rdf:RDF>
+  </metadata>
+  <g
+     id="background-with-glow">
+    <rect
+       id="background"
+       y="-3.357e-6"
+       width="67.73"
+       height="67.73"
+       rx="3.307"
+       ry="3.307"
+       fill="#0d5eaf"
+       stroke-width=".4104" />
+    <path
+       id="glow"
+       transform="scale(.2646)"
+       d="m9.959 0.2578c-5.698 1.168-9.959 6.189-9.959 12.24v52.31a234.1 86.8 0 0 0 188.9 35.71 234.1 86.8 0 0 0 67.09-3.715v-84.3c0-4.319-2.17-8.112-5.482-10.36-0.01554-0.01049-0.03129-0.02083-0.04688-0.03125-0.2971-0.1993-0.6034-0.3849-0.918-0.5586-0.05211-0.02867-0.1037-0.05799-0.1562-0.08594-0.2939-0.1568-0.5968-0.3001-0.9043-0.4336-0.05654-0.02442-0.111-0.05257-0.168-0.07617-0.3308-0.1378-0.6709-0.2577-1.016-0.3672-0.03502-0.01105-0.06836-0.02636-0.1035-0.03711-0.3806-0.1172-0.7687-0.2158-1.164-0.2969h-236.1z"
+       fill="#fff"
+       opacity=".2"
+       stroke-width="1.551" />
+  </g>
+  <g
+     id="favicon-bag"
+     transform="translate(-46.809258,-7.6499461)"
+     display="none">
+    <use
+       xlink:href="#schoolbag"
+       transform="matrix(2.25,0,0,2.25,-30.62,0)"
+       fill="#ffffff"
+       x="0"
+       y="0"
+       width="100%"
+       height="100%"
+       id="use18" />
+  </g>
+  <g
+     id="widgets-with-shadow"
+     transform="matrix(0.62859773,0,0,0.63035889,12.536993,12.511931)"
+     style="stroke-width:1.58861">
+    <g
+       id="widgets"
+       fill="#ffffff"
+       style="stroke-width:2.18867">
+      <path
+         id="schoolbag"
+         d="m 44.52,19.7 h 10.45 a 0.4353,0.4353 0 0 1 0.4353,0.4353 v 3.917 A 0.4353,0.4353 0 0 1 54.97,24.4876 H 44.52 a 0.4353,0.4353 0 0 1 -0.4353,-0.4353 v -3.917 A 0.4353,0.4353 0 0 1 44.52,19.7 Z M 55.4,18.394 v -0.8705 a 0.4353,0.4353 0 0 0 -0.4353,-0.4353 h -10.45 a 0.4353,0.4353 0 0 0 -0.4353,0.4353 v 0.8705 a 0.4353,0.4353 0 0 0 0.4353,0.4353 h 10.45 A 0.4353,0.4353 0 0 0 55.4,18.394 Z m -14.8,10.01 v 0.8705 a 2.176,2.176 0 0 0 2.176,2.176 h 13.93 a 2.176,2.176 0 0 0 2.176,-2.176 V 28.404 a 0.4353,0.4353 0 0 0 -0.4353,-0.4353 h -17.41 a 0.4353,0.4353 0 0 0 -0.4353,0.4353 z m -0.8705,-7.4 v -1.741 a 0.4353,0.4353 0 0 0 -0.4353,-0.4353 h -0.8705 a 1.306,1.306 0 0 0 -1.306,1.306 v 0.8706 a 0.4353,0.4353 0 0 0 0.4353,0.4353 h 1.741 a 0.4353,0.4353 0 0 0 0.4353,-0.4353 z m -2.612,1.741 v 4.788 a 1.306,1.306 0 0 0 1.306,1.306 h 0.8705 a 0.4353,0.4353 0 0 0 0.4353,-0.4353 v -5.659 A 0.4353,0.4353 0 0 0 39.294,22.3094 h -1.741 a 0.4353,0.4353 0 0 0 -0.4353,0.4353 z m 22.63,0 v 5.659 a 0.4353,0.4353 0 0 0 0.4353,0.4353 h 0.8705 a 1.306,1.306 0 0 0 1.306,-1.306 v -4.788 A 0.4353,0.4353 0 0 0 61.924,22.31 h -1.741 a 0.4353,0.4353 0 0 0 -0.4353,0.4353 z m 2.612,-1.741 v -0.8706 a 1.306,1.306 0 0 0 -1.306,-1.306 H 60.183 a 0.4353,0.4353 0 0 0 -0.4353,0.4353 v 1.741 a 0.4353,0.4353 0 0 0 0.4353,0.4353 h 1.741 a 0.4353,0.4353 0 0 0 0.4353,-0.4353 z m -3.482,-6.203 v 11.86 a 0.4353,0.4353 0 0 1 -0.4353,0.4353 h -17.41 A 0.4353,0.4353 0 0 1 40.5969,26.661 v -11.86 a 6.42,6.42 0 0 1 6.42,-6.42 h 0.3809 A 0.1632,0.1632 0 0 0 47.561,8.2178 V 7.5105 a 2.179,2.179 0 0 1 2.229,-2.176 c 1.188,0.0282 2.124,1.028 2.124,2.217 v 0.6664 a 0.1632,0.1632 0 0 0 0.1632,0.1632 h 0.3809 a 6.42,6.42 0 0 1 6.42,6.42 z m -10.45,-6.583 a 0.1632,0.1632 0 0 0 0.1632,0.1632 h 2.285 A 0.1632,0.1632 0 0 0 51.0389,8.218 V 7.5404 c 0,-0.7306 -0.5978,-1.348 -1.328,-1.336 a 1.307,1.307 0 0 0 -1.283,1.306 z m -0.4353,4.081 a 1.741,1.741 0 1 0 1.741,-1.741 1.741,1.741 0 0 0 -1.741,1.741 z m 8.27,5.223 a 1.307,1.307 0 0 0 -1.306,-1.306 h -10.45 a 1.307,1.307 0 0 0 -1.306,1.306 v 6.529 a 1.307,1.307 0 0 0 1.306,1.306 h 10.45 a 1.307,1.307 0 0 0 1.306,-1.306 z"
+         stroke-width="0.0864368" />
+      <path
+         id="puzzle-ll"
+         d="m 8.484,37.13 c -1.759,0 -3.175,1.416 -3.175,3.175 v 18.89 c 0,1.759 1.416,3.175 3.175,3.175 h 18.93 c 1.759,0 3.175,-1.416 3.175,-3.175 v -18.89 c 0,-1.759 -1.416,-3.175 -3.175,-3.175 h -5.842 v 2.798 h -0.01188 c 0.0052,0.0528 0.01281,0.1048 0.01447,0.1586 0,2.002 -1.623,3.625 -3.625,3.625 -2.002,0 -3.625,-1.623 -3.625,-3.625 0.01013,-0.0551 0.02494,-0.1053 0.03669,-0.1586 H 14.32614 V 37.13 Z m 28.69,12.62 c 3e-6,2.002 -1.623,3.625 -3.625,3.625 -4.515,-0.8302 -3.163,-7.154 0,-7.251 2.002,0 3.625,1.623 3.625,3.625 z m -6.582,-3.623 h 2.798 v 7.247 h -2.798 z"
+         style="stroke-width:1.58861" />
+      <path
+         id="puzzle-lr"
+         d="m 37.31,59.24 c 0,1.759 1.416,3.175 3.175,3.175 h 18.89 c 1.759,0 3.175,-1.416 3.175,-3.175 V 40.31 c 0,-1.759 -1.416,-3.175 -3.175,-3.175 h -18.89 c -1.759,0 -3.175,1.416 -3.175,3.175 v 5.842 h 2.798 v 0.0119 c 0.0528,-0.005 0.1048,-0.0128 0.1586,-0.0145 2.002,0 3.625,1.623 3.625,3.625 0,2.002 -1.623,3.625 -3.625,3.625 -0.0551,-0.0101 -0.1053,-0.0249 -0.1586,-0.0367 v 0.0351 H 37.31 Z"
+         style="stroke-width:1.58861" />
+      <path
+         id="puzzle-ul"
+         d="m 31.48,20.23 c 0.9818,-0.9818 0.9818,-2.563 0,-3.544 L 20.94,6.146 c -0.9818,-0.9819 -2.563,-0.9819 -3.545,0 l -10.57,10.57 c -0.9818,0.9818 -0.9818,2.563 6e-6,3.544 l 10.54,10.54 c 0.9818,0.9819 2.563,0.9819 3.545,0 l 3.261,-3.261 -1.562,-1.562 0.0064,-0.0069 c -0.03229,-0.02696 -0.06563,-0.05145 -0.09668,-0.08057 -1.118,-1.118 -1.118,-2.93 0,-4.048 1.118,-1.118 2.93,-1.118 4.048,0 0.02514,0.0363 0.04485,0.07241 0.0681,0.109 l 0.0196,-0.01948 1.562,1.562 z M 8.42,29.199 c -1.118,-1.118 -1.118,-2.93 -6.1e-6,-4.048 2.9840001,-2.057 5.7590001,2.228 4.0480001,4.048 -1.118,1.118 -2.9300001,1.118 -4.0480001,0 z m 5.697,-1.652 -1.562,1.562 -4.045,-4.045 1.562,-1.562 z"
+         style="stroke-width:1.58861" />
+    </g>
+  </g>
+</svg>
diff --git a/aleksis/core/tasks.py b/aleksis/core/tasks.py
index 13eb76444b77e84ca7509958f02517c98b678296..97ccfa2270b9d87ab8698414ce87c53f06446d22 100644
--- a/aleksis/core/tasks.py
+++ b/aleksis/core/tasks.py
@@ -40,3 +40,11 @@ def backup_data() -> None:
     # Hand off to dbbackup's management commands
     management.call_command("dbbackup", *db_options)
     management.call_command("mediabackup", *media_options)
+
+
+@app.task(run_every=timedelta(days=1))
+def clear_oauth_tokens():
+    """Clear expired OAuth2 tokens."""
+    from oauth2_provider.models import clear_tokens  # noqa
+
+    return clear_tokens()
diff --git a/aleksis/core/templates/core/base_print.html b/aleksis/core/templates/core/base_print.html
index d0b7cf6dd054a07e2e2efea7b1ce40176804c952..ed2a0c200c3798311db66980f3391b52ed67600e 100644
--- a/aleksis/core/templates/core/base_print.html
+++ b/aleksis/core/templates/core/base_print.html
@@ -5,6 +5,8 @@
 <!DOCTYPE html>
 <html lang="{{ LANGUAGE_CODE }}">
 <head>
+  <base href="{{ BASE_URL }}" />
+
   {% include "core/partials/meta.html" %}
 
   <title>
diff --git a/aleksis/core/templates/core/partials/meta.html b/aleksis/core/templates/core/partials/meta.html
index cae0f93b801ab0157f61bbe319067ac49979002c..30b2ef099f0914f8ab68df34c047732293d91d5b 100644
--- a/aleksis/core/templates/core/partials/meta.html
+++ b/aleksis/core/templates/core/partials/meta.html
@@ -6,7 +6,7 @@
 <meta name="description" content="{{ SITE_PREFERENCES.general__description }}"/>
 <meta name="generator" content="AlekSIS School Information System"/>
 
-<meta name="theme-color" content="red">
+<meta name="theme-color" content="{{ SITE_PREFERENCES.theme__primary }}">
 <meta name="mobile-web-app-capable" content="yes">
 
 <meta name="apple-mobile-web-app-title" content="{{ SITE_PREFERENCES.general__title }}">
diff --git a/aleksis/core/tests/regression/test_regression.py b/aleksis/core/tests/regression/test_regression.py
index 7ac541531db385ea8e28b454dc487458a45d7a66..b9d33e6981312817324b92d4fe67176b96763cda 100644
--- a/aleksis/core/tests/regression/test_regression.py
+++ b/aleksis/core/tests/regression/test_regression.py
@@ -1,3 +1,12 @@
+from django.contrib.auth import get_user_model
+
+import pytest
+
+from aleksis.core.models import Group, Person
+
+pytestmark = pytest.mark.django_db
+
+
 def test_all_settigns_registered():
     """Tests for regressions of preferences not being registered.
 
@@ -33,3 +42,43 @@ def test_custom_managers_return_correct_qs():
         assert isinstance(Manager.from_queryset(QuerySet)().get_queryset(), QuerySet)
 
     _check_get_queryset(managers.GroupManager, managers.GroupQuerySet)
+
+
+def test_reassign_user_to_person():
+    """Tests that on re-assigning a user, groups are correctly synced.
+
+    https://edugit.org/AlekSIS/official/AlekSIS-Core/-/issues/628
+    """
+
+    User = get_user_model()
+
+    group1 = Group.objects.create(name="Group 1")
+    group2 = Group.objects.create(name="Group 2")
+
+    user1 = User.objects.create(username="user1")
+    user2 = User.objects.create(username="user2")
+
+    person1 = Person.objects.create(first_name="Person", last_name="1", user=user1)
+    person2 = Person.objects.create(first_name="Person", last_name="2", user=user2)
+
+    person1.member_of.set([group1])
+    person2.member_of.set([group2])
+
+    assert user1.groups.count() == 1
+    assert user2.groups.count() == 1
+    assert user1.groups.first().name == "Group 1"
+    assert user2.groups.first().name == "Group 2"
+
+    person1.user = None
+    person1.save()
+    assert user1.groups.count() == 0
+
+    person2.user = user1
+    person2.save()
+    person1.user = user2
+    person1.save()
+
+    assert user1.groups.count() == 1
+    assert user2.groups.count() == 1
+    assert user1.groups.first().name == "Group 2"
+    assert user2.groups.first().name == "Group 1"
diff --git a/aleksis/core/util/core_helpers.py b/aleksis/core/util/core_helpers.py
index 148d33594d2cc0a2619a1c1a64c3b8fa69dad79c..fc83b605032013b7d0dbee06ce0b1ef8193c177d 100644
--- a/aleksis/core/util/core_helpers.py
+++ b/aleksis/core/util/core_helpers.py
@@ -216,6 +216,7 @@ def custom_information_processor(request: Union[HttpRequest, None]) -> dict:
         "PWA_ICONS": regrouped_pwa_icons,
         "SENTRY_ENABLED": settings.SENTRY_ENABLED,
         "SITE_PREFERENCES": get_site_preferences(),
+        "BASE_URL": settings.BASE_URL,
     }
 
     if settings.SENTRY_ENABLED:
@@ -389,3 +390,54 @@ def create_default_celery_schedule():
         PeriodicTask.objects.create(
             name=f"{name} (default schedule)", task=name, **{attr: db_schedule}
         )
+
+
+class OOTRouter:
+    """Database router for operations that should run out of transaction.
+
+    This router routes database operations for certain apps through
+    the separate default_oot connection, to ensure that data get
+    updated immediately even during atomic transactions.
+    """
+
+    default_db = "default"
+    oot_db = "default_oot"
+
+    @property
+    def oot_labels(self):
+        return settings.DATABASE_OOT_LABELS
+
+    @property
+    def default_dbs(self):
+        return set((self.default_db, self.oot_db))
+
+    def is_same_db(self, db1: str, db2: str):
+        return set((db1, db2)).issubset(self.default_dbs)
+
+    def db_for_read(self, model: Model, **hints) -> Optional[str]:
+        if model._meta.app_label in self.oot_labels:
+            return self.oot_db
+
+        return None
+
+    def db_for_write(self, model: Model, **hints) -> Optional[str]:
+        return self.db_for_read(model, **hints)
+
+    def allow_relation(self, obj1: Model, obj2: Model, **hints) -> Optional[bool]:
+        # Allow relations between default database and OOT connection
+        # They are the same database
+        if self.is_same_db(obj1._state.db, obj2._state.db):
+            return True
+
+        return None
+
+    def allow_migrate(
+        self, db: str, app_label: str, model_name: Optional[str] = None, **hints
+    ) -> Optional[bool]:
+        # Never allow any migrations on the default_oot database
+        # It connects to the same database as default, so everything
+        # migrated there
+        if db == self.oot_db:
+            return False
+
+        return None
diff --git a/aleksis/core/util/email.py b/aleksis/core/util/email.py
index fc7525a7d64e50ec1045dacf02d253ed13b17568..eae0e584604aa4e7141edcb6b244a2e1a079a762 100644
--- a/aleksis/core/util/email.py
+++ b/aleksis/core/util/email.py
@@ -15,7 +15,7 @@ def send_email(
     **kwargs,
 ):
     """Send templated email with data from context processors."""
-    processed_context = process_custom_context_processors(settings.PDF_CONTEXT_PROCESSORS)
+    processed_context = process_custom_context_processors(settings.NON_REQUEST_CONTEXT_PROCESSORS)
     processed_context.update(context)
     if not from_email:
         from_address = get_site_preferences()["mail__address"]
diff --git a/aleksis/core/util/pdf.py b/aleksis/core/util/pdf.py
index d65000811b123eab7ce6ad7e7ce29b02c3d73b06..a261017b3b2bb22decea1cc517b414858b14a68c 100644
--- a/aleksis/core/util/pdf.py
+++ b/aleksis/core/util/pdf.py
@@ -1,5 +1,6 @@
 import os
 import subprocess  # noqa
+from datetime import timedelta
 from tempfile import TemporaryDirectory
 from typing import Optional, Tuple, Union
 from urllib.parse import urljoin
@@ -73,13 +74,17 @@ def generate_pdf_from_template(
 ) -> Tuple[PDFFile, AsyncResult]:
     """Start a PDF generation task and return the matching file object and Celery result."""
     if not request:
-        processed_context = process_custom_context_processors(settings.PDF_CONTEXT_PROCESSORS)
+        processed_context = process_custom_context_processors(
+            settings.NON_REQUEST_CONTEXT_PROCESSORS
+        )
         processed_context.update(context)
     else:
         processed_context = context
     html_template = render_to_string(template_name, processed_context, request)
 
-    file_object = PDFFile.objects.create(html_file=ContentFile(html_template, name="source.html"))
+    file_object = PDFFile.objects.create(
+        html_file=ContentFile(html_template.encode(), name="source.html")
+    )
 
     # As this method may be run in background and there is no request available,
     # we have to use a predefined URL from settings then
@@ -127,7 +132,7 @@ def clean_up_expired_pdf_files() -> None:
     PDFFile.objects.filter(expires_at__lt=timezone.now()).delete()
 
 
-@app.task
+@app.task(run_every=timedelta(days=1))
 def clean_up_expired_pdf_files_task() -> None:
     """Clean up expired PDF files."""
     return clean_up_expired_pdf_files()
diff --git a/aleksis/core/views.py b/aleksis/core/views.py
index ec38875ad876f6cc7f6b8943a70254a28704195b..539807bf19434b3ae812afe9fa8f317063be8654 100644
--- a/aleksis/core/views.py
+++ b/aleksis/core/views.py
@@ -175,6 +175,7 @@ class ManifestView(View):
             {
                 "src": favicon_img.faviconImage.url,
                 "sizes": f"{favicon_img.size}x{favicon_img.size}",
+                "purpose": "maskable" if prefs["theme__pwa_icon_maskable"] else "any",
             }
             for favicon_img in pwa_imgs
         ]
diff --git a/docker-startup.sh b/docker-startup.sh
index 1e02ce1d4bfdbd4373e93da8e2bd3f0c1ae02d56..776b13310b1078da8d2687dd5a4af8c146c3c0df 100755
--- a/docker-startup.sh
+++ b/docker-startup.sh
@@ -48,7 +48,11 @@ wait_database() {
 
 prepare_database() {
 	# Migrate database; should only be run in app container or job
-	aleksis-admin migrate && aleksis-admin createinitialrevisions
+	if aleksis-admin migrate --check >/dev/null 2>&1; then
+		aleksis-admin migrate && \
+		aleksis-admin clear_cache && \
+		aleksis-admin createinitialrevisions
+	fi
 }
 
 # Wait for database to be reachable under all conditions
diff --git a/docs/_static/accept_invite.png b/docs/_static/accept_invite.png
new file mode 100644
index 0000000000000000000000000000000000000000..598839ab61686ef58cc979ce2cc437b093f9e456
Binary files /dev/null and b/docs/_static/accept_invite.png differ
diff --git a/docs/_static/invitations.png b/docs/_static/invitations.png
new file mode 100644
index 0000000000000000000000000000000000000000..07cb25b9b1b741cd9a37aa07385b283c6c2805fe
Binary files /dev/null and b/docs/_static/invitations.png differ
diff --git a/docs/_static/invite_existing.png b/docs/_static/invite_existing.png
new file mode 100644
index 0000000000000000000000000000000000000000..6ae7c7b819fd43e3dc3bd5b35dc204a1661a1eca
Binary files /dev/null and b/docs/_static/invite_existing.png differ
diff --git a/docs/_static/signup.png b/docs/_static/signup.png
new file mode 100644
index 0000000000000000000000000000000000000000..cb60572b41a58327f366f7d9db665f6618220554
Binary files /dev/null and b/docs/_static/signup.png differ
diff --git a/docs/admin/17_storage.rst b/docs/admin/17_storage.rst
index 96b789b36d30e7d0014bc19df091b86d1433118a..f4a7f6130735644298207edc290ee72ddb4f2d65 100644
--- a/docs/admin/17_storage.rst
+++ b/docs/admin/17_storage.rst
@@ -28,6 +28,12 @@ AlekSIS allows you to configure an Amazon S3 endpoint for  media
 files. This is useful e.g. for loadbalancing with multiple AlekSIS
 instances.
 
+.. note::
+   For some background jobs, AlekSIS stores HTML snippets in the media
+   storage for later use. You must ensure your S3 endpoint is part of
+   your ``Access-Control-Allow-Origin`` CORS header, so HTML loaded from
+   there can load resources from the ALekSIS instance.
+
 Configure an S3 endpoint
 ~~~~~~~~~~~~~~~~~~~~~~~~
 
diff --git a/docs/admin/18_mail.rst b/docs/admin/18_mail.rst
new file mode 100644
index 0000000000000000000000000000000000000000..60e02d1c72a62d9e90ce438a9595e1de54e5f08b
--- /dev/null
+++ b/docs/admin/18_mail.rst
@@ -0,0 +1,36 @@
+Mail
+====
+
+AlekSIS needs to send mails e.g. for account confirmations, feedback or
+error reports.
+
+Configure mailing
+-----------------
+
+The mailserver can be configured via the configuration file
+
+.. code-block:: toml
+
+	[mail.server]
+	host = "mail.example.com"
+	tls = False
+	ssl = True
+	port = 25
+	user = "mailuser"
+	password = "password"
+
+Name and address for mails sent by AlekSIS can be configured in the
+webinterface.  To configure, visit `Admin → Configuration` and click on the
+`Mail` tab.
+
+Configure mail recipients
+-------------------------
+
+You can configure admin contacts in your configuration file, located at
+``/etc/aleksis/``.
+
+.. code-blocK:: toml
+
+	[contact]
+	admins = [["AlekSIS - Admins", "root@example.com"],["AlekSIS - Admins2", "root2@example.com"]]
+	from = 'aleksis@example.com'
diff --git a/docs/admin/22_registration.rst b/docs/admin/22_registration.rst
new file mode 100644
index 0000000000000000000000000000000000000000..2442b5ce6c59314928fb3f6504b2db51eaa02010
--- /dev/null
+++ b/docs/admin/22_registration.rst
@@ -0,0 +1,82 @@
+Registration and user invitations
+=================================
+
+In addition to central management of user accounts, AlekSIS allows self-registration
+by users. Registration can be either fully open, or based on personal invitations.
+
+In a system handling ciritcal data, access control should be as tight as possible.
+However, there are scenarios where central account creation is not feasible, e.g.
+for optional guardian accounts. In such a scenario, the invitation system allows
+for processes like handing out invitation codes as a letter or through e-mail
+campaigns.
+
+Configuration
+-------------
+
+.. _core-registration:
+
+Registration
+~~~~~~~~~~~~
+
+Registration can be enabled via the configuration interface in frontend.
+
+In the ``Authentication`` tab, click the checkbox ``Enable signup`` to enable
+signup for everyone. A menu item will be added for public registration.
+
+.. warning::
+   Do not enable this feature unless you intend to run a public AlekSIS instance.
+
+User invitations
+~~~~~~~~~~~~~~~~
+
+.. _core-user-invitations:
+
+In the same location as public registration, the invitation system can be enabled.
+
+* Authentication
+
+  * Enable invitations: Click to enable invitations.
+  * Length of invite code: Length of invitation code packets, defaults to 5.
+  * Size of packets: Configure how many packets are generated, defaults to 3.
+
+By default, an invitation code looks like the following:
+``abcde-abcde-abcde``.
+
+A menu item will become available for users to enter their invitation code.
+
+Usage
+-----
+
+Invite by email or code
+~~~~~~~~~~~~~~~~~~~~~~~
+
+To invite a new user , visit the invitation page located at ``People → Invite
+person``
+
+Here you are able to invite the user by email address or generate an
+invitation code.
+
+.. image:: ../_static/invitations.png
+  :width: 100%
+  :alt: Invitations page
+
+This mechanism allows for registration of entirely new persons that do not
+exist in the system, e.g. if perosnal details are not known in advance.
+
+Invite existing person
+~~~~~~~~~~~~~~~~~~~~~~
+
+To invite an existing person, open the person in AlekSIS and click ``Invite
+user``.
+
+The invitation will be sent to the person's email address, and can only
+be used by this person. Upon registration, the new account will automatically
+be linked to the existing person.
+
+.. image:: ../_static/invite_existing.png
+  :width: 100%
+  :alt: Invite existing person
+
+.. note::
+   Before using this feature, make sure to read and understand
+   :ref:`core-concept-person`.
diff --git a/docs/conf.py b/docs/conf.py
index 55931744c0714ae7b52ef4b2e14dc50af236c811..b4ae8848dea26ac31ba2c8e964475666ce569884 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -29,9 +29,9 @@ copyright = "2019-2022 The AlekSIS team"
 author = "The AlekSIS Team"
 
 # The short X.Y version
-version = "2.6"
+version = "2.7"
 # The full version, including alpha/beta/rc tags
-release = "2.6.1.dev0"
+release = "2.7.3.dev0"
 
 
 # -- General configuration ---------------------------------------------------
diff --git a/docs/user/01_registration.rst b/docs/user/01_registration.rst
new file mode 100644
index 0000000000000000000000000000000000000000..3beb4fb51621af47b97a51a1cb6719773249ecf7
--- /dev/null
+++ b/docs/user/01_registration.rst
@@ -0,0 +1,36 @@
+Register a new account
+======================
+
+.. _core-user-registration:
+
+Public registration
+-------------------
+
+If public registration is enabled on the AlekSIS instance, you can click the
+``Signup`` button located in the navigation sidebar and register for an
+AlekSIS account.
+
+.. image:: ../_static/signup.png
+  :width: 100%
+  :alt: Signup formular
+
+If enabled, you have to verify your email address after signup. To do so, click
+on the link you recieved on the email address you entered in the signup form.
+
+.. note::
+   Normally, AlekSIS does not allow public registratio, and all accounts are
+   centrally managed by administrators. Public registration is an optional
+   feature that has to be enabled by adminsitrators after careful consideration.
+
+Using an invitation code
+------------------------
+
+If you have an invitation code, click ``Accept invitation`` in the sidebar and
+enter it. You will be redirected to the signup form.
+
+.. image:: ../_static/accept_invite.png
+  :width: 100%
+  :alt: Accept invitation
+
+If you've recieved an invitation link (e.g. via email), clicking the link
+will redirect you to the signup form automatically.
diff --git a/docs/user/01_personal_account.rst b/docs/user/02_personal_account.rst
similarity index 100%
rename from docs/user/01_personal_account.rst
rename to docs/user/02_personal_account.rst
diff --git a/docs/user/02_dashboard.rst b/docs/user/10_dashboard.rst
similarity index 100%
rename from docs/user/02_dashboard.rst
rename to docs/user/10_dashboard.rst
diff --git a/pyproject.toml b/pyproject.toml
index 8254a6a2a05a9790ea3babfad998f58636cce6f1..8e33c935254407385a114b1bf530a336dc6b9ee3 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
 [tool.poetry]
 name = "AlekSIS-Core"
-version = "2.6.1.dev0"
+version = "2.7.3.dev0"
 packages = [
     { include = "aleksis" }
 ]
@@ -113,11 +113,11 @@ django-allauth = "^0.47.0"
 django-uwsgi-ng = "^1.1.0"
 django-extensions = "^3.1.1"
 ipython = "^8.0.0"
-django-oauth-toolkit = "^1.6.2"
+django-oauth-toolkit = "^1.7.0"
 django-redis = "^5.0.0"
 django-storages = {version = "^1.11.1", optional = true}
 boto3 = {version = "^1.17.33", optional = true}
-django-cleanup = "^5.1.0"
+django-cleanup = "^6.0.0"
 djangorestframework = "^3.12.4"
 Whoosh = "^2.7.4"
 django-titofisto = "^0.2.0"