diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index df96ee2ea76ac310826bf8552ef99c6a853ba994..fbc4a5f64d562986675178c00c965bd9332455fa 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -12,13 +12,38 @@ Unreleased
 Added
 ~~~~~
 
+* Provide an ``ExtensiblePolymorphicModel`` to support the features of extensible models for polymorphic models and vice-versa.
 * Implement optional Sentry integration for error and performance tracing.
 
+Changed
+~~~~~~~
+
+* Replace dev.sh helper script with tox environments.
+
+`2.0`_ - 2021-10-29
+-------------------
+
+Changed
+~~~~~~~
+
+* Refactor views/forms for creating/editing persons.
+
 Fixed
 ~~~~~
 
 * Fix order of submit buttons in login form and restructure login template
   to make 2FA work correctly.
+* Fix page title bug on the impersonate page.
+* Users were able to edit the linked user if self-editing was activated.
+* Users weren't able to edit the allowed fields although they were configured correctly.
+* Provide `style.css` and icon files without any authentication to avoid caching issues.
+
+
+Removed
+~~~~~~~
+
+* Remove mass linking of persons to accounts, bevcause the view had performance issues,
+  but was practically unused.
 
 `2.0rc7`_ - 2021-10-18
 ----------------------
@@ -399,3 +424,4 @@ Fixed
 .. _2.0rc5: https://edugit.org/AlekSIS/Official/AlekSIS/-/tags/2.0rc5
 .. _2.0rc6: https://edugit.org/AlekSIS/Official/AlekSIS/-/tags/2.0rc6
 .. _2.0rc7: https://edugit.org/AlekSIS/Official/AlekSIS/-/tags/2.0rc7
+.. _2.0: https://edugit.org/AlekSIS/Official/AlekSIS/-/tags/2.0
diff --git a/aleksis/core/forms.py b/aleksis/core/forms.py
index 642364b1b331f37720bdbb5798ac20b33786b79b..740fd24b3b5d82c1df5c50d2ad78aa7d71a92292 100644
--- a/aleksis/core/forms.py
+++ b/aleksis/core/forms.py
@@ -13,7 +13,6 @@ from allauth.account.forms import SignupForm
 from allauth.account.utils import get_user_model, setup_user_email
 from django_select2.forms import ModelSelect2MultipleWidget, ModelSelect2Widget, Select2Widget
 from dynamic_preferences.forms import PreferenceForm
-from guardian.core import ObjectPermissionChecker
 from material import Fieldset, Layout, Row
 
 from .mixins import ExtensibleForm, SchoolTermRelatedExtensibleForm
@@ -34,56 +33,8 @@ from .registries import (
 from .util.core_helpers import get_site_preferences
 
 
-class PersonAccountForm(forms.ModelForm):
-    """Form to assign user accounts to persons in the frontend."""
-
-    class Meta:
-        model = Person
-        fields = ["last_name", "first_name", "user"]
-        widgets = {"user": Select2Widget(attrs={"class": "browser-default"})}
-
-    new_user = forms.CharField(required=False)
-
-    def __init__(self, *args, **kwargs):
-        super().__init__(*args, **kwargs)
-
-        # Fields displayed only for informational purposes
-        self.fields["first_name"].disabled = True
-        self.fields["last_name"].disabled = True
-
-    def clean(self) -> None:
-        user = get_user_model()
-
-        if self.cleaned_data.get("new_user", None):
-            if self.cleaned_data.get("user", None):
-                # The user selected both an existing user and provided a name to create a new one
-                self.add_error(
-                    "new_user",
-                    _("You cannot set a new username when also selecting an existing user."),
-                )
-            elif user.objects.filter(username=self.cleaned_data["new_user"]).exists():
-                # The user tried to create a new user with the name of an existing user
-                self.add_error("new_user", _("This username is already in use."))
-            else:
-                # Create new User object and assign to form field for existing user
-                new_user_obj = user.objects.create_user(
-                    self.cleaned_data["new_user"],
-                    self.instance.email,
-                    first_name=self.instance.first_name,
-                    last_name=self.instance.last_name,
-                )
-
-                self.cleaned_data["user"] = new_user_obj
-
-
-# Formset for batch-processing of assignments of users to persons
-PersonsAccountsFormSet = forms.modelformset_factory(
-    Person, form=PersonAccountForm, max_num=0, extra=0
-)
-
-
-class EditPersonForm(ExtensibleForm):
-    """Form to edit an existing person object in the frontend."""
+class PersonForm(ExtensibleForm):
+    """Form to edit or add a person object in the frontend."""
 
     layout = Layout(
         Fieldset(
@@ -142,25 +93,49 @@ class EditPersonForm(ExtensibleForm):
         required=False, label=_("New user"), help_text=_("Create a new account")
     )
 
-    def __init__(self, request: HttpRequest, *args, **kwargs):
+    def __init__(self, *args, **kwargs):
+        request = kwargs.pop("request", None)
         super().__init__(*args, **kwargs)
 
         # Disable non-editable fields
-        person_fields = set([field.name for field in Person.syncable_fields()]).intersection(
-            set(self.fields)
-        )
+        allowed_person_fields = get_site_preferences()["account__editable_fields_person"]
 
-        if self.instance:
-            checker = ObjectPermissionChecker(request.user)
-            checker.prefetch_perms([self.instance])
+        if (
+            request
+            and self.instance
+            and not request.user.has_perm("core.change_person", self.instance)
+        ):
+            # First, disable all fields
+            for field in self.fields:
+                self.fields[field].disabled = True
 
-            for field in person_fields:
-                if not checker.has_perm(f"core.change_person_field_{field}", self.instance):
-                    self.fields[field].disabled = True
+            # Then, activate allowed fields
+            for field in allowed_person_fields:
+                self.fields[field].disabled = False
 
     def clean(self) -> None:
-        # Use code implemented in dedicated form to verify user selection
-        return PersonAccountForm.clean(self)
+        user = get_user_model()
+
+        if self.cleaned_data.get("new_user", None):
+            if self.cleaned_data.get("user", None):
+                # The user selected both an existing user and provided a name to create a new one
+                self.add_error(
+                    "new_user",
+                    _("You cannot set a new username when also selecting an existing user."),
+                )
+            elif user.objects.filter(username=self.cleaned_data["new_user"]).exists():
+                # The user tried to create a new user with the name of an existing user
+                self.add_error("new_user", _("This username is already in use."))
+            else:
+                # Create new User object and assign to form field for existing user
+                new_user_obj = user.objects.create_user(
+                    self.cleaned_data["new_user"],
+                    self.instance.email,
+                    first_name=self.instance.first_name,
+                    last_name=self.instance.last_name,
+                )
+
+                self.cleaned_data["user"] = new_user_obj
 
 
 class EditGroupForm(SchoolTermRelatedExtensibleForm):
diff --git a/aleksis/core/locale/ar/LC_MESSAGES/django.po b/aleksis/core/locale/ar/LC_MESSAGES/django.po
index ef5a6607f526523fb1ba3ca7f43e08ab21629c62..29ee921af8694936e102e32d65b310ac44979fbc 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: 2021-08-28 17:53+0200\n"
+"POT-Creation-Date: 2021-10-28 16:18+0200\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,23 +18,23 @@ 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:148 aleksis/core/settings.py:343
+#: aleksis/core/apps.py:150
 msgid "OpenID Connect scope"
 msgstr ""
 
-#: aleksis/core/apps.py:149 aleksis/core/settings.py:344
+#: aleksis/core/apps.py:151
 msgid "Given name, family name, link to profile and picture if existing."
 msgstr ""
 
-#: aleksis/core/apps.py:150 aleksis/core/settings.py:345
+#: aleksis/core/apps.py:152
 msgid "Full home postal address"
 msgstr ""
 
-#: aleksis/core/apps.py:151 aleksis/core/settings.py:346
+#: aleksis/core/apps.py:153
 msgid "Email address"
 msgstr ""
 
-#: aleksis/core/apps.py:152 aleksis/core/settings.py:347
+#: aleksis/core/apps.py:154
 msgid "Home and mobile phone"
 msgstr ""
 
@@ -76,124 +76,124 @@ msgstr ""
 msgid "Search by contact details"
 msgstr ""
 
-#: aleksis/core/forms.py:62
-msgid "You cannot set a new username when also selecting an existing user."
-msgstr ""
-
-#: aleksis/core/forms.py:66
-msgid "This username is already in use."
-msgstr ""
-
-#: aleksis/core/forms.py:90 aleksis/core/forms.py:412
+#: aleksis/core/forms.py:41 aleksis/core/forms.py:387
 msgid "Base data"
 msgstr ""
 
-#: aleksis/core/forms.py:96
+#: aleksis/core/forms.py:47
 msgid "Address"
 msgstr ""
 
-#: aleksis/core/forms.py:97
+#: aleksis/core/forms.py:48
 msgid "Contact data"
 msgstr ""
 
-#: aleksis/core/forms.py:99
+#: aleksis/core/forms.py:50
 msgid "Advanced personal data"
 msgstr ""
 
-#: aleksis/core/forms.py:142
+#: aleksis/core/forms.py:93
 msgid "New user"
 msgstr ""
 
-#: aleksis/core/forms.py:142
+#: aleksis/core/forms.py:93
 msgid "Create a new account"
 msgstr ""
 
-#: aleksis/core/forms.py:170 aleksis/core/models.py:116
+#: aleksis/core/forms.py:124
+msgid "You cannot set a new username when also selecting an existing user."
+msgstr ""
+
+#: aleksis/core/forms.py:128
+msgid "This username is already in use."
+msgstr ""
+
+#: aleksis/core/forms.py:145 aleksis/core/models.py:117
 msgid "School term"
 msgstr ""
 
-#: aleksis/core/forms.py:171
+#: aleksis/core/forms.py:146
 msgid "Common data"
 msgstr ""
 
-#: aleksis/core/forms.py:172 aleksis/core/forms.py:221
-#: aleksis/core/menus.py:238 aleksis/core/models.py:139
+#: aleksis/core/forms.py:147 aleksis/core/forms.py:196
+#: aleksis/core/menus.py:238 aleksis/core/models.py:140
 #: aleksis/core/templates/core/person/list.html:8
 #: aleksis/core/templates/core/person/list.html:9
 msgid "Persons"
 msgstr ""
 
-#: aleksis/core/forms.py:173
+#: aleksis/core/forms.py:148
 msgid "Additional data"
 msgstr ""
 
-#: aleksis/core/forms.py:213 aleksis/core/forms.py:216
-#: aleksis/core/models.py:59
+#: aleksis/core/forms.py:188 aleksis/core/forms.py:191
+#: aleksis/core/models.py:60
 msgid "Date"
 msgstr ""
 
-#: aleksis/core/forms.py:214 aleksis/core/forms.py:217
-#: aleksis/core/models.py:67
+#: aleksis/core/forms.py:189 aleksis/core/forms.py:192
+#: aleksis/core/models.py:68
 msgid "Time"
 msgstr ""
 
-#: aleksis/core/forms.py:234 aleksis/core/menus.py:249
-#: aleksis/core/models.py:381 aleksis/core/templates/core/group/list.html:8
+#: aleksis/core/forms.py:209 aleksis/core/menus.py:249
+#: aleksis/core/models.py:398 aleksis/core/templates/core/group/list.html:8
 #: aleksis/core/templates/core/group/list.html:9
 #: aleksis/core/templates/core/person/full.html:144
 msgid "Groups"
 msgstr ""
 
-#: aleksis/core/forms.py:244
+#: aleksis/core/forms.py:219
 msgid "From when until when should the announcement be displayed?"
 msgstr ""
 
-#: aleksis/core/forms.py:247
+#: aleksis/core/forms.py:222
 msgid "Who should see the announcement?"
 msgstr ""
 
-#: aleksis/core/forms.py:248
+#: aleksis/core/forms.py:223
 msgid "Write your announcement:"
 msgstr ""
 
-#: aleksis/core/forms.py:287
+#: aleksis/core/forms.py:262
 msgid "You are not allowed to create announcements which are only valid in the past."
 msgstr ""
 
-#: aleksis/core/forms.py:291
+#: aleksis/core/forms.py:266
 msgid "The from date and time must be earlier then the until date and time."
 msgstr ""
 
-#: aleksis/core/forms.py:300
+#: aleksis/core/forms.py:275
 msgid "You need at least one recipient."
 msgstr ""
 
-#: aleksis/core/forms.py:414
+#: aleksis/core/forms.py:389
 msgid "Account data"
 msgstr ""
 
-#: aleksis/core/forms.py:416
+#: aleksis/core/forms.py:391
 msgid "Consents"
 msgstr ""
 
-#: aleksis/core/forms.py:421
+#: aleksis/core/forms.py:396
 msgid "Password"
 msgstr ""
 
-#: aleksis/core/forms.py:427
+#: aleksis/core/forms.py:402
 msgid "Password (again)"
 msgstr ""
 
-#: aleksis/core/forms.py:436
+#: aleksis/core/forms.py:411
 #, python-brace-format
 msgid "I have read the <a href='{privacy_policy}'>Privacy policy</a> and agree with them."
 msgstr ""
 
-#: aleksis/core/forms.py:460
+#: aleksis/core/forms.py:435
 msgid "You must type the same password each time."
 msgstr ""
 
-#: aleksis/core/forms.py:605
+#: aleksis/core/forms.py:580
 msgid "No valid selection."
 msgstr ""
 
@@ -224,8 +224,8 @@ msgid "{task.status} - {task.result}"
 msgstr ""
 
 #: aleksis/core/menus.py:9 aleksis/core/templates/two_factor/core/login.html:6
-#: aleksis/core/templates/two_factor/core/login.html:20
-#: aleksis/core/templates/two_factor/core/login.html:95
+#: aleksis/core/templates/two_factor/core/login.html:22
+#: aleksis/core/templates/two_factor/core/login.html:76
 msgid "Login"
 msgstr ""
 
@@ -238,7 +238,7 @@ msgstr ""
 msgid "Dashboard"
 msgstr ""
 
-#: aleksis/core/menus.py:32 aleksis/core/models.py:588
+#: aleksis/core/menus.py:32 aleksis/core/models.py:605
 #: aleksis/core/preferences.py:26
 #: aleksis/core/templates/core/notifications.html:4
 #: aleksis/core/templates/core/notifications.html:5
@@ -296,13 +296,13 @@ msgstr ""
 msgid "Admin"
 msgstr ""
 
-#: aleksis/core/menus.py:127 aleksis/core/models.py:687
+#: aleksis/core/menus.py:127 aleksis/core/models.py:704
 #: aleksis/core/templates/core/announcement/list.html:7
 #: aleksis/core/templates/core/announcement/list.html:8
 msgid "Announcements"
 msgstr ""
 
-#: aleksis/core/menus.py:138 aleksis/core/models.py:117
+#: aleksis/core/menus.py:138 aleksis/core/models.py:118
 #: aleksis/core/templates/core/school_term/list.html:8
 #: aleksis/core/templates/core/school_term/list.html:9
 msgid "School terms"
@@ -353,570 +353,561 @@ msgstr ""
 msgid "People"
 msgstr ""
 
-#: aleksis/core/menus.py:260 aleksis/core/models.py:941
+#: aleksis/core/menus.py:260 aleksis/core/models.py:958
 #: aleksis/core/templates/core/group_type/list.html:8
 #: aleksis/core/templates/core/group_type/list.html:9
 msgid "Group types"
 msgstr ""
 
 #: aleksis/core/menus.py:271
-msgid "Persons and accounts"
-msgstr ""
-
-#: aleksis/core/menus.py:282
 msgid "Groups and child groups"
 msgstr ""
 
-#: aleksis/core/menus.py:293 aleksis/core/models.py:429
+#: aleksis/core/menus.py:282 aleksis/core/models.py:446
 #: aleksis/core/templates/core/additional_field/list.html:8
 #: aleksis/core/templates/core/additional_field/list.html:9
 msgid "Additional fields"
 msgstr ""
 
-#: aleksis/core/menus.py:308
+#: aleksis/core/menus.py:297
 #: aleksis/core/templates/core/group/child_groups.html:7
 #: aleksis/core/templates/core/group/child_groups.html:9
 msgid "Assign child groups to groups"
 msgstr ""
 
-#: aleksis/core/mixins.py:475
+#: aleksis/core/mixins.py:498
 msgid "Linked school term"
 msgstr ""
 
-#: aleksis/core/models.py:57
+#: aleksis/core/models.py:58
 msgid "Boolean (Yes/No)"
 msgstr ""
 
-#: aleksis/core/models.py:58
+#: aleksis/core/models.py:59
 msgid "Text (one line)"
 msgstr ""
 
-#: aleksis/core/models.py:60
+#: aleksis/core/models.py:61
 msgid "Date and time"
 msgstr ""
 
-#: aleksis/core/models.py:61
+#: aleksis/core/models.py:62
 msgid "Decimal number"
 msgstr ""
 
-#: aleksis/core/models.py:62 aleksis/core/models.py:185
+#: aleksis/core/models.py:63 aleksis/core/models.py:186
 msgid "E-mail address"
 msgstr ""
 
-#: aleksis/core/models.py:63
+#: aleksis/core/models.py:64
 msgid "Integer"
 msgstr ""
 
-#: aleksis/core/models.py:64
+#: aleksis/core/models.py:65
 msgid "IP address"
 msgstr ""
 
-#: aleksis/core/models.py:65
+#: aleksis/core/models.py:66
 msgid "Boolean or empty (Yes/No/Neither)"
 msgstr ""
 
-#: aleksis/core/models.py:66
+#: aleksis/core/models.py:67
 msgid "Text (multi-line)"
 msgstr ""
 
-#: aleksis/core/models.py:68
+#: aleksis/core/models.py:69
 msgid "URL / Link"
 msgstr ""
 
-#: aleksis/core/models.py:80 aleksis/core/models.py:910
+#: aleksis/core/models.py:81 aleksis/core/models.py:927
 msgid "Name"
 msgstr ""
 
-#: aleksis/core/models.py:82
+#: aleksis/core/models.py:83
 msgid "Start date"
 msgstr ""
 
-#: aleksis/core/models.py:83
+#: aleksis/core/models.py:84
 msgid "End date"
 msgstr ""
 
-#: aleksis/core/models.py:102
+#: aleksis/core/models.py:103
 msgid "The start date must be earlier than the end date."
 msgstr ""
 
-#: aleksis/core/models.py:109
+#: aleksis/core/models.py:110
 msgid "There is already a school term for this time or a part of this time."
 msgstr ""
 
-#: aleksis/core/models.py:138 aleksis/core/models.py:859
-#: aleksis/core/templates/core/person/accounts.html:41
+#: aleksis/core/models.py:139 aleksis/core/models.py:876
 msgid "Person"
 msgstr ""
 
-#: aleksis/core/models.py:141
+#: aleksis/core/models.py:142
 msgid "Can view address"
 msgstr ""
 
-#: aleksis/core/models.py:142
+#: aleksis/core/models.py:143
 msgid "Can view contact details"
 msgstr ""
 
-#: aleksis/core/models.py:143
+#: aleksis/core/models.py:144
 msgid "Can view photo"
 msgstr ""
 
-#: aleksis/core/models.py:144
+#: aleksis/core/models.py:145
 msgid "Can view persons groups"
 msgstr ""
 
-#: aleksis/core/models.py:145
+#: aleksis/core/models.py:146
 msgid "Can view personal details"
 msgstr ""
 
-#: aleksis/core/models.py:155
+#: aleksis/core/models.py:156
 msgid "female"
 msgstr ""
 
-#: aleksis/core/models.py:155
+#: aleksis/core/models.py:156
 msgid "male"
 msgstr ""
 
-#: aleksis/core/models.py:163
+#: aleksis/core/models.py:164
 msgid "Linked user"
 msgstr ""
 
-#: aleksis/core/models.py:165
+#: aleksis/core/models.py:166
 msgid "Is person active?"
 msgstr ""
 
-#: aleksis/core/models.py:167
+#: aleksis/core/models.py:168
 msgid "First name"
 msgstr ""
 
-#: aleksis/core/models.py:168
+#: aleksis/core/models.py:169
 msgid "Last name"
 msgstr ""
 
-#: aleksis/core/models.py:170
+#: aleksis/core/models.py:171
 msgid "Additional name(s)"
 msgstr ""
 
-#: aleksis/core/models.py:174 aleksis/core/models.py:398
+#: aleksis/core/models.py:175 aleksis/core/models.py:415
 msgid "Short name"
 msgstr ""
 
-#: aleksis/core/models.py:177
+#: aleksis/core/models.py:178
 msgid "Street"
 msgstr ""
 
-#: aleksis/core/models.py:178
+#: aleksis/core/models.py:179
 msgid "Street number"
 msgstr ""
 
-#: aleksis/core/models.py:179
+#: aleksis/core/models.py:180
 msgid "Postal code"
 msgstr ""
 
-#: aleksis/core/models.py:180
+#: aleksis/core/models.py:181
 msgid "Place"
 msgstr ""
 
-#: aleksis/core/models.py:182
+#: aleksis/core/models.py:183
 msgid "Home phone"
 msgstr ""
 
-#: aleksis/core/models.py:183
+#: aleksis/core/models.py:184
 msgid "Mobile phone"
 msgstr ""
 
-#: aleksis/core/models.py:187
+#: aleksis/core/models.py:188
 msgid "Date of birth"
 msgstr ""
 
-#: aleksis/core/models.py:188
+#: aleksis/core/models.py:189
 msgid "Sex"
 msgstr ""
 
-#: aleksis/core/models.py:190
+#: aleksis/core/models.py:191
 msgid "Photo"
 msgstr ""
 
-#: aleksis/core/models.py:194 aleksis/core/templates/core/person/full.html:137
+#: aleksis/core/models.py:195 aleksis/core/templates/core/person/full.html:137
 msgid "Guardians / Parents"
 msgstr ""
 
-#: aleksis/core/models.py:201
+#: aleksis/core/models.py:202
 msgid "Primary group"
 msgstr ""
 
-#: aleksis/core/models.py:204 aleksis/core/models.py:546
-#: aleksis/core/models.py:570 aleksis/core/models.py:655
-#: aleksis/core/models.py:934 aleksis/core/templates/core/person/full.html:120
+#: aleksis/core/models.py:205 aleksis/core/models.py:563
+#: aleksis/core/models.py:587 aleksis/core/models.py:672
+#: aleksis/core/models.py:951 aleksis/core/templates/core/person/full.html:120
 msgid "Description"
 msgstr ""
 
-#: aleksis/core/models.py:353
+#: aleksis/core/models.py:370
 msgid "Title of field"
 msgstr ""
 
-#: aleksis/core/models.py:355
+#: aleksis/core/models.py:372
 msgid "Type of field"
 msgstr ""
 
-#: aleksis/core/models.py:362
+#: aleksis/core/models.py:379
 msgid "Addtitional field for groups"
 msgstr ""
 
-#: aleksis/core/models.py:363
+#: aleksis/core/models.py:380
 msgid "Addtitional fields for groups"
 msgstr ""
 
-#: aleksis/core/models.py:380
+#: aleksis/core/models.py:397
 msgid "Group"
 msgstr ""
 
-#: aleksis/core/models.py:383
+#: aleksis/core/models.py:400
 msgid "Can assign child groups to groups"
 msgstr ""
 
-#: aleksis/core/models.py:384
+#: aleksis/core/models.py:401
 msgid "Can view statistics about group."
 msgstr ""
 
-#: aleksis/core/models.py:396
+#: aleksis/core/models.py:413
 msgid "Long name"
 msgstr ""
 
-#: aleksis/core/models.py:406 aleksis/core/templates/core/group/full.html:85
+#: aleksis/core/models.py:423 aleksis/core/templates/core/group/full.html:85
 msgid "Members"
 msgstr ""
 
-#: aleksis/core/models.py:409 aleksis/core/templates/core/group/full.html:82
+#: aleksis/core/models.py:426 aleksis/core/templates/core/group/full.html:82
 msgid "Owners"
 msgstr ""
 
-#: aleksis/core/models.py:416 aleksis/core/templates/core/group/full.html:55
+#: aleksis/core/models.py:433 aleksis/core/templates/core/group/full.html:55
 msgid "Parent groups"
 msgstr ""
 
-#: aleksis/core/models.py:424
+#: aleksis/core/models.py:441
 msgid "Type of group"
 msgstr ""
 
-#: aleksis/core/models.py:542
+#: aleksis/core/models.py:559
 msgid "User"
 msgstr ""
 
-#: aleksis/core/models.py:545 aleksis/core/models.py:569
-#: aleksis/core/models.py:654
+#: aleksis/core/models.py:562 aleksis/core/models.py:586
+#: aleksis/core/models.py:671
 #: aleksis/core/templates/core/announcement/list.html:18
 msgid "Title"
 msgstr ""
 
-#: aleksis/core/models.py:548
+#: aleksis/core/models.py:565
 msgid "Application"
 msgstr ""
 
-#: aleksis/core/models.py:554
+#: aleksis/core/models.py:571
 msgid "Activity"
 msgstr ""
 
-#: aleksis/core/models.py:555
+#: aleksis/core/models.py:572
 msgid "Activities"
 msgstr ""
 
-#: aleksis/core/models.py:561
+#: aleksis/core/models.py:578
 msgid "Sender"
 msgstr ""
 
-#: aleksis/core/models.py:566
+#: aleksis/core/models.py:583
 msgid "Recipient"
 msgstr ""
 
-#: aleksis/core/models.py:571 aleksis/core/models.py:911
+#: aleksis/core/models.py:588 aleksis/core/models.py:928
 msgid "Link"
 msgstr ""
 
-#: aleksis/core/models.py:573
+#: aleksis/core/models.py:590
 msgid "Read"
 msgstr ""
 
-#: aleksis/core/models.py:574
+#: aleksis/core/models.py:591
 msgid "Sent"
 msgstr ""
 
-#: aleksis/core/models.py:587
+#: aleksis/core/models.py:604
 msgid "Notification"
 msgstr ""
 
-#: aleksis/core/models.py:656
+#: aleksis/core/models.py:673
 msgid "Link to detailed view"
 msgstr ""
 
-#: aleksis/core/models.py:659
+#: aleksis/core/models.py:676
 msgid "Date and time from when to show"
 msgstr ""
 
-#: aleksis/core/models.py:662
+#: aleksis/core/models.py:679
 msgid "Date and time until when to show"
 msgstr ""
 
-#: aleksis/core/models.py:686
+#: aleksis/core/models.py:703
 msgid "Announcement"
 msgstr ""
 
-#: aleksis/core/models.py:724
+#: aleksis/core/models.py:741
 msgid "Announcement recipient"
 msgstr ""
 
-#: aleksis/core/models.py:725
+#: aleksis/core/models.py:742
 msgid "Announcement recipients"
 msgstr ""
 
-#: aleksis/core/models.py:780
+#: aleksis/core/models.py:797
 msgid "Widget Title"
 msgstr ""
 
-#: aleksis/core/models.py:781
+#: aleksis/core/models.py:798
 msgid "Activate Widget"
 msgstr ""
 
-#: aleksis/core/models.py:782
+#: aleksis/core/models.py:799
 msgid "Widget is broken"
 msgstr ""
 
-#: aleksis/core/models.py:785
+#: aleksis/core/models.py:802
 msgid "Size on mobile devices"
 msgstr ""
 
-#: aleksis/core/models.py:786
+#: aleksis/core/models.py:803
 msgid "<= 600 px, 12 columns"
 msgstr ""
 
-#: aleksis/core/models.py:791
+#: aleksis/core/models.py:808
 msgid "Size on tablet devices"
 msgstr ""
 
-#: aleksis/core/models.py:792
+#: aleksis/core/models.py:809
 msgid "> 600 px, 12 columns"
 msgstr ""
 
-#: aleksis/core/models.py:797
+#: aleksis/core/models.py:814
 msgid "Size on desktop devices"
 msgstr ""
 
-#: aleksis/core/models.py:798
+#: aleksis/core/models.py:815
 msgid "> 992 px, 12 columns"
 msgstr ""
 
-#: aleksis/core/models.py:803
+#: aleksis/core/models.py:820
 msgid "Size on large desktop devices"
 msgstr ""
 
-#: aleksis/core/models.py:804
+#: aleksis/core/models.py:821
 msgid "> 1200 px>, 12 columns"
 msgstr ""
 
-#: aleksis/core/models.py:835
+#: aleksis/core/models.py:852
 msgid "Can edit default dashboard"
 msgstr ""
 
-#: aleksis/core/models.py:836
+#: aleksis/core/models.py:853
 msgid "Dashboard Widget"
 msgstr ""
 
-#: aleksis/core/models.py:837
+#: aleksis/core/models.py:854
 msgid "Dashboard Widgets"
 msgstr ""
 
-#: aleksis/core/models.py:843
+#: aleksis/core/models.py:860
 msgid "URL"
 msgstr ""
 
-#: aleksis/core/models.py:844
+#: aleksis/core/models.py:861
 msgid "Icon URL"
 msgstr ""
 
-#: aleksis/core/models.py:850
+#: aleksis/core/models.py:867
 msgid "External link widget"
 msgstr ""
 
-#: aleksis/core/models.py:851
+#: aleksis/core/models.py:868
 msgid "External link widgets"
 msgstr ""
 
-#: aleksis/core/models.py:856
+#: aleksis/core/models.py:873
 msgid "Dashboard widget"
 msgstr ""
 
-#: aleksis/core/models.py:861
+#: aleksis/core/models.py:878
 msgid "Order"
 msgstr ""
 
-#: aleksis/core/models.py:862
+#: aleksis/core/models.py:879
 msgid "Part of the default dashboard"
 msgstr ""
 
-#: aleksis/core/models.py:877
+#: aleksis/core/models.py:894
 msgid "Dashboard widget order"
 msgstr ""
 
-#: aleksis/core/models.py:878
+#: aleksis/core/models.py:895
 msgid "Dashboard widget orders"
 msgstr ""
 
-#: aleksis/core/models.py:884
+#: aleksis/core/models.py:901
 msgid "Menu ID"
 msgstr ""
 
-#: aleksis/core/models.py:897
+#: aleksis/core/models.py:914
 msgid "Custom menu"
 msgstr ""
 
-#: aleksis/core/models.py:898
+#: aleksis/core/models.py:915
 msgid "Custom menus"
 msgstr ""
 
-#: aleksis/core/models.py:908
+#: aleksis/core/models.py:925
 msgid "Menu"
 msgstr ""
 
-#: aleksis/core/models.py:912
+#: aleksis/core/models.py:929
 msgid "Icon"
 msgstr ""
 
-#: aleksis/core/models.py:918
+#: aleksis/core/models.py:935
 msgid "Custom menu item"
 msgstr ""
 
-#: aleksis/core/models.py:919
+#: aleksis/core/models.py:936
 msgid "Custom menu items"
 msgstr ""
 
-#: aleksis/core/models.py:933
+#: aleksis/core/models.py:950
 msgid "Title of type"
 msgstr ""
 
-#: aleksis/core/models.py:940 aleksis/core/templates/core/group/full.html:47
+#: aleksis/core/models.py:957 aleksis/core/templates/core/group/full.html:47
 msgid "Group type"
 msgstr ""
 
-#: aleksis/core/models.py:954
+#: aleksis/core/models.py:971
 msgid "Can view system status"
 msgstr ""
 
-#: aleksis/core/models.py:955
-msgid "Can link persons to accounts"
-msgstr ""
-
-#: aleksis/core/models.py:956
+#: aleksis/core/models.py:972
 msgid "Can manage data"
 msgstr ""
 
-#: aleksis/core/models.py:957
+#: aleksis/core/models.py:973
 msgid "Can impersonate"
 msgstr ""
 
-#: aleksis/core/models.py:958
+#: aleksis/core/models.py:974
 msgid "Can use search"
 msgstr ""
 
-#: aleksis/core/models.py:959
+#: aleksis/core/models.py:975
 msgid "Can change site preferences"
 msgstr ""
 
-#: aleksis/core/models.py:960
+#: aleksis/core/models.py:976
 msgid "Can change person preferences"
 msgstr ""
 
-#: aleksis/core/models.py:961
+#: aleksis/core/models.py:977
 msgid "Can change group preferences"
 msgstr ""
 
-#: aleksis/core/models.py:962
+#: aleksis/core/models.py:978
 msgid "Can add oauth applications"
 msgstr ""
 
-#: aleksis/core/models.py:963
+#: aleksis/core/models.py:979
 msgid "Can list oauth applications"
 msgstr ""
 
-#: aleksis/core/models.py:964
+#: aleksis/core/models.py:980
 msgid "Can view oauth applications"
 msgstr ""
 
-#: aleksis/core/models.py:965
+#: aleksis/core/models.py:981
 msgid "Can update oauth applications"
 msgstr ""
 
-#: aleksis/core/models.py:966
+#: aleksis/core/models.py:982
 msgid "Can delete oauth applications"
 msgstr ""
 
-#: aleksis/core/models.py:967
+#: aleksis/core/models.py:983
 msgid "Can test PDF generation"
 msgstr ""
 
-#: aleksis/core/models.py:1003
+#: aleksis/core/models.py:1019
 msgid "Related data check task"
 msgstr ""
 
-#: aleksis/core/models.py:1011
+#: aleksis/core/models.py:1027
 msgid "Issue solved"
 msgstr ""
 
-#: aleksis/core/models.py:1012
+#: aleksis/core/models.py:1028
 msgid "Notification sent"
 msgstr ""
 
-#: aleksis/core/models.py:1025
+#: aleksis/core/models.py:1041
 msgid "Data check result"
 msgstr ""
 
-#: aleksis/core/models.py:1026
+#: aleksis/core/models.py:1042
 msgid "Data check results"
 msgstr ""
 
-#: aleksis/core/models.py:1028
+#: aleksis/core/models.py:1044
 msgid "Can run data checks"
 msgstr ""
 
-#: aleksis/core/models.py:1029
+#: aleksis/core/models.py:1045
 msgid "Can solve data check problems"
 msgstr ""
 
-#: aleksis/core/models.py:1044
+#: aleksis/core/models.py:1060
 msgid "Owner"
 msgstr ""
 
-#: aleksis/core/models.py:1048
+#: aleksis/core/models.py:1064
 msgid "File expires at"
 msgstr ""
 
-#: aleksis/core/models.py:1050
+#: aleksis/core/models.py:1066
 msgid "Generated HTML file"
 msgstr ""
 
-#: aleksis/core/models.py:1052
+#: aleksis/core/models.py:1068
 msgid "Generated PDF file"
 msgstr ""
 
-#: aleksis/core/models.py:1059
+#: aleksis/core/models.py:1075
 msgid "PDF file"
 msgstr ""
 
-#: aleksis/core/models.py:1060
+#: aleksis/core/models.py:1076
 msgid "PDF files"
 msgstr ""
 
-#: aleksis/core/models.py:1065
+#: aleksis/core/models.py:1081
 msgid "Task result"
 msgstr ""
 
-#: aleksis/core/models.py:1068
+#: aleksis/core/models.py:1084
 msgid "Task user"
 msgstr ""
 
-#: aleksis/core/models.py:1080
+#: aleksis/core/models.py:1096
 msgid "Task user assignment"
 msgstr ""
 
-#: aleksis/core/models.py:1081
+#: aleksis/core/models.py:1097
 msgid "Task user assignments"
 msgstr ""
 
@@ -1028,75 +1019,71 @@ msgstr ""
 msgid "Official name of the school, e.g. as given by supervisory authority"
 msgstr ""
 
-#: aleksis/core/preferences.py:256
-msgid "Enabled custom authentication backends"
-msgstr ""
-
-#: aleksis/core/preferences.py:268
+#: aleksis/core/preferences.py:254
 msgid "Allow users to change their passwords"
 msgstr ""
 
-#: aleksis/core/preferences.py:276
+#: aleksis/core/preferences.py:262
 msgid "Enable signup"
 msgstr ""
 
-#: aleksis/core/preferences.py:287
+#: aleksis/core/preferences.py:273
 msgid "Available languages"
 msgstr ""
 
-#: aleksis/core/preferences.py:299
+#: aleksis/core/preferences.py:285
 msgid "Send emails if data checks detect problems"
 msgstr ""
 
-#: aleksis/core/preferences.py:310
+#: aleksis/core/preferences.py:296
 msgid "Email recipients for data checks problem emails"
 msgstr ""
 
-#: aleksis/core/preferences.py:321
+#: aleksis/core/preferences.py:307
 msgid "Email recipient groups for data checks problem emails"
 msgstr ""
 
-#: aleksis/core/preferences.py:330
+#: aleksis/core/preferences.py:316
 msgid "Show dashboard to users without login"
 msgstr ""
 
-#: aleksis/core/preferences.py:339
+#: aleksis/core/preferences.py:325
 msgid "Allow users to edit their dashboard"
 msgstr ""
 
-#: aleksis/core/preferences.py:350
+#: aleksis/core/preferences.py:336
 msgid "Fields on person model which are editable by themselves."
 msgstr ""
 
-#: aleksis/core/preferences.py:364
+#: aleksis/core/preferences.py:350
 msgid "Editable fields on person model which should trigger a notification on change"
 msgstr ""
 
-#: aleksis/core/preferences.py:377
+#: aleksis/core/preferences.py:363
 msgid "Contact for notification if a person changes their data"
 msgstr ""
 
-#: aleksis/core/preferences.py:387
+#: aleksis/core/preferences.py:373
 msgid "PDF file expiration duration"
 msgstr ""
 
-#: aleksis/core/preferences.py:388
+#: aleksis/core/preferences.py:374
 msgid "in minutes"
 msgstr ""
 
-#: aleksis/core/preferences.py:398
+#: aleksis/core/preferences.py:384
 msgid "Automatically update the dashboard and its widgets"
 msgstr ""
 
-#: aleksis/core/preferences.py:408
+#: aleksis/core/preferences.py:394
 msgid "Automatically update the dashboard and its widgets sitewide"
 msgstr ""
 
-#: aleksis/core/settings.py:468
+#: aleksis/core/settings.py:452
 msgid "English"
 msgstr ""
 
-#: aleksis/core/settings.py:469
+#: aleksis/core/settings.py:453
 msgid "German"
 msgstr ""
 
@@ -1260,7 +1247,7 @@ msgstr ""
 #: aleksis/core/templates/account/password_reset_done.html:5
 #: aleksis/core/templates/account/verification_email_required.html:5
 #: aleksis/core/templates/account/verification_email_required.html:6
-#: aleksis/core/templates/two_factor/core/login.html:100
+#: aleksis/core/templates/two_factor/core/login.html:81
 msgid "Reset password"
 msgstr ""
 
@@ -1997,32 +1984,10 @@ msgid ""
 "          "
 msgstr ""
 
-#: aleksis/core/templates/core/person/accounts.html:12
-#: aleksis/core/templates/core/person/accounts.html:14
-msgid "Link persons to accounts"
-msgstr ""
-
-#: aleksis/core/templates/core/person/accounts.html:21
-msgid ""
-"\n"
-"        You can use this form to assign user accounts to persons. Use the\n"
-"        dropdowns to select existing accounts; use the text fields to create new\n"
-"        accounts on-the-fly. The latter will create a new account with the\n"
-"        entered username and copy all other details from the person.\n"
-"      "
-msgstr ""
-
-#: aleksis/core/templates/core/person/accounts.html:36
-#: aleksis/core/templates/core/person/accounts.html:60
-msgid "Update"
-msgstr ""
-
-#: aleksis/core/templates/core/person/accounts.html:42
-msgid "Existing account"
-msgstr ""
-
-#: aleksis/core/templates/core/person/accounts.html:43
-msgid "New account"
+#: aleksis/core/templates/core/person/create.html:12
+#: aleksis/core/templates/core/person/create.html:13
+#: aleksis/core/templates/core/person/list.html:17
+msgid "Create person"
 msgstr ""
 
 #: aleksis/core/templates/core/person/edit.html:12
@@ -2031,6 +1996,8 @@ msgid "Edit person"
 msgstr ""
 
 #: aleksis/core/templates/core/person/full.html:44
+#: aleksis/core/templates/impersonate/list_users.html:7
+#: aleksis/core/templates/impersonate/list_users.html:8
 msgid "Impersonate"
 msgstr ""
 
@@ -2042,10 +2009,6 @@ msgstr ""
 msgid "Children"
 msgstr ""
 
-#: aleksis/core/templates/core/person/list.html:17
-msgid "Create person"
-msgstr ""
-
 #: aleksis/core/templates/core/person/list.html:21
 msgid "Filter persons"
 msgstr ""
@@ -2082,10 +2045,6 @@ msgstr ""
 msgid "Save preferences"
 msgstr ""
 
-#: aleksis/core/templates/impersonate/list_users.html:8
-msgid "Impersonate user"
-msgstr ""
-
 #: aleksis/core/templates/oauth2_provider/application_confirm_delete.html:5
 #: aleksis/core/templates/oauth2_provider/application_confirm_delete.html:6
 msgid "Delete application"
@@ -2438,64 +2397,70 @@ msgstr ""
 msgid "Generate Tokens"
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:18
+#: aleksis/core/templates/two_factor/core/login.html:20
 msgid "Login with username and password"
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:26
-msgid "You have no permission to view this page. Please login with an other account."
+#: aleksis/core/templates/two_factor/core/login.html:28
+msgid ""
+"You have no permission to view this page. Please login with an other\n"
+"                    account."
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:33
+#: aleksis/core/templates/two_factor/core/login.html:36
 msgid "Please login to see this page."
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:43
+#: aleksis/core/templates/two_factor/core/login.html:46
 msgid ""
 "\n"
-"                      We are calling your phone right now, please enter the\n"
-"                      digits you hear.\n"
-"                    "
+"                        We are calling your phone right now, please enter the\n"
+"                        digits you hear.\n"
+"                      "
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:48
+#: aleksis/core/templates/two_factor/core/login.html:51
 msgid ""
 "\n"
-"                      We sent you a text message, please enter the tokens we\n"
-"                      sent.\n"
-"                    "
+"                        We sent you a text message, please enter the tokens we\n"
+"                        sent.\n"
+"                      "
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:53
+#: aleksis/core/templates/two_factor/core/login.html:56
 msgid ""
 "\n"
-"                      Please enter the tokens generated by your token\n"
-"                      generator.\n"
-"                    "
+"                        Please enter the tokens generated by your token\n"
+"                        generator.\n"
+"                      "
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:59
+#: aleksis/core/templates/two_factor/core/login.html:62
 msgid ""
 "\n"
-"                    Use this form for entering backup tokens for logging in.\n"
-"                    These tokens have been generated for you to print and keep safe. Please\n"
-"                    enter one of these backup tokens to login to your account.\n"
-"                  "
+"                      Use this form for entering backup tokens for logging in.\n"
+"                      These tokens have been generated for you to print and keep safe. Please\n"
+"                      enter one of these backup tokens to login to your account.\n"
+"                    "
+msgstr ""
+
+#: aleksis/core/templates/two_factor/core/login.html:90
+msgid "Device currently not available?"
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:74
+#: aleksis/core/templates/two_factor/core/login.html:92
 msgid "Or, alternatively, use one of your backup phones:"
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:84
+#: aleksis/core/templates/two_factor/core/login.html:102
 msgid "As a last resort, you can use a backup token:"
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:87
+#: aleksis/core/templates/two_factor/core/login.html:105
 msgid "Use Backup Token"
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:110
+#: aleksis/core/templates/two_factor/core/login.html:116
 msgid "Use alternative login options"
 msgstr ""
 
@@ -2764,107 +2729,107 @@ msgstr ""
 msgid "Download PDF"
 msgstr ""
 
-#: aleksis/core/views.py:253
+#: aleksis/core/views.py:251
 msgid "The school term has been created."
 msgstr ""
 
-#: aleksis/core/views.py:265
+#: aleksis/core/views.py:263
 msgid "The school term has been saved."
 msgstr ""
 
-#: aleksis/core/views.py:410
+#: aleksis/core/views.py:387
 msgid "The child groups were successfully saved."
 msgstr ""
 
-#: aleksis/core/views.py:471
+#: aleksis/core/views.py:406 aleksis/core/views.py:416
 msgid "The person has been saved."
 msgstr ""
 
-#: aleksis/core/views.py:510
+#: aleksis/core/views.py:466
 msgid "The group has been saved."
 msgstr ""
 
-#: aleksis/core/views.py:607
+#: aleksis/core/views.py:563
 msgid "The announcement has been saved."
 msgstr ""
 
-#: aleksis/core/views.py:623
+#: aleksis/core/views.py:579
 msgid "The announcement has been deleted."
 msgstr ""
 
-#: aleksis/core/views.py:707
+#: aleksis/core/views.py:663
 msgid "The preferences have been saved successfully."
 msgstr ""
 
-#: aleksis/core/views.py:731
+#: aleksis/core/views.py:687
 msgid "The person has been deleted."
 msgstr ""
 
-#: aleksis/core/views.py:745
+#: aleksis/core/views.py:701
 msgid "The group has been deleted."
 msgstr ""
 
-#: aleksis/core/views.py:777
+#: aleksis/core/views.py:733
 msgid "The additional_field has been saved."
 msgstr ""
 
-#: aleksis/core/views.py:811
+#: aleksis/core/views.py:767
 msgid "The additional field has been deleted."
 msgstr ""
 
-#: aleksis/core/views.py:836
+#: aleksis/core/views.py:792
 msgid "The group type has been saved."
 msgstr ""
 
-#: aleksis/core/views.py:866
+#: aleksis/core/views.py:822
 msgid "The group type has been deleted."
 msgstr ""
 
-#: aleksis/core/views.py:899
+#: aleksis/core/views.py:855
 msgid "Progress: Run data checks"
 msgstr ""
 
-#: aleksis/core/views.py:900
+#: aleksis/core/views.py:856
 msgid "Run data checks …"
 msgstr ""
 
-#: aleksis/core/views.py:901
+#: aleksis/core/views.py:857
 msgid "The data checks were run successfully."
 msgstr ""
 
-#: aleksis/core/views.py:902
+#: aleksis/core/views.py:858
 msgid "There was a problem while running data checks."
 msgstr ""
 
-#: aleksis/core/views.py:918
+#: aleksis/core/views.py:874
 #, python-brace-format
 msgid "The solve option '{solve_option_obj.verbose_name}' "
 msgstr ""
 
-#: aleksis/core/views.py:960
+#: aleksis/core/views.py:916
 msgid "The dashboard widget has been saved."
 msgstr ""
 
-#: aleksis/core/views.py:990
+#: aleksis/core/views.py:946
 msgid "The dashboard widget has been created."
 msgstr ""
 
-#: aleksis/core/views.py:1000
+#: aleksis/core/views.py:956
 msgid "The dashboard widget has been deleted."
 msgstr ""
 
-#: aleksis/core/views.py:1067
+#: aleksis/core/views.py:1023
 msgid "Your dashboard configuration has been saved successfully."
 msgstr ""
 
-#: aleksis/core/views.py:1069
+#: aleksis/core/views.py:1025
 msgid "The configuration of the default dashboard has been saved successfully."
 msgstr ""
 
-#: aleksis/core/views.py:1197
+#: aleksis/core/views.py:1153
 msgid "The third-party account could not be disconnected because it is the only login method available."
 msgstr ""
 
-#: aleksis/core/views.py:1204
+#: aleksis/core/views.py:1160
 msgid "The third-party account has been successfully disconnected."
 msgstr ""
diff --git a/aleksis/core/locale/ar/LC_MESSAGES/djangojs.po b/aleksis/core/locale/ar/LC_MESSAGES/djangojs.po
index c66c2fc59010a34863f4e372e19aebc75cfd9631..58d7ae38a2326acb79508cd05c32cab673c58fe9 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: 2021-08-28 17:53+0200\n"
+"POT-Creation-Date: 2021-10-28 16:18+0200\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"
diff --git a/aleksis/core/locale/de_DE/LC_MESSAGES/django.po b/aleksis/core/locale/de_DE/LC_MESSAGES/django.po
index 1418826eb332523177bf5da3fc0b3b7c6b6d1a2f..f392000d5c400048743b02d15cfca5dbb4efd644 100644
--- a/aleksis/core/locale/de_DE/LC_MESSAGES/django.po
+++ b/aleksis/core/locale/de_DE/LC_MESSAGES/django.po
@@ -7,35 +7,35 @@ msgid ""
 msgstr ""
 "Project-Id-Version: AlekSIS (School Information System) 0.1\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2021-08-28 17:53+0200\n"
-"PO-Revision-Date: 2021-08-28 17:33+0000\n"
+"POT-Creation-Date: 2021-10-28 16:18+0200\n"
+"PO-Revision-Date: 2021-10-29 14:28+0000\n"
 "Last-Translator: Jonathan Weth <teckids@jonathanweth.de>\n"
-"Language-Team: German <https://translate.edugit.org/projects/aleksis/aleksis/"
-"de/>\n"
+"Language-Team: German <https://translate.edugit.org/projects/aleksis/"
+"aleksis-core/de/>\n"
 "Language: de_DE\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.4\n"
+"X-Generator: Weblate 4.8\n"
 
-#: aleksis/core/apps.py:148 aleksis/core/settings.py:343
+#: aleksis/core/apps.py:150
 msgid "OpenID Connect scope"
 msgstr "OpenID-Connect-Scope"
 
-#: aleksis/core/apps.py:149 aleksis/core/settings.py:344
+#: aleksis/core/apps.py:151
 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:150 aleksis/core/settings.py:345
+#: aleksis/core/apps.py:152
 msgid "Full home postal address"
 msgstr "Vollständige Postanschrift"
 
-#: aleksis/core/apps.py:151 aleksis/core/settings.py:346
+#: aleksis/core/apps.py:153
 msgid "Email address"
 msgstr "E-Mail-Adresse"
 
-#: aleksis/core/apps.py:152 aleksis/core/settings.py:347
+#: aleksis/core/apps.py:154
 msgid "Home and mobile phone"
 msgstr "Festnetz- und Mobilfunknummer"
 
@@ -77,124 +77,124 @@ msgstr "Nach Namen suchen"
 msgid "Search by contact details"
 msgstr "Nach Kontaktdetails suchen"
 
-#: aleksis/core/forms.py:62
-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:66
-msgid "This username is already in use."
-msgstr "Dieser Benutzername wird bereits genutzt."
-
-#: aleksis/core/forms.py:90 aleksis/core/forms.py:412
+#: aleksis/core/forms.py:41 aleksis/core/forms.py:387
 msgid "Base data"
 msgstr "Basisdaten"
 
-#: aleksis/core/forms.py:96
+#: aleksis/core/forms.py:47
 msgid "Address"
 msgstr "Adresse"
 
-#: aleksis/core/forms.py:97
+#: aleksis/core/forms.py:48
 msgid "Contact data"
 msgstr "Kontaktdaten"
 
-#: aleksis/core/forms.py:99
+#: aleksis/core/forms.py:50
 msgid "Advanced personal data"
 msgstr "Zusätzliche persönliche Daten"
 
-#: aleksis/core/forms.py:142
+#: aleksis/core/forms.py:93
 msgid "New user"
 msgstr "Neuer Benutzer"
 
-#: aleksis/core/forms.py:142
+#: aleksis/core/forms.py:93
 msgid "Create a new account"
 msgstr "Neues Benutzerkonto erstellen"
 
-#: aleksis/core/forms.py:170 aleksis/core/models.py:116
+#: aleksis/core/forms.py:124
+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:128
+msgid "This username is already in use."
+msgstr "Dieser Benutzername wird bereits genutzt."
+
+#: aleksis/core/forms.py:145 aleksis/core/models.py:117
 msgid "School term"
 msgstr "Schuljahr"
 
-#: aleksis/core/forms.py:171
+#: aleksis/core/forms.py:146
 msgid "Common data"
 msgstr "Allgemeine Daten"
 
-#: aleksis/core/forms.py:172 aleksis/core/forms.py:221
-#: aleksis/core/menus.py:238 aleksis/core/models.py:139
+#: aleksis/core/forms.py:147 aleksis/core/forms.py:196
+#: aleksis/core/menus.py:238 aleksis/core/models.py:140
 #: aleksis/core/templates/core/person/list.html:8
 #: aleksis/core/templates/core/person/list.html:9
 msgid "Persons"
 msgstr "Personen"
 
-#: aleksis/core/forms.py:173
+#: aleksis/core/forms.py:148
 msgid "Additional data"
 msgstr "Zusätzliche Datne"
 
-#: aleksis/core/forms.py:213 aleksis/core/forms.py:216
-#: aleksis/core/models.py:59
+#: aleksis/core/forms.py:188 aleksis/core/forms.py:191
+#: aleksis/core/models.py:60
 msgid "Date"
 msgstr "Datum"
 
-#: aleksis/core/forms.py:214 aleksis/core/forms.py:217
-#: aleksis/core/models.py:67
+#: aleksis/core/forms.py:189 aleksis/core/forms.py:192
+#: aleksis/core/models.py:68
 msgid "Time"
 msgstr "Zeit"
 
-#: aleksis/core/forms.py:234 aleksis/core/menus.py:249
-#: aleksis/core/models.py:381 aleksis/core/templates/core/group/list.html:8
+#: aleksis/core/forms.py:209 aleksis/core/menus.py:249
+#: aleksis/core/models.py:398 aleksis/core/templates/core/group/list.html:8
 #: aleksis/core/templates/core/group/list.html:9
 #: aleksis/core/templates/core/person/full.html:144
 msgid "Groups"
 msgstr "Gruppen"
 
-#: aleksis/core/forms.py:244
+#: aleksis/core/forms.py:219
 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:247
+#: aleksis/core/forms.py:222
 msgid "Who should see the announcement?"
 msgstr "Wer soll die Ankündigung sehen?"
 
-#: aleksis/core/forms.py:248
+#: aleksis/core/forms.py:223
 msgid "Write your announcement:"
 msgstr "Schreiben Sie ihre Ankündigung:"
 
-#: aleksis/core/forms.py:287
+#: aleksis/core/forms.py:262
 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:291
+#: aleksis/core/forms.py:266
 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:300
+#: aleksis/core/forms.py:275
 msgid "You need at least one recipient."
 msgstr "Sie benötigen mindestens einen Empfänger."
 
-#: aleksis/core/forms.py:414
+#: aleksis/core/forms.py:389
 msgid "Account data"
 msgstr "Kontodaten"
 
-#: aleksis/core/forms.py:416
+#: aleksis/core/forms.py:391
 msgid "Consents"
 msgstr "Zustimmungen"
 
-#: aleksis/core/forms.py:421
+#: aleksis/core/forms.py:396
 msgid "Password"
 msgstr "Passwort"
 
-#: aleksis/core/forms.py:427
+#: aleksis/core/forms.py:402
 msgid "Password (again)"
 msgstr "Passwort wiederholen"
 
-#: aleksis/core/forms.py:436
+#: aleksis/core/forms.py:411
 #, python-brace-format
 msgid "I have read the <a href='{privacy_policy}'>Privacy policy</a> and agree with them."
 msgstr "Ich habe die <a href='{privacy_policy}'>Datenschutzerklärung</a> gelesen und stimme ihr zu."
 
-#: aleksis/core/forms.py:460
+#: aleksis/core/forms.py:435
 msgid "You must type the same password each time."
 msgstr "Sie müssen zweimal das gleiche Passwort eingeben."
 
-#: aleksis/core/forms.py:605
+#: aleksis/core/forms.py:580
 msgid "No valid selection."
 msgstr "Keine gültige Auswahl."
 
@@ -225,8 +225,8 @@ 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:20
-#: aleksis/core/templates/two_factor/core/login.html:95
+#: aleksis/core/templates/two_factor/core/login.html:22
+#: aleksis/core/templates/two_factor/core/login.html:76
 msgid "Login"
 msgstr "Anmelden"
 
@@ -239,7 +239,7 @@ msgstr "Registrieren"
 msgid "Dashboard"
 msgstr "Dashboard"
 
-#: aleksis/core/menus.py:32 aleksis/core/models.py:588
+#: aleksis/core/menus.py:32 aleksis/core/models.py:605
 #: aleksis/core/preferences.py:26
 #: aleksis/core/templates/core/notifications.html:4
 #: aleksis/core/templates/core/notifications.html:5
@@ -297,13 +297,13 @@ msgstr "Autorisierte Anwendungen"
 msgid "Admin"
 msgstr "Admin"
 
-#: aleksis/core/menus.py:127 aleksis/core/models.py:687
+#: aleksis/core/menus.py:127 aleksis/core/models.py:704
 #: aleksis/core/templates/core/announcement/list.html:7
 #: aleksis/core/templates/core/announcement/list.html:8
 msgid "Announcements"
 msgstr "Ankündigungen"
 
-#: aleksis/core/menus.py:138 aleksis/core/models.py:117
+#: aleksis/core/menus.py:138 aleksis/core/models.py:118
 #: aleksis/core/templates/core/school_term/list.html:8
 #: aleksis/core/templates/core/school_term/list.html:9
 msgid "School terms"
@@ -354,570 +354,561 @@ msgstr "OAuth2-Anwendungen"
 msgid "People"
 msgstr "Leute"
 
-#: aleksis/core/menus.py:260 aleksis/core/models.py:941
+#: aleksis/core/menus.py:260 aleksis/core/models.py:958
 #: aleksis/core/templates/core/group_type/list.html:8
 #: aleksis/core/templates/core/group_type/list.html:9
 msgid "Group types"
 msgstr "Gruppentypen"
 
 #: aleksis/core/menus.py:271
-msgid "Persons and accounts"
-msgstr "Personen und Konten"
-
-#: aleksis/core/menus.py:282
 msgid "Groups and child groups"
 msgstr "Gruppen und Kindgruppen"
 
-#: aleksis/core/menus.py:293 aleksis/core/models.py:429
+#: aleksis/core/menus.py:282 aleksis/core/models.py:446
 #: aleksis/core/templates/core/additional_field/list.html:8
 #: aleksis/core/templates/core/additional_field/list.html:9
 msgid "Additional fields"
 msgstr "Zusätzliche Felder"
 
-#: aleksis/core/menus.py:308
+#: aleksis/core/menus.py:297
 #: aleksis/core/templates/core/group/child_groups.html:7
 #: aleksis/core/templates/core/group/child_groups.html:9
 msgid "Assign child groups to groups"
 msgstr "Kindgruppen zu Gruppen zuordnen"
 
-#: aleksis/core/mixins.py:475
+#: aleksis/core/mixins.py:498
 msgid "Linked school term"
 msgstr "Zugeordnetes Schuljahr"
 
-#: aleksis/core/models.py:57
+#: aleksis/core/models.py:58
 msgid "Boolean (Yes/No)"
 msgstr "Boolean (Ja/Nein)"
 
-#: aleksis/core/models.py:58
+#: aleksis/core/models.py:59
 msgid "Text (one line)"
 msgstr "Text (eine Zeile)"
 
-#: aleksis/core/models.py:60
+#: aleksis/core/models.py:61
 msgid "Date and time"
 msgstr "Datum und Uhrzeit"
 
-#: aleksis/core/models.py:61
+#: aleksis/core/models.py:62
 msgid "Decimal number"
 msgstr "Dezimalzahl"
 
-#: aleksis/core/models.py:62 aleksis/core/models.py:185
+#: aleksis/core/models.py:63 aleksis/core/models.py:186
 msgid "E-mail address"
 msgstr "E-Mail-Adresse"
 
-#: aleksis/core/models.py:63
+#: aleksis/core/models.py:64
 msgid "Integer"
 msgstr "Ganze Zahl"
 
-#: aleksis/core/models.py:64
+#: aleksis/core/models.py:65
 msgid "IP address"
 msgstr "IP-Adresse"
 
-#: aleksis/core/models.py:65
+#: aleksis/core/models.py:66
 msgid "Boolean or empty (Yes/No/Neither)"
 msgstr "Boolean oder leer (Ja/Nein/weder)"
 
-#: aleksis/core/models.py:66
+#: aleksis/core/models.py:67
 msgid "Text (multi-line)"
 msgstr "Text (mehrzeilig)"
 
-#: aleksis/core/models.py:68
+#: aleksis/core/models.py:69
 msgid "URL / Link"
 msgstr "URL / Link"
 
-#: aleksis/core/models.py:80 aleksis/core/models.py:910
+#: aleksis/core/models.py:81 aleksis/core/models.py:927
 msgid "Name"
 msgstr "Name"
 
-#: aleksis/core/models.py:82
+#: aleksis/core/models.py:83
 msgid "Start date"
 msgstr "Startdatum"
 
-#: aleksis/core/models.py:83
+#: aleksis/core/models.py:84
 msgid "End date"
 msgstr "Enddatum"
 
-#: aleksis/core/models.py:102
+#: aleksis/core/models.py:103
 msgid "The start date must be earlier than the end date."
 msgstr "Das Startdatum muss vor dem Enddatum liegen."
 
-#: aleksis/core/models.py:109
+#: aleksis/core/models.py:110
 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:138 aleksis/core/models.py:859
-#: aleksis/core/templates/core/person/accounts.html:41
+#: aleksis/core/models.py:139 aleksis/core/models.py:876
 msgid "Person"
 msgstr "Person"
 
-#: aleksis/core/models.py:141
+#: aleksis/core/models.py:142
 msgid "Can view address"
 msgstr "Kann Adresse sehen"
 
-#: aleksis/core/models.py:142
+#: aleksis/core/models.py:143
 msgid "Can view contact details"
 msgstr "Kann Kontaktdetails sehen"
 
-#: aleksis/core/models.py:143
+#: aleksis/core/models.py:144
 msgid "Can view photo"
 msgstr "Kann Foto sehen"
 
-#: aleksis/core/models.py:144
+#: aleksis/core/models.py:145
 msgid "Can view persons groups"
 msgstr "Kann Gruppen einer Person sehen"
 
-#: aleksis/core/models.py:145
+#: aleksis/core/models.py:146
 msgid "Can view personal details"
 msgstr "Kann persönliche Daten sehen"
 
-#: aleksis/core/models.py:155
+#: aleksis/core/models.py:156
 msgid "female"
 msgstr "weiblich"
 
-#: aleksis/core/models.py:155
+#: aleksis/core/models.py:156
 msgid "male"
 msgstr "männlich"
 
-#: aleksis/core/models.py:163
+#: aleksis/core/models.py:164
 msgid "Linked user"
 msgstr "Verknüpfter Benutzer"
 
-#: aleksis/core/models.py:165
+#: aleksis/core/models.py:166
 msgid "Is person active?"
 msgstr "Ist die Person aktiv?"
 
-#: aleksis/core/models.py:167
+#: aleksis/core/models.py:168
 msgid "First name"
 msgstr "Vorname"
 
-#: aleksis/core/models.py:168
+#: aleksis/core/models.py:169
 msgid "Last name"
 msgstr "Nachname"
 
-#: aleksis/core/models.py:170
+#: aleksis/core/models.py:171
 msgid "Additional name(s)"
 msgstr "Zusätzliche Namen"
 
-#: aleksis/core/models.py:174 aleksis/core/models.py:398
+#: aleksis/core/models.py:175 aleksis/core/models.py:415
 msgid "Short name"
 msgstr "Kurzname"
 
-#: aleksis/core/models.py:177
+#: aleksis/core/models.py:178
 msgid "Street"
 msgstr "Straße"
 
-#: aleksis/core/models.py:178
+#: aleksis/core/models.py:179
 msgid "Street number"
 msgstr "Hausnummer"
 
-#: aleksis/core/models.py:179
+#: aleksis/core/models.py:180
 msgid "Postal code"
 msgstr "Postleitzahl"
 
-#: aleksis/core/models.py:180
+#: aleksis/core/models.py:181
 msgid "Place"
 msgstr "Ort"
 
-#: aleksis/core/models.py:182
+#: aleksis/core/models.py:183
 msgid "Home phone"
 msgstr "Festnetz"
 
-#: aleksis/core/models.py:183
+#: aleksis/core/models.py:184
 msgid "Mobile phone"
 msgstr "Handy"
 
-#: aleksis/core/models.py:187
+#: aleksis/core/models.py:188
 msgid "Date of birth"
 msgstr "Geburtsdatum"
 
-#: aleksis/core/models.py:188
+#: aleksis/core/models.py:189
 msgid "Sex"
 msgstr "Geschlecht"
 
-#: aleksis/core/models.py:190
+#: aleksis/core/models.py:191
 msgid "Photo"
 msgstr "Foto"
 
-#: aleksis/core/models.py:194 aleksis/core/templates/core/person/full.html:137
+#: aleksis/core/models.py:195 aleksis/core/templates/core/person/full.html:137
 msgid "Guardians / Parents"
 msgstr "Erziehungsberechtigte / Eltern"
 
-#: aleksis/core/models.py:201
+#: aleksis/core/models.py:202
 msgid "Primary group"
 msgstr "Primärgruppe"
 
-#: aleksis/core/models.py:204 aleksis/core/models.py:546
-#: aleksis/core/models.py:570 aleksis/core/models.py:655
-#: aleksis/core/models.py:934 aleksis/core/templates/core/person/full.html:120
+#: aleksis/core/models.py:205 aleksis/core/models.py:563
+#: aleksis/core/models.py:587 aleksis/core/models.py:672
+#: aleksis/core/models.py:951 aleksis/core/templates/core/person/full.html:120
 msgid "Description"
 msgstr "Beschreibung"
 
-#: aleksis/core/models.py:353
+#: aleksis/core/models.py:370
 msgid "Title of field"
 msgstr "Feldtitel"
 
-#: aleksis/core/models.py:355
+#: aleksis/core/models.py:372
 msgid "Type of field"
 msgstr "Feldtyp"
 
-#: aleksis/core/models.py:362
+#: aleksis/core/models.py:379
 msgid "Addtitional field for groups"
 msgstr "Zusätzliche Felder für Gruppen"
 
-#: aleksis/core/models.py:363
+#: aleksis/core/models.py:380
 msgid "Addtitional fields for groups"
 msgstr "Zusätzliche Felder für Gruppen"
 
-#: aleksis/core/models.py:380
+#: aleksis/core/models.py:397
 msgid "Group"
 msgstr "Gruppe"
 
-#: aleksis/core/models.py:383
+#: aleksis/core/models.py:400
 msgid "Can assign child groups to groups"
 msgstr "Kann Kindgruppen zu Gruppen zuordnen"
 
-#: aleksis/core/models.py:384
+#: aleksis/core/models.py:401
 msgid "Can view statistics about group."
 msgstr "Kann Statistiken über Gruppen sehen."
 
-#: aleksis/core/models.py:396
+#: aleksis/core/models.py:413
 msgid "Long name"
 msgstr "Langname"
 
-#: aleksis/core/models.py:406 aleksis/core/templates/core/group/full.html:85
+#: aleksis/core/models.py:423 aleksis/core/templates/core/group/full.html:85
 msgid "Members"
 msgstr "Mitglieder"
 
-#: aleksis/core/models.py:409 aleksis/core/templates/core/group/full.html:82
+#: aleksis/core/models.py:426 aleksis/core/templates/core/group/full.html:82
 msgid "Owners"
 msgstr "Leiter/-innen"
 
-#: aleksis/core/models.py:416 aleksis/core/templates/core/group/full.html:55
+#: aleksis/core/models.py:433 aleksis/core/templates/core/group/full.html:55
 msgid "Parent groups"
 msgstr "Ãœbergeordnete Gruppen"
 
-#: aleksis/core/models.py:424
+#: aleksis/core/models.py:441
 msgid "Type of group"
 msgstr "Gruppentyp"
 
-#: aleksis/core/models.py:542
+#: aleksis/core/models.py:559
 msgid "User"
 msgstr "Benutzer"
 
-#: aleksis/core/models.py:545 aleksis/core/models.py:569
-#: aleksis/core/models.py:654
+#: aleksis/core/models.py:562 aleksis/core/models.py:586
+#: aleksis/core/models.py:671
 #: aleksis/core/templates/core/announcement/list.html:18
 msgid "Title"
 msgstr "Titel"
 
-#: aleksis/core/models.py:548
+#: aleksis/core/models.py:565
 msgid "Application"
 msgstr "Anwendung"
 
-#: aleksis/core/models.py:554
+#: aleksis/core/models.py:571
 msgid "Activity"
 msgstr "Aktivität"
 
-#: aleksis/core/models.py:555
+#: aleksis/core/models.py:572
 msgid "Activities"
 msgstr "Aktivitäten"
 
-#: aleksis/core/models.py:561
+#: aleksis/core/models.py:578
 msgid "Sender"
 msgstr "Absender"
 
-#: aleksis/core/models.py:566
+#: aleksis/core/models.py:583
 msgid "Recipient"
 msgstr "Empfänger"
 
-#: aleksis/core/models.py:571 aleksis/core/models.py:911
+#: aleksis/core/models.py:588 aleksis/core/models.py:928
 msgid "Link"
 msgstr "Link"
 
-#: aleksis/core/models.py:573
+#: aleksis/core/models.py:590
 msgid "Read"
 msgstr "Gelesen"
 
-#: aleksis/core/models.py:574
+#: aleksis/core/models.py:591
 msgid "Sent"
 msgstr "Versandt"
 
-#: aleksis/core/models.py:587
+#: aleksis/core/models.py:604
 msgid "Notification"
 msgstr "Benachrichtigung"
 
-#: aleksis/core/models.py:656
+#: aleksis/core/models.py:673
 msgid "Link to detailed view"
 msgstr "Link zur detaillierten Ansicht"
 
-#: aleksis/core/models.py:659
+#: aleksis/core/models.py:676
 msgid "Date and time from when to show"
 msgstr "Datum und Uhrzeit des Anzeigestarts"
 
-#: aleksis/core/models.py:662
+#: aleksis/core/models.py:679
 msgid "Date and time until when to show"
 msgstr "Anzeigezeitraum"
 
-#: aleksis/core/models.py:686
+#: aleksis/core/models.py:703
 msgid "Announcement"
 msgstr "Ankündigung"
 
-#: aleksis/core/models.py:724
+#: aleksis/core/models.py:741
 msgid "Announcement recipient"
 msgstr "Empfänger der Ankündigung"
 
-#: aleksis/core/models.py:725
+#: aleksis/core/models.py:742
 msgid "Announcement recipients"
 msgstr "Empfänger der Ankündigung"
 
-#: aleksis/core/models.py:780
+#: aleksis/core/models.py:797
 msgid "Widget Title"
 msgstr "Widget-Titel"
 
-#: aleksis/core/models.py:781
+#: aleksis/core/models.py:798
 msgid "Activate Widget"
 msgstr "Widget aktivieren"
 
-#: aleksis/core/models.py:782
+#: aleksis/core/models.py:799
 msgid "Widget is broken"
 msgstr "Widget ist kaputt"
 
-#: aleksis/core/models.py:785
+#: aleksis/core/models.py:802
 msgid "Size on mobile devices"
 msgstr "Größe auf Mobilgeräten"
 
-#: aleksis/core/models.py:786
+#: aleksis/core/models.py:803
 msgid "<= 600 px, 12 columns"
 msgstr "<= 600 px, 12 Spalten"
 
-#: aleksis/core/models.py:791
+#: aleksis/core/models.py:808
 msgid "Size on tablet devices"
 msgstr "Größe auf Tablets"
 
-#: aleksis/core/models.py:792
+#: aleksis/core/models.py:809
 msgid "> 600 px, 12 columns"
 msgstr "> 600px, 12 Spalten"
 
-#: aleksis/core/models.py:797
+#: aleksis/core/models.py:814
 msgid "Size on desktop devices"
 msgstr "Größe auf Desktopgeräten"
 
-#: aleksis/core/models.py:798
+#: aleksis/core/models.py:815
 msgid "> 992 px, 12 columns"
 msgstr "> 992 px, 12 Spalten"
 
-#: aleksis/core/models.py:803
+#: aleksis/core/models.py:820
 msgid "Size on large desktop devices"
 msgstr "Größe auf großen Desktopgeräten"
 
-#: aleksis/core/models.py:804
+#: aleksis/core/models.py:821
 msgid "> 1200 px>, 12 columns"
 msgstr "> 1200 px, 12 Spalten"
 
-#: aleksis/core/models.py:835
+#: aleksis/core/models.py:852
 msgid "Can edit default dashboard"
 msgstr "Kann Standarddashboard bearbeiten"
 
-#: aleksis/core/models.py:836
+#: aleksis/core/models.py:853
 msgid "Dashboard Widget"
 msgstr "Dashboard-Widget"
 
-#: aleksis/core/models.py:837
+#: aleksis/core/models.py:854
 msgid "Dashboard Widgets"
 msgstr "Dashboard-Widgets"
 
-#: aleksis/core/models.py:843
+#: aleksis/core/models.py:860
 msgid "URL"
 msgstr "URL"
 
-#: aleksis/core/models.py:844
+#: aleksis/core/models.py:861
 msgid "Icon URL"
 msgstr "Symbol-URL"
 
-#: aleksis/core/models.py:850
+#: aleksis/core/models.py:867
 msgid "External link widget"
 msgstr "Externer-Link-Widget"
 
-#: aleksis/core/models.py:851
+#: aleksis/core/models.py:868
 msgid "External link widgets"
 msgstr "Externer-Link-Widgets"
 
-#: aleksis/core/models.py:856
+#: aleksis/core/models.py:873
 msgid "Dashboard widget"
 msgstr "Dashboard-Widget"
 
-#: aleksis/core/models.py:861
+#: aleksis/core/models.py:878
 msgid "Order"
 msgstr "Reihenfolge"
 
-#: aleksis/core/models.py:862
+#: aleksis/core/models.py:879
 msgid "Part of the default dashboard"
 msgstr "Teil des Standarddashboards"
 
-#: aleksis/core/models.py:877
+#: aleksis/core/models.py:894
 msgid "Dashboard widget order"
 msgstr "Reihenfolge der Dashboard-Widgets"
 
-#: aleksis/core/models.py:878
+#: aleksis/core/models.py:895
 msgid "Dashboard widget orders"
 msgstr "Reihenfolgen der Dashboard-Widgets"
 
-#: aleksis/core/models.py:884
+#: aleksis/core/models.py:901
 msgid "Menu ID"
 msgstr "Menü-ID"
 
-#: aleksis/core/models.py:897
+#: aleksis/core/models.py:914
 msgid "Custom menu"
 msgstr "Benutzerdefiniertes Menü"
 
-#: aleksis/core/models.py:898
+#: aleksis/core/models.py:915
 msgid "Custom menus"
 msgstr "Benutzerdefinierte Menüs"
 
-#: aleksis/core/models.py:908
+#: aleksis/core/models.py:925
 msgid "Menu"
 msgstr "Menü"
 
-#: aleksis/core/models.py:912
+#: aleksis/core/models.py:929
 msgid "Icon"
 msgstr "Symbol"
 
-#: aleksis/core/models.py:918
+#: aleksis/core/models.py:935
 msgid "Custom menu item"
 msgstr "Benutzerdefiniertes Menüelement"
 
-#: aleksis/core/models.py:919
+#: aleksis/core/models.py:936
 msgid "Custom menu items"
 msgstr "Benutzerdefinierte Menüelemente"
 
-#: aleksis/core/models.py:933
+#: aleksis/core/models.py:950
 msgid "Title of type"
 msgstr "Titel des Typs"
 
-#: aleksis/core/models.py:940 aleksis/core/templates/core/group/full.html:47
+#: aleksis/core/models.py:957 aleksis/core/templates/core/group/full.html:47
 msgid "Group type"
 msgstr "Gruppentyp"
 
-#: aleksis/core/models.py:954
+#: aleksis/core/models.py:971
 msgid "Can view system status"
 msgstr "Kann Systemstatus sehen"
 
-#: aleksis/core/models.py:955
-msgid "Can link persons to accounts"
-msgstr "Kann Personen mit Benutzerkonten verknüpfen"
-
-#: aleksis/core/models.py:956
+#: aleksis/core/models.py:972
 msgid "Can manage data"
 msgstr "Kann Daten verwalten"
 
-#: aleksis/core/models.py:957
+#: aleksis/core/models.py:973
 msgid "Can impersonate"
 msgstr "Kann sich verkleiden"
 
-#: aleksis/core/models.py:958
+#: aleksis/core/models.py:974
 msgid "Can use search"
 msgstr "Kann Suche benutzen"
 
-#: aleksis/core/models.py:959
+#: aleksis/core/models.py:975
 msgid "Can change site preferences"
 msgstr "Kann Konfiguration ändern"
 
-#: aleksis/core/models.py:960
+#: aleksis/core/models.py:976
 msgid "Can change person preferences"
 msgstr "Kann Einstellungen einer Person verändern"
 
-#: aleksis/core/models.py:961
+#: aleksis/core/models.py:977
 msgid "Can change group preferences"
 msgstr "Kann Einstellungen einer Gruppe verändern"
 
-#: aleksis/core/models.py:962
+#: aleksis/core/models.py:978
 msgid "Can add oauth applications"
 msgstr "Kann OAuth-Anwendungen hinzufügen"
 
-#: aleksis/core/models.py:963
+#: aleksis/core/models.py:979
 msgid "Can list oauth applications"
 msgstr "Can OAuth-Anwendungen auflisten"
 
-#: aleksis/core/models.py:964
+#: aleksis/core/models.py:980
 msgid "Can view oauth applications"
 msgstr "Kann OAuth-Anwendungen sehen"
 
-#: aleksis/core/models.py:965
+#: aleksis/core/models.py:981
 msgid "Can update oauth applications"
 msgstr "Kann OAuth-Anwendungen aktualisieren"
 
-#: aleksis/core/models.py:966
+#: aleksis/core/models.py:982
 msgid "Can delete oauth applications"
 msgstr "Kann OAuth-Anwendungen löschen"
 
-#: aleksis/core/models.py:967
+#: aleksis/core/models.py:983
 msgid "Can test PDF generation"
 msgstr "Kann die PDF-Generierung testen"
 
-#: aleksis/core/models.py:1003
+#: aleksis/core/models.py:1019
 msgid "Related data check task"
 msgstr "Zugehörige Datenprüfungsaufgabe"
 
-#: aleksis/core/models.py:1011
+#: aleksis/core/models.py:1027
 msgid "Issue solved"
 msgstr "Problem gelöst"
 
-#: aleksis/core/models.py:1012
+#: aleksis/core/models.py:1028
 msgid "Notification sent"
 msgstr "Benachrichtigung gesendet"
 
-#: aleksis/core/models.py:1025
+#: aleksis/core/models.py:1041
 msgid "Data check result"
 msgstr "Datenprüfungsergebnis"
 
-#: aleksis/core/models.py:1026
+#: aleksis/core/models.py:1042
 msgid "Data check results"
 msgstr "Datenprüfungsergebnisse"
 
-#: aleksis/core/models.py:1028
+#: aleksis/core/models.py:1044
 msgid "Can run data checks"
 msgstr "Kann Datenprüfungen ausführen"
 
-#: aleksis/core/models.py:1029
+#: aleksis/core/models.py:1045
 msgid "Can solve data check problems"
 msgstr "Kann Datenprüfungsprobleme lösen"
 
-#: aleksis/core/models.py:1044
+#: aleksis/core/models.py:1060
 msgid "Owner"
 msgstr "Leiter"
 
-#: aleksis/core/models.py:1048
+#: aleksis/core/models.py:1064
 msgid "File expires at"
 msgstr "Datei abgelaufen am"
 
-#: aleksis/core/models.py:1050
+#: aleksis/core/models.py:1066
 msgid "Generated HTML file"
 msgstr "Generierte HTML-Datei"
 
-#: aleksis/core/models.py:1052
+#: aleksis/core/models.py:1068
 msgid "Generated PDF file"
 msgstr "Generierte PDF-Datei"
 
-#: aleksis/core/models.py:1059
+#: aleksis/core/models.py:1075
 msgid "PDF file"
 msgstr "PDF-Datei"
 
-#: aleksis/core/models.py:1060
+#: aleksis/core/models.py:1076
 msgid "PDF files"
 msgstr "PDF-Dateien"
 
-#: aleksis/core/models.py:1065
+#: aleksis/core/models.py:1081
 msgid "Task result"
 msgstr "Task-Ergebnis"
 
-#: aleksis/core/models.py:1068
+#: aleksis/core/models.py:1084
 msgid "Task user"
 msgstr "Task-Benutzer"
 
-#: aleksis/core/models.py:1080
+#: aleksis/core/models.py:1096
 msgid "Task user assignment"
 msgstr "Task-Benutzer-Zuordnung"
 
-#: aleksis/core/models.py:1081
+#: aleksis/core/models.py:1097
 msgid "Task user assignments"
 msgstr "Task-Benutzer-Zuordnungen"
 
@@ -1029,77 +1020,71 @@ msgstr "Sichtbarer Name der Schule"
 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:256
-msgid "Enabled custom authentication backends"
-msgstr "Benutzerdefinierte Authentifizierungsbackends aktivieren"
-
-#: aleksis/core/preferences.py:268
+#: aleksis/core/preferences.py:254
 msgid "Allow users to change their passwords"
 msgstr "Erlaube Benutzern, ihr Passwort zu ändern"
 
-#: aleksis/core/preferences.py:276
+#: aleksis/core/preferences.py:262
 msgid "Enable signup"
 msgstr "Registrierung aktivieren"
 
-#: aleksis/core/preferences.py:287
+#: aleksis/core/preferences.py:273
 msgid "Available languages"
 msgstr "Verfügbare Sprachen"
 
-#: aleksis/core/preferences.py:299
+#: aleksis/core/preferences.py:285
 msgid "Send emails if data checks detect problems"
 msgstr "E-Mails versenden, wenn Datenprüfungen Probleme finden"
 
-#: aleksis/core/preferences.py:310
+#: aleksis/core/preferences.py:296
 msgid "Email recipients for data checks problem emails"
 msgstr "E-Mailempfänger für Datenprüfungsproblem-E-Mails"
 
-#: aleksis/core/preferences.py:321
+#: aleksis/core/preferences.py:307
 msgid "Email recipient groups for data checks problem emails"
 msgstr "E-Mail-Empfängergruppen für Datenprüfungsproblem-E-Mails"
 
-#: aleksis/core/preferences.py:330
+#: aleksis/core/preferences.py:316
 msgid "Show dashboard to users without login"
 msgstr "Zeige Dashboard für Benutzer ohne Login"
 
-#: aleksis/core/preferences.py:339
+#: aleksis/core/preferences.py:325
 msgid "Allow users to edit their dashboard"
 msgstr "Erlaube Benutzern, ihr Dashboard zu bearbeiten"
 
-#: aleksis/core/preferences.py:350
+#: aleksis/core/preferences.py:336
 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:364
+#: aleksis/core/preferences.py:350
 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:377
+#: aleksis/core/preferences.py:363
 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:387
+#: aleksis/core/preferences.py:373
 msgid "PDF file expiration duration"
 msgstr "PDF-Datei-Ablaufdauer"
 
-#: aleksis/core/preferences.py:388
+#: aleksis/core/preferences.py:374
 msgid "in minutes"
 msgstr "in Minuten"
 
-#: aleksis/core/preferences.py:398
+#: aleksis/core/preferences.py:384
 msgid "Automatically update the dashboard and its widgets"
 msgstr "Automatisch das Dashboard und seine Widgets aktualisieren"
 
-#: aleksis/core/preferences.py:408
+#: aleksis/core/preferences.py:394
 msgid "Automatically update the dashboard and its widgets sitewide"
-msgstr ""
-"Automatisch das Dashboard und seine Widgets aktualisieren (auf der ganzen "
-"Seite)"
+msgstr "Automatisch das Dashboard und seine Widgets aktualisieren (auf der ganzen Seite)"
 
-#: aleksis/core/settings.py:468
+#: aleksis/core/settings.py:452
 msgid "English"
 msgstr "Englisch"
 
-#: aleksis/core/settings.py:469
+#: aleksis/core/settings.py:453
 msgid "German"
 msgstr "Deutsch"
 
@@ -1294,7 +1279,7 @@ msgstr ""
 #: aleksis/core/templates/account/password_reset_done.html:5
 #: aleksis/core/templates/account/verification_email_required.html:5
 #: aleksis/core/templates/account/verification_email_required.html:6
-#: aleksis/core/templates/two_factor/core/login.html:100
+#: aleksis/core/templates/two_factor/core/login.html:81
 msgid "Reset password"
 msgstr "Passwort zurücksetzen"
 
@@ -2144,39 +2129,11 @@ msgstr ""
 "        die Verwaltenden von AlekSIS an Ihrer Schule.\n"
 "          "
 
-#: aleksis/core/templates/core/person/accounts.html:12
-#: aleksis/core/templates/core/person/accounts.html:14
-msgid "Link persons to accounts"
-msgstr "Personen mit Benutzerkonten verknüpfen"
-
-#: aleksis/core/templates/core/person/accounts.html:21
-msgid ""
-"\n"
-"        You can use this form to assign user accounts to persons. Use the\n"
-"        dropdowns to select existing accounts; use the text fields to create new\n"
-"        accounts on-the-fly. The latter will create a new account with the\n"
-"        entered username and copy all other details from the person.\n"
-"      "
-msgstr ""
-"\n"
-"        Sie können dieses Formular nutzen, um Benutzerkonten Personen zuzuweisen. Nutzen Sie das\n"
-"    Auswahlfeld um ein existierendes Benutzerkonto auszuwählen; nutzen Sie das Textfeld, um einen neuen Benutzer zu\n"
-"    erstellen. Letzteres erstellt ein neues Benutzerkonto mit dem\n"
-"    eingegebenen Benutzernamen und kopiert alle anderen Daten der Person.\n"
-"      "
-
-#: aleksis/core/templates/core/person/accounts.html:36
-#: aleksis/core/templates/core/person/accounts.html:60
-msgid "Update"
-msgstr "Aktualisieren"
-
-#: aleksis/core/templates/core/person/accounts.html:42
-msgid "Existing account"
-msgstr "Existierendes Konto"
-
-#: aleksis/core/templates/core/person/accounts.html:43
-msgid "New account"
-msgstr "Neues Konto"
+#: aleksis/core/templates/core/person/create.html:12
+#: aleksis/core/templates/core/person/create.html:13
+#: aleksis/core/templates/core/person/list.html:17
+msgid "Create person"
+msgstr "Person erstellen"
 
 #: aleksis/core/templates/core/person/edit.html:12
 #: aleksis/core/templates/core/person/edit.html:13
@@ -2184,6 +2141,8 @@ msgid "Edit person"
 msgstr "Person editieren"
 
 #: aleksis/core/templates/core/person/full.html:44
+#: aleksis/core/templates/impersonate/list_users.html:7
+#: aleksis/core/templates/impersonate/list_users.html:8
 msgid "Impersonate"
 msgstr "Verkleiden"
 
@@ -2195,10 +2154,6 @@ msgstr "Kontaktdetails"
 msgid "Children"
 msgstr "Kinder"
 
-#: aleksis/core/templates/core/person/list.html:17
-msgid "Create person"
-msgstr "Person erstellen"
-
 #: aleksis/core/templates/core/person/list.html:21
 msgid "Filter persons"
 msgstr "Personen filtern"
@@ -2235,10 +2190,6 @@ msgstr "Einstellungen für %(instance)s"
 msgid "Save preferences"
 msgstr "Einstellungen speichern"
 
-#: aleksis/core/templates/impersonate/list_users.html:8
-msgid "Impersonate user"
-msgstr "Als Benutzer verkleiden"
-
 #: aleksis/core/templates/oauth2_provider/application_confirm_delete.html:5
 #: aleksis/core/templates/oauth2_provider/application_confirm_delete.html:6
 msgid "Delete application"
@@ -2645,81 +2596,91 @@ msgstr "Zurück zur Kontosicherheit"
 msgid "Generate Tokens"
 msgstr "Tokens generieren"
 
-#: aleksis/core/templates/two_factor/core/login.html:18
+#: aleksis/core/templates/two_factor/core/login.html:20
 msgid "Login with username and password"
 msgstr "Anmeldung mit Benutzername und Passwort"
 
-#: aleksis/core/templates/two_factor/core/login.html:26
-msgid "You have no permission to view this page. Please login with an other account."
-msgstr "Sie haben nicht die nötigen Berechtigungen, um diese Seite aufzurufen. Bitte loggen Sie sich mit einem anderen Account ein."
+#: aleksis/core/templates/two_factor/core/login.html:28
+msgid ""
+"You have no permission to view this page. Please login with an other\n"
+"                    account."
+msgstr ""
+"Sie haben keine Berichtigung, um diese Seite aufzurufen. \n"
+"Bitte loggen Sie sich mit einem anderen Account ein."
 
-#: aleksis/core/templates/two_factor/core/login.html:33
+#: aleksis/core/templates/two_factor/core/login.html:36
 msgid "Please login to see this page."
 msgstr "Bitte melden Sie sich an, um diese Seite zu sehen."
 
-#: aleksis/core/templates/two_factor/core/login.html:43
+#: aleksis/core/templates/two_factor/core/login.html:46
 msgid ""
 "\n"
-"                      We are calling your phone right now, please enter the\n"
-"                      digits you hear.\n"
-"                    "
+"                        We are calling your phone right now, please enter the\n"
+"                        digits you hear.\n"
+"                      "
 msgstr ""
 "\n"
-"                      Wir rufen Ihr Telefon jetzt an, \n"
+"                        Wir rufen Ihr Telefon jetzt an, \n"
 "            bitte geben Sie die Zahlen ein, die Sie hören.\n"
-"                    "
+"                      "
 
-#: aleksis/core/templates/two_factor/core/login.html:48
+#: aleksis/core/templates/two_factor/core/login.html:51
 msgid ""
 "\n"
-"                      We sent you a text message, please enter the tokens we\n"
-"                      sent.\n"
-"                    "
+"                        We sent you a text message, please enter the tokens we\n"
+"                        sent.\n"
+"                      "
 msgstr ""
 "\n"
-"                      Wir haben Ihnen per SMS einen Token geschickt, \n"
-"            bitte geben Sie diesen ein.\n"
-"                    "
+"                        Wir haben Ihnen eine SMS geschickt, \n"
+"            bitte geben Sie die Token ein, die wir geschickt haben.\n"
+"                      "
 
-#: aleksis/core/templates/two_factor/core/login.html:53
+#: aleksis/core/templates/two_factor/core/login.html:56
 msgid ""
 "\n"
-"                      Please enter the tokens generated by your token\n"
-"                      generator.\n"
-"                    "
+"                        Please enter the tokens generated by your token\n"
+"                        generator.\n"
+"                      "
 msgstr ""
 "\n"
-"                      Bitte geben Sie den von Ihrem Token-Generator\n"
+"                        Bitte geben Sie den von Ihrem Token-Generator\n"
 "              generierten Token ein.\n"
-"                    "
+"                      "
 
-#: aleksis/core/templates/two_factor/core/login.html:59
+#: aleksis/core/templates/two_factor/core/login.html:62
 msgid ""
 "\n"
-"                    Use this form for entering backup tokens for logging in.\n"
-"                    These tokens have been generated for you to print and keep safe. Please\n"
-"                    enter one of these backup tokens to login to your account.\n"
-"                  "
+"                      Use this form for entering backup tokens for logging in.\n"
+"                      These tokens have been generated for you to print and keep safe. Please\n"
+"                      enter one of these backup tokens to login to your account.\n"
+"                    "
 msgstr ""
 "\n"
-"                    Nutzen Sie dieses Formular um Ihre Backup-Tokens zum Anmelden einzugeben.\n"
-"                Diese Tokens wurden für Sie generiert, um diese gut aufzubewahren. Bitte\n"
+"                      Nutzen Sie dieses Formular um Ihre Backup-Tokens zum "
+"Anmelden einzugeben.\n"
+"                Diese Tokens wurden für Sie generiert, um diese gut "
+"aufzubewahren. Bitte\n"
 "                geben Sie einen dieser Tokens ein, um sich einzuloggen.\n"
-"                  "
+"                    "
 
-#: aleksis/core/templates/two_factor/core/login.html:74
+#: aleksis/core/templates/two_factor/core/login.html:90
+msgid "Device currently not available?"
+msgstr "Gerät aktuell nicht verfügbar?"
+
+#: aleksis/core/templates/two_factor/core/login.html:92
 msgid "Or, alternatively, use one of your backup phones:"
 msgstr "Oder, alternativ, nutzen Sie eins Ihrer Backup-Telefone:"
 
-#: aleksis/core/templates/two_factor/core/login.html:84
+#: aleksis/core/templates/two_factor/core/login.html:102
 msgid "As a last resort, you can use a backup token:"
 msgstr "Als letzte Möglichkeit können Sie einen Backup-Token nutzen:"
 
-#: aleksis/core/templates/two_factor/core/login.html:87
+#: aleksis/core/templates/two_factor/core/login.html:105
 msgid "Use Backup Token"
 msgstr "Backup-Token nutzen"
 
-#: aleksis/core/templates/two_factor/core/login.html:110
+#: aleksis/core/templates/two_factor/core/login.html:116
 msgid "Use alternative login options"
 msgstr "Alternative Anmeldemöglichkeiten nutzen"
 
@@ -2849,7 +2810,8 @@ msgid ""
 "          "
 msgstr ""
 "\n"
-"            Wir haben Ihnen per SMS einen Token geschickt, bitte geben Sie diesen ein.\n"
+"            Wir haben Ihnen eine SMS geschickt, bitte geben Sie die Tokens "
+"ein, die wir geschickt haben.\n"
 "          "
 
 #: aleksis/core/templates/two_factor/core/setup.html:63
@@ -3060,111 +3022,150 @@ msgstr "Es ist ein Fehler beim Generieren der PDF-Datei aufgetreten."
 msgid "Download PDF"
 msgstr "PDF herunterladen"
 
-#: aleksis/core/views.py:253
+#: aleksis/core/views.py:251
 msgid "The school term has been created."
 msgstr "Das Schuljahr wurde erstellt."
 
-#: aleksis/core/views.py:265
+#: aleksis/core/views.py:263
 msgid "The school term has been saved."
 msgstr "Das Schuljahr wurde gespeichert."
 
-#: aleksis/core/views.py:410
+#: aleksis/core/views.py:387
 msgid "The child groups were successfully saved."
 msgstr "Die Untergruppen wurden gespeichert."
 
-#: aleksis/core/views.py:471
+#: aleksis/core/views.py:406 aleksis/core/views.py:416
 msgid "The person has been saved."
 msgstr "Die Person wurde gespeichert."
 
-#: aleksis/core/views.py:510
+#: aleksis/core/views.py:466
 msgid "The group has been saved."
 msgstr "Die Gruppe wurde gespeichert."
 
-#: aleksis/core/views.py:607
+#: aleksis/core/views.py:563
 msgid "The announcement has been saved."
 msgstr "Die Ankündigung wurde gespeichert."
 
-#: aleksis/core/views.py:623
+#: aleksis/core/views.py:579
 msgid "The announcement has been deleted."
 msgstr "Ankündigung wurde gelöscht."
 
-#: aleksis/core/views.py:707
+#: aleksis/core/views.py:663
 msgid "The preferences have been saved successfully."
 msgstr "Die Einstellungen wurde gespeichert."
 
-#: aleksis/core/views.py:731
+#: aleksis/core/views.py:687
 msgid "The person has been deleted."
 msgstr "Die Person wurde gelöscht."
 
-#: aleksis/core/views.py:745
+#: aleksis/core/views.py:701
 msgid "The group has been deleted."
 msgstr "Die Gruppe wurde gelöscht."
 
-#: aleksis/core/views.py:777
+#: aleksis/core/views.py:733
 msgid "The additional_field has been saved."
 msgstr "Das zusätzliche Feld wurde gespeichert."
 
-#: aleksis/core/views.py:811
+#: aleksis/core/views.py:767
 msgid "The additional field has been deleted."
 msgstr "Das zusätzliche Feld wurde gelöscht."
 
-#: aleksis/core/views.py:836
+#: aleksis/core/views.py:792
 msgid "The group type has been saved."
 msgstr "Der Gruppentyp wurde gespeichert."
 
-#: aleksis/core/views.py:866
+#: aleksis/core/views.py:822
 msgid "The group type has been deleted."
 msgstr "Der Gruppentyp wurde gelöscht."
 
-#: aleksis/core/views.py:899
+#: aleksis/core/views.py:855
 msgid "Progress: Run data checks"
 msgstr "Fortschritt: Datenprüfungen ausführen"
 
-#: aleksis/core/views.py:900
+#: aleksis/core/views.py:856
 msgid "Run data checks …"
 msgstr "Datenprüfungen laufen …"
 
-#: aleksis/core/views.py:901
+#: aleksis/core/views.py:857
 msgid "The data checks were run successfully."
 msgstr "Die Datenprüfungen wurden erfolgreich ausgeführt."
 
-#: aleksis/core/views.py:902
+#: aleksis/core/views.py:858
 msgid "There was a problem while running data checks."
 msgstr "Es gab ein Problem beim Ausführen der Datenprüfungen."
 
-#: aleksis/core/views.py:918
+#: aleksis/core/views.py:874
 #, python-brace-format
 msgid "The solve option '{solve_option_obj.verbose_name}' "
 msgstr "Die Lösungsoption \"{solve_option_obj.verbose_name}\" "
 
-#: aleksis/core/views.py:960
+#: aleksis/core/views.py:916
 msgid "The dashboard widget has been saved."
 msgstr "Das Dashboard-Widget wurde gespeichert."
 
-#: aleksis/core/views.py:990
+#: aleksis/core/views.py:946
 msgid "The dashboard widget has been created."
 msgstr "Das Dashboard-Widget wurde erstellt."
 
-#: aleksis/core/views.py:1000
+#: aleksis/core/views.py:956
 msgid "The dashboard widget has been deleted."
 msgstr "Das Dashboard-Widget wurde gelöscht."
 
-#: aleksis/core/views.py:1067
+#: aleksis/core/views.py:1023
 msgid "Your dashboard configuration has been saved successfully."
 msgstr "Ihre Dashboardkonfiguration wurde erfolgreich gespeichert."
 
-#: aleksis/core/views.py:1069
+#: aleksis/core/views.py:1025
 msgid "The configuration of the default dashboard has been saved successfully."
 msgstr "Die Konfiguration des Standard-Dashboardes wurde erfolgreich gespeichert."
 
-#: aleksis/core/views.py:1197
+#: aleksis/core/views.py:1153
 msgid "The third-party account could not be disconnected because it is the only login method available."
 msgstr "Das Drittanbieter-Konto konnte nicht deaktiviert werden, weil es die einzige verfügbare Anmeldeoption ist."
 
-#: aleksis/core/views.py:1204
+#: aleksis/core/views.py:1160
 msgid "The third-party account has been successfully disconnected."
 msgstr "Das Drittanbieter-Konto wurde erfolgreich getrennt."
 
+#~ msgid "Persons and accounts"
+#~ msgstr "Personen und Konten"
+
+#~ msgid "Can link persons to accounts"
+#~ msgstr "Kann Personen mit Benutzerkonten verknüpfen"
+
+#~ msgid "Enabled custom authentication backends"
+#~ msgstr "Benutzerdefinierte Authentifizierungsbackends aktivieren"
+
+#~ msgid "Link persons to accounts"
+#~ msgstr "Personen mit Benutzerkonten verknüpfen"
+
+#~ msgid ""
+#~ "\n"
+#~ "        You can use this form to assign user accounts to persons. Use the\n"
+#~ "        dropdowns to select existing accounts; use the text fields to create new\n"
+#~ "        accounts on-the-fly. The latter will create a new account with the\n"
+#~ "        entered username and copy all other details from the person.\n"
+#~ "      "
+#~ msgstr ""
+#~ "\n"
+#~ "        Sie können dieses Formular nutzen, um Benutzerkonten Personen zuzuweisen. Nutzen Sie das\n"
+#~ "    Auswahlfeld um ein existierendes Benutzerkonto auszuwählen; nutzen Sie das Textfeld, um einen neuen Benutzer zu\n"
+#~ "    erstellen. Letzteres erstellt ein neues Benutzerkonto mit dem\n"
+#~ "    eingegebenen Benutzernamen und kopiert alle anderen Daten der Person.\n"
+#~ "      "
+
+#~ msgid "Update"
+#~ msgstr "Aktualisieren"
+
+#~ msgid "Existing account"
+#~ msgstr "Existierendes Konto"
+
+#~ msgid "New account"
+#~ msgstr "Neues Konto"
+
+#~ msgid "Impersonate user"
+#~ msgstr "Als Benutzer verkleiden"
+
 #~ msgid "Authorized tokens"
 #~ msgstr "Autorisierte Tokens"
 
diff --git a/aleksis/core/locale/de_DE/LC_MESSAGES/djangojs.po b/aleksis/core/locale/de_DE/LC_MESSAGES/djangojs.po
index e10a495775fcb643cbe11cc1ce0daf4c5fc649ef..6bbb636d795adbbe19acdf95ed873b27814d9284 100644
--- a/aleksis/core/locale/de_DE/LC_MESSAGES/djangojs.po
+++ b/aleksis/core/locale/de_DE/LC_MESSAGES/djangojs.po
@@ -3,32 +3,36 @@
 # This file is distributed under the same license as the PACKAGE package.
 # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
 #
-#, fuzzy
 msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2021-08-28 17:53+0200\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"
-"Language: \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"
+"Language: de_DE\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Weblate 4.8\n"
 
 #: aleksis/core/static/js/main.js:15
 msgid "Today"
-msgstr ""
+msgstr "Heute"
 
 #: aleksis/core/static/js/main.js:16
 msgid "Cancel"
-msgstr ""
+msgstr "Abbrechen"
 
 #: aleksis/core/static/js/main.js:17
 msgid "OK"
-msgstr ""
+msgstr "OK"
 
 #: aleksis/core/static/js/main.js:127
 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 1474f2840f186c7492954d6897652557d18f5976..3c118dd9a39119c4615e68b5f729d60de3726bff 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: 2021-08-28 17:53+0200\n"
+"POT-Creation-Date: 2021-10-28 16:18+0200\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,25 +18,25 @@ msgstr ""
 "Plural-Forms: nplurals=2; plural=n > 1;\n"
 "X-Generator: Weblate 4.4\n"
 
-#: aleksis/core/apps.py:148 aleksis/core/settings.py:343
+#: aleksis/core/apps.py:150
 msgid "OpenID Connect scope"
 msgstr ""
 
-#: aleksis/core/apps.py:149 aleksis/core/settings.py:344
+#: aleksis/core/apps.py:151
 msgid "Given name, family name, link to profile and picture if existing."
 msgstr ""
 
-#: aleksis/core/apps.py:150 aleksis/core/settings.py:345
+#: aleksis/core/apps.py:152
 msgid "Full home postal address"
 msgstr ""
 
-#: aleksis/core/apps.py:151 aleksis/core/settings.py:346
+#: aleksis/core/apps.py:153
 #, fuzzy
 #| msgid "Contact details"
 msgid "Email address"
 msgstr "Détails de contact"
 
-#: aleksis/core/apps.py:152 aleksis/core/settings.py:347
+#: aleksis/core/apps.py:154
 msgid "Home and mobile phone"
 msgstr ""
 
@@ -80,54 +80,54 @@ msgstr ""
 msgid "Search by contact details"
 msgstr "Détails de contact"
 
-#: aleksis/core/forms.py:62
-msgid "You cannot set a new username when also selecting an existing user."
-msgstr ""
-
-#: aleksis/core/forms.py:66
-msgid "This username is already in use."
-msgstr "Cet nom est deja en utilisation."
-
-#: aleksis/core/forms.py:90 aleksis/core/forms.py:412
+#: aleksis/core/forms.py:41 aleksis/core/forms.py:387
 msgid "Base data"
 msgstr ""
 
-#: aleksis/core/forms.py:96
+#: aleksis/core/forms.py:47
 msgid "Address"
 msgstr ""
 
-#: aleksis/core/forms.py:97
+#: aleksis/core/forms.py:48
 #, fuzzy
 #| msgid "Contact details"
 msgid "Contact data"
 msgstr "Détails de contact"
 
-#: aleksis/core/forms.py:99
+#: aleksis/core/forms.py:50
 #, fuzzy
 #| msgid "Contact details"
 msgid "Advanced personal data"
 msgstr "Détails de contact"
 
-#: aleksis/core/forms.py:142
+#: aleksis/core/forms.py:93
 msgid "New user"
 msgstr ""
 
-#: aleksis/core/forms.py:142
+#: aleksis/core/forms.py:93
 msgid "Create a new account"
 msgstr ""
 
-#: aleksis/core/forms.py:170 aleksis/core/models.py:116
+#: aleksis/core/forms.py:124
+msgid "You cannot set a new username when also selecting an existing user."
+msgstr ""
+
+#: aleksis/core/forms.py:128
+msgid "This username is already in use."
+msgstr "Cet nom est deja en utilisation."
+
+#: aleksis/core/forms.py:145 aleksis/core/models.py:117
 msgid "School term"
 msgstr ""
 
-#: aleksis/core/forms.py:171
+#: aleksis/core/forms.py:146
 #, fuzzy
 #| msgid "Contact details"
 msgid "Common data"
 msgstr "Détails de contact"
 
-#: aleksis/core/forms.py:172 aleksis/core/forms.py:221
-#: aleksis/core/menus.py:238 aleksis/core/models.py:139
+#: aleksis/core/forms.py:147 aleksis/core/forms.py:196
+#: aleksis/core/menus.py:238 aleksis/core/models.py:140
 #: aleksis/core/templates/core/person/list.html:8
 #: aleksis/core/templates/core/person/list.html:9
 #, fuzzy
@@ -135,24 +135,24 @@ msgstr "Détails de contact"
 msgid "Persons"
 msgstr "Personne"
 
-#: aleksis/core/forms.py:173
+#: aleksis/core/forms.py:148
 #, fuzzy
 #| msgid "Contact details"
 msgid "Additional data"
 msgstr "Détails de contact"
 
-#: aleksis/core/forms.py:213 aleksis/core/forms.py:216
-#: aleksis/core/models.py:59
+#: aleksis/core/forms.py:188 aleksis/core/forms.py:191
+#: aleksis/core/models.py:60
 msgid "Date"
 msgstr "Date"
 
-#: aleksis/core/forms.py:214 aleksis/core/forms.py:217
-#: aleksis/core/models.py:67
+#: aleksis/core/forms.py:189 aleksis/core/forms.py:192
+#: aleksis/core/models.py:68
 msgid "Time"
 msgstr ""
 
-#: aleksis/core/forms.py:234 aleksis/core/menus.py:249
-#: aleksis/core/models.py:381 aleksis/core/templates/core/group/list.html:8
+#: aleksis/core/forms.py:209 aleksis/core/menus.py:249
+#: aleksis/core/models.py:398 aleksis/core/templates/core/group/list.html:8
 #: aleksis/core/templates/core/group/list.html:9
 #: aleksis/core/templates/core/person/full.html:144
 #, fuzzy
@@ -160,58 +160,58 @@ msgstr ""
 msgid "Groups"
 msgstr "Groupe"
 
-#: aleksis/core/forms.py:244
+#: aleksis/core/forms.py:219
 msgid "From when until when should the announcement be displayed?"
 msgstr ""
 
-#: aleksis/core/forms.py:247
+#: aleksis/core/forms.py:222
 msgid "Who should see the announcement?"
 msgstr ""
 
-#: aleksis/core/forms.py:248
+#: aleksis/core/forms.py:223
 msgid "Write your announcement:"
 msgstr ""
 
-#: aleksis/core/forms.py:287
+#: aleksis/core/forms.py:262
 msgid "You are not allowed to create announcements which are only valid in the past."
 msgstr ""
 
-#: aleksis/core/forms.py:291
+#: aleksis/core/forms.py:266
 msgid "The from date and time must be earlier then the until date and time."
 msgstr ""
 
-#: aleksis/core/forms.py:300
+#: aleksis/core/forms.py:275
 msgid "You need at least one recipient."
 msgstr ""
 
-#: aleksis/core/forms.py:414
+#: aleksis/core/forms.py:389
 #, fuzzy
 #| msgid "Contact details"
 msgid "Account data"
 msgstr "Détails de contact"
 
-#: aleksis/core/forms.py:416
+#: aleksis/core/forms.py:391
 msgid "Consents"
 msgstr ""
 
-#: aleksis/core/forms.py:421
+#: aleksis/core/forms.py:396
 msgid "Password"
 msgstr ""
 
-#: aleksis/core/forms.py:427
+#: aleksis/core/forms.py:402
 msgid "Password (again)"
 msgstr ""
 
-#: aleksis/core/forms.py:436
+#: aleksis/core/forms.py:411
 #, python-brace-format
 msgid "I have read the <a href='{privacy_policy}'>Privacy policy</a> and agree with them."
 msgstr ""
 
-#: aleksis/core/forms.py:460
+#: aleksis/core/forms.py:435
 msgid "You must type the same password each time."
 msgstr ""
 
-#: aleksis/core/forms.py:605
+#: aleksis/core/forms.py:580
 msgid "No valid selection."
 msgstr ""
 
@@ -242,8 +242,8 @@ msgid "{task.status} - {task.result}"
 msgstr ""
 
 #: aleksis/core/menus.py:9 aleksis/core/templates/two_factor/core/login.html:6
-#: aleksis/core/templates/two_factor/core/login.html:20
-#: aleksis/core/templates/two_factor/core/login.html:95
+#: aleksis/core/templates/two_factor/core/login.html:22
+#: aleksis/core/templates/two_factor/core/login.html:76
 msgid "Login"
 msgstr ""
 
@@ -256,7 +256,7 @@ msgstr ""
 msgid "Dashboard"
 msgstr ""
 
-#: aleksis/core/menus.py:32 aleksis/core/models.py:588
+#: aleksis/core/menus.py:32 aleksis/core/models.py:605
 #: aleksis/core/preferences.py:26
 #: aleksis/core/templates/core/notifications.html:4
 #: aleksis/core/templates/core/notifications.html:5
@@ -314,13 +314,13 @@ msgstr ""
 msgid "Admin"
 msgstr ""
 
-#: aleksis/core/menus.py:127 aleksis/core/models.py:687
+#: aleksis/core/menus.py:127 aleksis/core/models.py:704
 #: aleksis/core/templates/core/announcement/list.html:7
 #: aleksis/core/templates/core/announcement/list.html:8
 msgid "Announcements"
 msgstr ""
 
-#: aleksis/core/menus.py:138 aleksis/core/models.py:117
+#: aleksis/core/menus.py:138 aleksis/core/models.py:118
 #: aleksis/core/templates/core/school_term/list.html:8
 #: aleksis/core/templates/core/school_term/list.html:9
 msgid "School terms"
@@ -371,7 +371,7 @@ msgstr ""
 msgid "People"
 msgstr ""
 
-#: aleksis/core/menus.py:260 aleksis/core/models.py:941
+#: aleksis/core/menus.py:260 aleksis/core/models.py:958
 #: aleksis/core/templates/core/group_type/list.html:8
 #: aleksis/core/templates/core/group_type/list.html:9
 #, fuzzy
@@ -380,593 +380,582 @@ msgid "Group types"
 msgstr "Groupe"
 
 #: aleksis/core/menus.py:271
-msgid "Persons and accounts"
-msgstr ""
-
-#: aleksis/core/menus.py:282
 msgid "Groups and child groups"
 msgstr ""
 
-#: aleksis/core/menus.py:293 aleksis/core/models.py:429
+#: aleksis/core/menus.py:282 aleksis/core/models.py:446
 #: aleksis/core/templates/core/additional_field/list.html:8
 #: aleksis/core/templates/core/additional_field/list.html:9
 msgid "Additional fields"
 msgstr ""
 
-#: aleksis/core/menus.py:308
+#: aleksis/core/menus.py:297
 #: aleksis/core/templates/core/group/child_groups.html:7
 #: aleksis/core/templates/core/group/child_groups.html:9
 msgid "Assign child groups to groups"
 msgstr ""
 
-#: aleksis/core/mixins.py:475
+#: aleksis/core/mixins.py:498
 msgid "Linked school term"
 msgstr ""
 
-#: aleksis/core/models.py:57
+#: aleksis/core/models.py:58
 msgid "Boolean (Yes/No)"
 msgstr ""
 
-#: aleksis/core/models.py:58
+#: aleksis/core/models.py:59
 msgid "Text (one line)"
 msgstr ""
 
-#: aleksis/core/models.py:60
+#: aleksis/core/models.py:61
 msgid "Date and time"
 msgstr ""
 
-#: aleksis/core/models.py:61
+#: aleksis/core/models.py:62
 msgid "Decimal number"
 msgstr ""
 
-#: aleksis/core/models.py:62 aleksis/core/models.py:185
+#: aleksis/core/models.py:63 aleksis/core/models.py:186
 msgid "E-mail address"
 msgstr ""
 
-#: aleksis/core/models.py:63
+#: aleksis/core/models.py:64
 msgid "Integer"
 msgstr ""
 
-#: aleksis/core/models.py:64
+#: aleksis/core/models.py:65
 msgid "IP address"
 msgstr ""
 
-#: aleksis/core/models.py:65
+#: aleksis/core/models.py:66
 msgid "Boolean or empty (Yes/No/Neither)"
 msgstr ""
 
-#: aleksis/core/models.py:66
+#: aleksis/core/models.py:67
 msgid "Text (multi-line)"
 msgstr ""
 
-#: aleksis/core/models.py:68
+#: aleksis/core/models.py:69
 msgid "URL / Link"
 msgstr ""
 
-#: aleksis/core/models.py:80 aleksis/core/models.py:910
+#: aleksis/core/models.py:81 aleksis/core/models.py:927
 msgid "Name"
 msgstr ""
 
-#: aleksis/core/models.py:82
+#: aleksis/core/models.py:83
 #, fuzzy
 #| msgid "Contact details"
 msgid "Start date"
 msgstr "Détails de contact"
 
-#: aleksis/core/models.py:83
+#: aleksis/core/models.py:84
 msgid "End date"
 msgstr ""
 
-#: aleksis/core/models.py:102
+#: aleksis/core/models.py:103
 msgid "The start date must be earlier than the end date."
 msgstr ""
 
-#: aleksis/core/models.py:109
+#: aleksis/core/models.py:110
 msgid "There is already a school term for this time or a part of this time."
 msgstr ""
 
-#: aleksis/core/models.py:138 aleksis/core/models.py:859
-#: aleksis/core/templates/core/person/accounts.html:41
+#: aleksis/core/models.py:139 aleksis/core/models.py:876
 msgid "Person"
 msgstr "Personne"
 
-#: aleksis/core/models.py:141
+#: aleksis/core/models.py:142
 #, fuzzy
 #| msgid "Contact details"
 msgid "Can view address"
 msgstr "Détails de contact"
 
-#: aleksis/core/models.py:142
+#: aleksis/core/models.py:143
 #, fuzzy
 #| msgid "Contact details"
 msgid "Can view contact details"
 msgstr "Détails de contact"
 
-#: aleksis/core/models.py:143
+#: aleksis/core/models.py:144
 #, fuzzy
 #| msgid "Contact details"
 msgid "Can view photo"
 msgstr "Détails de contact"
 
-#: aleksis/core/models.py:144
+#: aleksis/core/models.py:145
 #, fuzzy
 #| msgid "Contact details"
 msgid "Can view persons groups"
 msgstr "Détails de contact"
 
-#: aleksis/core/models.py:145
+#: aleksis/core/models.py:146
 #, fuzzy
 #| msgid "Contact details"
 msgid "Can view personal details"
 msgstr "Détails de contact"
 
-#: aleksis/core/models.py:155
+#: aleksis/core/models.py:156
 msgid "female"
 msgstr ""
 
-#: aleksis/core/models.py:155
+#: aleksis/core/models.py:156
 msgid "male"
 msgstr ""
 
-#: aleksis/core/models.py:163
+#: aleksis/core/models.py:164
 msgid "Linked user"
 msgstr ""
 
-#: aleksis/core/models.py:165
+#: aleksis/core/models.py:166
 msgid "Is person active?"
 msgstr ""
 
-#: aleksis/core/models.py:167
+#: aleksis/core/models.py:168
 msgid "First name"
 msgstr "Prénom"
 
-#: aleksis/core/models.py:168
+#: aleksis/core/models.py:169
 msgid "Last name"
 msgstr "Nom de famille"
 
-#: aleksis/core/models.py:170
+#: aleksis/core/models.py:171
 msgid "Additional name(s)"
 msgstr ""
 
-#: aleksis/core/models.py:174 aleksis/core/models.py:398
+#: aleksis/core/models.py:175 aleksis/core/models.py:415
 #, fuzzy
 #| msgid "First name"
 msgid "Short name"
 msgstr "Prénom"
 
-#: aleksis/core/models.py:177
+#: aleksis/core/models.py:178
 msgid "Street"
 msgstr ""
 
-#: aleksis/core/models.py:178
+#: aleksis/core/models.py:179
 msgid "Street number"
 msgstr ""
 
-#: aleksis/core/models.py:179
+#: aleksis/core/models.py:180
 msgid "Postal code"
 msgstr ""
 
-#: aleksis/core/models.py:180
+#: aleksis/core/models.py:181
 msgid "Place"
 msgstr ""
 
-#: aleksis/core/models.py:182
+#: aleksis/core/models.py:183
 msgid "Home phone"
 msgstr ""
 
-#: aleksis/core/models.py:183
+#: aleksis/core/models.py:184
 msgid "Mobile phone"
 msgstr ""
 
-#: aleksis/core/models.py:187
+#: aleksis/core/models.py:188
 msgid "Date of birth"
 msgstr "Date d'anniversaire"
 
-#: aleksis/core/models.py:188
+#: aleksis/core/models.py:189
 msgid "Sex"
 msgstr "Sexe"
 
-#: aleksis/core/models.py:190
+#: aleksis/core/models.py:191
 msgid "Photo"
 msgstr ""
 
-#: aleksis/core/models.py:194 aleksis/core/templates/core/person/full.html:137
+#: aleksis/core/models.py:195 aleksis/core/templates/core/person/full.html:137
 msgid "Guardians / Parents"
 msgstr ""
 
-#: aleksis/core/models.py:201
+#: aleksis/core/models.py:202
 msgid "Primary group"
 msgstr ""
 
-#: aleksis/core/models.py:204 aleksis/core/models.py:546
-#: aleksis/core/models.py:570 aleksis/core/models.py:655
-#: aleksis/core/models.py:934 aleksis/core/templates/core/person/full.html:120
+#: aleksis/core/models.py:205 aleksis/core/models.py:563
+#: aleksis/core/models.py:587 aleksis/core/models.py:672
+#: aleksis/core/models.py:951 aleksis/core/templates/core/person/full.html:120
 msgid "Description"
 msgstr "Description"
 
-#: aleksis/core/models.py:353
+#: aleksis/core/models.py:370
 msgid "Title of field"
 msgstr ""
 
-#: aleksis/core/models.py:355
+#: aleksis/core/models.py:372
 msgid "Type of field"
 msgstr ""
 
-#: aleksis/core/models.py:362
+#: aleksis/core/models.py:379
 msgid "Addtitional field for groups"
 msgstr ""
 
-#: aleksis/core/models.py:363
+#: aleksis/core/models.py:380
 msgid "Addtitional fields for groups"
 msgstr ""
 
-#: aleksis/core/models.py:380
+#: aleksis/core/models.py:397
 msgid "Group"
 msgstr "groupe"
 
-#: aleksis/core/models.py:383
+#: aleksis/core/models.py:400
 msgid "Can assign child groups to groups"
 msgstr ""
 
-#: aleksis/core/models.py:384
+#: aleksis/core/models.py:401
 #, fuzzy
 #| msgid "Contact details"
 msgid "Can view statistics about group."
 msgstr "Détails de contact"
 
-#: aleksis/core/models.py:396
+#: aleksis/core/models.py:413
 #, fuzzy
 #| msgid "Last name"
 msgid "Long name"
 msgstr "Nom de famille"
 
-#: aleksis/core/models.py:406 aleksis/core/templates/core/group/full.html:85
+#: aleksis/core/models.py:423 aleksis/core/templates/core/group/full.html:85
 msgid "Members"
 msgstr ""
 
-#: aleksis/core/models.py:409 aleksis/core/templates/core/group/full.html:82
+#: aleksis/core/models.py:426 aleksis/core/templates/core/group/full.html:82
 msgid "Owners"
 msgstr "Propriétaires"
 
-#: aleksis/core/models.py:416 aleksis/core/templates/core/group/full.html:55
+#: aleksis/core/models.py:433 aleksis/core/templates/core/group/full.html:55
 msgid "Parent groups"
 msgstr ""
 
-#: aleksis/core/models.py:424
+#: aleksis/core/models.py:441
 msgid "Type of group"
 msgstr ""
 
-#: aleksis/core/models.py:542
+#: aleksis/core/models.py:559
 msgid "User"
 msgstr ""
 
-#: aleksis/core/models.py:545 aleksis/core/models.py:569
-#: aleksis/core/models.py:654
+#: aleksis/core/models.py:562 aleksis/core/models.py:586
+#: aleksis/core/models.py:671
 #: aleksis/core/templates/core/announcement/list.html:18
 msgid "Title"
 msgstr ""
 
-#: aleksis/core/models.py:548
+#: aleksis/core/models.py:565
 msgid "Application"
 msgstr ""
 
-#: aleksis/core/models.py:554
+#: aleksis/core/models.py:571
 msgid "Activity"
 msgstr ""
 
-#: aleksis/core/models.py:555
+#: aleksis/core/models.py:572
 msgid "Activities"
 msgstr ""
 
-#: aleksis/core/models.py:561
+#: aleksis/core/models.py:578
 msgid "Sender"
 msgstr ""
 
-#: aleksis/core/models.py:566
+#: aleksis/core/models.py:583
 msgid "Recipient"
 msgstr ""
 
-#: aleksis/core/models.py:571 aleksis/core/models.py:911
+#: aleksis/core/models.py:588 aleksis/core/models.py:928
 msgid "Link"
 msgstr ""
 
-#: aleksis/core/models.py:573
+#: aleksis/core/models.py:590
 msgid "Read"
 msgstr ""
 
-#: aleksis/core/models.py:574
+#: aleksis/core/models.py:591
 msgid "Sent"
 msgstr ""
 
-#: aleksis/core/models.py:587
+#: aleksis/core/models.py:604
 msgid "Notification"
 msgstr ""
 
-#: aleksis/core/models.py:656
+#: aleksis/core/models.py:673
 msgid "Link to detailed view"
 msgstr ""
 
-#: aleksis/core/models.py:659
+#: aleksis/core/models.py:676
 msgid "Date and time from when to show"
 msgstr ""
 
-#: aleksis/core/models.py:662
+#: aleksis/core/models.py:679
 msgid "Date and time until when to show"
 msgstr ""
 
-#: aleksis/core/models.py:686
+#: aleksis/core/models.py:703
 msgid "Announcement"
 msgstr ""
 
-#: aleksis/core/models.py:724
+#: aleksis/core/models.py:741
 msgid "Announcement recipient"
 msgstr ""
 
-#: aleksis/core/models.py:725
+#: aleksis/core/models.py:742
 msgid "Announcement recipients"
 msgstr ""
 
-#: aleksis/core/models.py:780
+#: aleksis/core/models.py:797
 msgid "Widget Title"
 msgstr ""
 
-#: aleksis/core/models.py:781
+#: aleksis/core/models.py:798
 msgid "Activate Widget"
 msgstr ""
 
-#: aleksis/core/models.py:782
+#: aleksis/core/models.py:799
 msgid "Widget is broken"
 msgstr ""
 
-#: aleksis/core/models.py:785
+#: aleksis/core/models.py:802
 msgid "Size on mobile devices"
 msgstr ""
 
-#: aleksis/core/models.py:786
+#: aleksis/core/models.py:803
 msgid "<= 600 px, 12 columns"
 msgstr ""
 
-#: aleksis/core/models.py:791
+#: aleksis/core/models.py:808
 msgid "Size on tablet devices"
 msgstr ""
 
-#: aleksis/core/models.py:792
+#: aleksis/core/models.py:809
 msgid "> 600 px, 12 columns"
 msgstr ""
 
-#: aleksis/core/models.py:797
+#: aleksis/core/models.py:814
 msgid "Size on desktop devices"
 msgstr ""
 
-#: aleksis/core/models.py:798
+#: aleksis/core/models.py:815
 msgid "> 992 px, 12 columns"
 msgstr ""
 
-#: aleksis/core/models.py:803
+#: aleksis/core/models.py:820
 msgid "Size on large desktop devices"
 msgstr ""
 
-#: aleksis/core/models.py:804
+#: aleksis/core/models.py:821
 msgid "> 1200 px>, 12 columns"
 msgstr ""
 
-#: aleksis/core/models.py:835
+#: aleksis/core/models.py:852
 msgid "Can edit default dashboard"
 msgstr ""
 
-#: aleksis/core/models.py:836
+#: aleksis/core/models.py:853
 msgid "Dashboard Widget"
 msgstr ""
 
-#: aleksis/core/models.py:837
+#: aleksis/core/models.py:854
 msgid "Dashboard Widgets"
 msgstr ""
 
-#: aleksis/core/models.py:843
+#: aleksis/core/models.py:860
 msgid "URL"
 msgstr ""
 
-#: aleksis/core/models.py:844
+#: aleksis/core/models.py:861
 msgid "Icon URL"
 msgstr ""
 
-#: aleksis/core/models.py:850
+#: aleksis/core/models.py:867
 msgid "External link widget"
 msgstr ""
 
-#: aleksis/core/models.py:851
+#: aleksis/core/models.py:868
 msgid "External link widgets"
 msgstr ""
 
-#: aleksis/core/models.py:856
+#: aleksis/core/models.py:873
 msgid "Dashboard widget"
 msgstr ""
 
-#: aleksis/core/models.py:861
+#: aleksis/core/models.py:878
 msgid "Order"
 msgstr ""
 
-#: aleksis/core/models.py:862
+#: aleksis/core/models.py:879
 msgid "Part of the default dashboard"
 msgstr ""
 
-#: aleksis/core/models.py:877
+#: aleksis/core/models.py:894
 msgid "Dashboard widget order"
 msgstr ""
 
-#: aleksis/core/models.py:878
+#: aleksis/core/models.py:895
 msgid "Dashboard widget orders"
 msgstr ""
 
-#: aleksis/core/models.py:884
+#: aleksis/core/models.py:901
 msgid "Menu ID"
 msgstr ""
 
-#: aleksis/core/models.py:897
+#: aleksis/core/models.py:914
 msgid "Custom menu"
 msgstr ""
 
-#: aleksis/core/models.py:898
+#: aleksis/core/models.py:915
 msgid "Custom menus"
 msgstr ""
 
-#: aleksis/core/models.py:908
+#: aleksis/core/models.py:925
 msgid "Menu"
 msgstr ""
 
-#: aleksis/core/models.py:912
+#: aleksis/core/models.py:929
 msgid "Icon"
 msgstr ""
 
-#: aleksis/core/models.py:918
+#: aleksis/core/models.py:935
 msgid "Custom menu item"
 msgstr ""
 
-#: aleksis/core/models.py:919
+#: aleksis/core/models.py:936
 msgid "Custom menu items"
 msgstr ""
 
-#: aleksis/core/models.py:933
+#: aleksis/core/models.py:950
 msgid "Title of type"
 msgstr ""
 
-#: aleksis/core/models.py:940 aleksis/core/templates/core/group/full.html:47
+#: aleksis/core/models.py:957 aleksis/core/templates/core/group/full.html:47
 #, fuzzy
 #| msgid "Group"
 msgid "Group type"
 msgstr "Groupe"
 
-#: aleksis/core/models.py:954
+#: aleksis/core/models.py:971
 #, fuzzy
 #| msgid "Contact details"
 msgid "Can view system status"
 msgstr "Détails de contact"
 
-#: aleksis/core/models.py:955
-#, fuzzy
-#| msgid "Contact details"
-msgid "Can link persons to accounts"
-msgstr "Détails de contact"
-
-#: aleksis/core/models.py:956
+#: aleksis/core/models.py:972
 msgid "Can manage data"
 msgstr ""
 
-#: aleksis/core/models.py:957
+#: aleksis/core/models.py:973
 #, fuzzy
 #| msgid "Contact details"
 msgid "Can impersonate"
 msgstr "Détails de contact"
 
-#: aleksis/core/models.py:958
+#: aleksis/core/models.py:974
 msgid "Can use search"
 msgstr ""
 
-#: aleksis/core/models.py:959
+#: aleksis/core/models.py:975
 msgid "Can change site preferences"
 msgstr ""
 
-#: aleksis/core/models.py:960
+#: aleksis/core/models.py:976
 msgid "Can change person preferences"
 msgstr ""
 
-#: aleksis/core/models.py:961
+#: aleksis/core/models.py:977
 msgid "Can change group preferences"
 msgstr ""
 
-#: aleksis/core/models.py:962
+#: aleksis/core/models.py:978
 msgid "Can add oauth applications"
 msgstr ""
 
-#: aleksis/core/models.py:963
+#: aleksis/core/models.py:979
 msgid "Can list oauth applications"
 msgstr ""
 
-#: aleksis/core/models.py:964
+#: aleksis/core/models.py:980
 #, fuzzy
 #| msgid "Contact details"
 msgid "Can view oauth applications"
 msgstr "Détails de contact"
 
-#: aleksis/core/models.py:965
+#: aleksis/core/models.py:981
 msgid "Can update oauth applications"
 msgstr ""
 
-#: aleksis/core/models.py:966
+#: aleksis/core/models.py:982
 msgid "Can delete oauth applications"
 msgstr ""
 
-#: aleksis/core/models.py:967
+#: aleksis/core/models.py:983
 msgid "Can test PDF generation"
 msgstr ""
 
-#: aleksis/core/models.py:1003
+#: aleksis/core/models.py:1019
 msgid "Related data check task"
 msgstr ""
 
-#: aleksis/core/models.py:1011
+#: aleksis/core/models.py:1027
 msgid "Issue solved"
 msgstr ""
 
-#: aleksis/core/models.py:1012
+#: aleksis/core/models.py:1028
 msgid "Notification sent"
 msgstr ""
 
-#: aleksis/core/models.py:1025
+#: aleksis/core/models.py:1041
 msgid "Data check result"
 msgstr ""
 
-#: aleksis/core/models.py:1026
+#: aleksis/core/models.py:1042
 msgid "Data check results"
 msgstr ""
 
-#: aleksis/core/models.py:1028
+#: aleksis/core/models.py:1044
 msgid "Can run data checks"
 msgstr ""
 
-#: aleksis/core/models.py:1029
+#: aleksis/core/models.py:1045
 msgid "Can solve data check problems"
 msgstr ""
 
-#: aleksis/core/models.py:1044
+#: aleksis/core/models.py:1060
 #, fuzzy
 #| msgid "Owners"
 msgid "Owner"
 msgstr "Propriétaires"
 
-#: aleksis/core/models.py:1048
+#: aleksis/core/models.py:1064
 msgid "File expires at"
 msgstr ""
 
-#: aleksis/core/models.py:1050
+#: aleksis/core/models.py:1066
 msgid "Generated HTML file"
 msgstr ""
 
-#: aleksis/core/models.py:1052
+#: aleksis/core/models.py:1068
 msgid "Generated PDF file"
 msgstr ""
 
-#: aleksis/core/models.py:1059
+#: aleksis/core/models.py:1075
 msgid "PDF file"
 msgstr ""
 
-#: aleksis/core/models.py:1060
+#: aleksis/core/models.py:1076
 msgid "PDF files"
 msgstr ""
 
-#: aleksis/core/models.py:1065
+#: aleksis/core/models.py:1081
 msgid "Task result"
 msgstr ""
 
-#: aleksis/core/models.py:1068
+#: aleksis/core/models.py:1084
 msgid "Task user"
 msgstr ""
 
-#: aleksis/core/models.py:1080
+#: aleksis/core/models.py:1096
 msgid "Task user assignment"
 msgstr ""
 
-#: aleksis/core/models.py:1081
+#: aleksis/core/models.py:1097
 msgid "Task user assignments"
 msgstr ""
 
@@ -1084,75 +1073,71 @@ msgstr ""
 msgid "Official name of the school, e.g. as given by supervisory authority"
 msgstr ""
 
-#: aleksis/core/preferences.py:256
-msgid "Enabled custom authentication backends"
-msgstr ""
-
-#: aleksis/core/preferences.py:268
+#: aleksis/core/preferences.py:254
 msgid "Allow users to change their passwords"
 msgstr ""
 
-#: aleksis/core/preferences.py:276
+#: aleksis/core/preferences.py:262
 msgid "Enable signup"
 msgstr ""
 
-#: aleksis/core/preferences.py:287
+#: aleksis/core/preferences.py:273
 msgid "Available languages"
 msgstr ""
 
-#: aleksis/core/preferences.py:299
+#: aleksis/core/preferences.py:285
 msgid "Send emails if data checks detect problems"
 msgstr ""
 
-#: aleksis/core/preferences.py:310
+#: aleksis/core/preferences.py:296
 msgid "Email recipients for data checks problem emails"
 msgstr ""
 
-#: aleksis/core/preferences.py:321
+#: aleksis/core/preferences.py:307
 msgid "Email recipient groups for data checks problem emails"
 msgstr ""
 
-#: aleksis/core/preferences.py:330
+#: aleksis/core/preferences.py:316
 msgid "Show dashboard to users without login"
 msgstr ""
 
-#: aleksis/core/preferences.py:339
+#: aleksis/core/preferences.py:325
 msgid "Allow users to edit their dashboard"
 msgstr ""
 
-#: aleksis/core/preferences.py:350
+#: aleksis/core/preferences.py:336
 msgid "Fields on person model which are editable by themselves."
 msgstr ""
 
-#: aleksis/core/preferences.py:364
+#: aleksis/core/preferences.py:350
 msgid "Editable fields on person model which should trigger a notification on change"
 msgstr ""
 
-#: aleksis/core/preferences.py:377
+#: aleksis/core/preferences.py:363
 msgid "Contact for notification if a person changes their data"
 msgstr ""
 
-#: aleksis/core/preferences.py:387
+#: aleksis/core/preferences.py:373
 msgid "PDF file expiration duration"
 msgstr ""
 
-#: aleksis/core/preferences.py:388
+#: aleksis/core/preferences.py:374
 msgid "in minutes"
 msgstr ""
 
-#: aleksis/core/preferences.py:398
+#: aleksis/core/preferences.py:384
 msgid "Automatically update the dashboard and its widgets"
 msgstr ""
 
-#: aleksis/core/preferences.py:408
+#: aleksis/core/preferences.py:394
 msgid "Automatically update the dashboard and its widgets sitewide"
 msgstr ""
 
-#: aleksis/core/settings.py:468
+#: aleksis/core/settings.py:452
 msgid "English"
 msgstr ""
 
-#: aleksis/core/settings.py:469
+#: aleksis/core/settings.py:453
 msgid "German"
 msgstr ""
 
@@ -1316,7 +1301,7 @@ msgstr ""
 #: aleksis/core/templates/account/password_reset_done.html:5
 #: aleksis/core/templates/account/verification_email_required.html:5
 #: aleksis/core/templates/account/verification_email_required.html:6
-#: aleksis/core/templates/two_factor/core/login.html:100
+#: aleksis/core/templates/two_factor/core/login.html:81
 msgid "Reset password"
 msgstr ""
 
@@ -2065,33 +2050,13 @@ msgid ""
 "          "
 msgstr ""
 
-#: aleksis/core/templates/core/person/accounts.html:12
-#: aleksis/core/templates/core/person/accounts.html:14
-msgid "Link persons to accounts"
-msgstr ""
-
-#: aleksis/core/templates/core/person/accounts.html:21
-msgid ""
-"\n"
-"        You can use this form to assign user accounts to persons. Use the\n"
-"        dropdowns to select existing accounts; use the text fields to create new\n"
-"        accounts on-the-fly. The latter will create a new account with the\n"
-"        entered username and copy all other details from the person.\n"
-"      "
-msgstr ""
-
-#: aleksis/core/templates/core/person/accounts.html:36
-#: aleksis/core/templates/core/person/accounts.html:60
-msgid "Update"
-msgstr ""
-
-#: aleksis/core/templates/core/person/accounts.html:42
-msgid "Existing account"
-msgstr ""
-
-#: aleksis/core/templates/core/person/accounts.html:43
-msgid "New account"
-msgstr ""
+#: aleksis/core/templates/core/person/create.html:12
+#: aleksis/core/templates/core/person/create.html:13
+#: aleksis/core/templates/core/person/list.html:17
+#, fuzzy
+#| msgid "Contact details"
+msgid "Create person"
+msgstr "Détails de contact"
 
 #: aleksis/core/templates/core/person/edit.html:12
 #: aleksis/core/templates/core/person/edit.html:13
@@ -2099,6 +2064,8 @@ msgid "Edit person"
 msgstr ""
 
 #: aleksis/core/templates/core/person/full.html:44
+#: aleksis/core/templates/impersonate/list_users.html:7
+#: aleksis/core/templates/impersonate/list_users.html:8
 #, fuzzy
 #| msgid "Contact details"
 msgid "Impersonate"
@@ -2112,12 +2079,6 @@ msgstr "Détails de contact"
 msgid "Children"
 msgstr ""
 
-#: aleksis/core/templates/core/person/list.html:17
-#, fuzzy
-#| msgid "Contact details"
-msgid "Create person"
-msgstr "Détails de contact"
-
 #: aleksis/core/templates/core/person/list.html:21
 msgid "Filter persons"
 msgstr ""
@@ -2154,10 +2115,6 @@ msgstr ""
 msgid "Save preferences"
 msgstr ""
 
-#: aleksis/core/templates/impersonate/list_users.html:8
-msgid "Impersonate user"
-msgstr ""
-
 #: aleksis/core/templates/oauth2_provider/application_confirm_delete.html:5
 #: aleksis/core/templates/oauth2_provider/application_confirm_delete.html:6
 msgid "Delete application"
@@ -2514,64 +2471,70 @@ msgstr ""
 msgid "Generate Tokens"
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:18
+#: aleksis/core/templates/two_factor/core/login.html:20
 msgid "Login with username and password"
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:26
-msgid "You have no permission to view this page. Please login with an other account."
+#: aleksis/core/templates/two_factor/core/login.html:28
+msgid ""
+"You have no permission to view this page. Please login with an other\n"
+"                    account."
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:33
+#: aleksis/core/templates/two_factor/core/login.html:36
 msgid "Please login to see this page."
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:43
+#: aleksis/core/templates/two_factor/core/login.html:46
 msgid ""
 "\n"
-"                      We are calling your phone right now, please enter the\n"
-"                      digits you hear.\n"
-"                    "
+"                        We are calling your phone right now, please enter the\n"
+"                        digits you hear.\n"
+"                      "
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:48
+#: aleksis/core/templates/two_factor/core/login.html:51
 msgid ""
 "\n"
-"                      We sent you a text message, please enter the tokens we\n"
-"                      sent.\n"
-"                    "
+"                        We sent you a text message, please enter the tokens we\n"
+"                        sent.\n"
+"                      "
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:53
+#: aleksis/core/templates/two_factor/core/login.html:56
 msgid ""
 "\n"
-"                      Please enter the tokens generated by your token\n"
-"                      generator.\n"
-"                    "
+"                        Please enter the tokens generated by your token\n"
+"                        generator.\n"
+"                      "
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:59
+#: aleksis/core/templates/two_factor/core/login.html:62
 msgid ""
 "\n"
-"                    Use this form for entering backup tokens for logging in.\n"
-"                    These tokens have been generated for you to print and keep safe. Please\n"
-"                    enter one of these backup tokens to login to your account.\n"
-"                  "
+"                      Use this form for entering backup tokens for logging in.\n"
+"                      These tokens have been generated for you to print and keep safe. Please\n"
+"                      enter one of these backup tokens to login to your account.\n"
+"                    "
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:74
+#: aleksis/core/templates/two_factor/core/login.html:90
+msgid "Device currently not available?"
+msgstr ""
+
+#: aleksis/core/templates/two_factor/core/login.html:92
 msgid "Or, alternatively, use one of your backup phones:"
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:84
+#: aleksis/core/templates/two_factor/core/login.html:102
 msgid "As a last resort, you can use a backup token:"
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:87
+#: aleksis/core/templates/two_factor/core/login.html:105
 msgid "Use Backup Token"
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:110
+#: aleksis/core/templates/two_factor/core/login.html:116
 msgid "Use alternative login options"
 msgstr ""
 
@@ -2836,107 +2799,112 @@ msgstr ""
 msgid "Download PDF"
 msgstr ""
 
-#: aleksis/core/views.py:253
+#: aleksis/core/views.py:251
 msgid "The school term has been created."
 msgstr ""
 
-#: aleksis/core/views.py:265
+#: aleksis/core/views.py:263
 msgid "The school term has been saved."
 msgstr ""
 
-#: aleksis/core/views.py:410
+#: aleksis/core/views.py:387
 msgid "The child groups were successfully saved."
 msgstr ""
 
-#: aleksis/core/views.py:471
+#: aleksis/core/views.py:406 aleksis/core/views.py:416
 msgid "The person has been saved."
 msgstr ""
 
-#: aleksis/core/views.py:510
+#: aleksis/core/views.py:466
 msgid "The group has been saved."
 msgstr ""
 
-#: aleksis/core/views.py:607
+#: aleksis/core/views.py:563
 msgid "The announcement has been saved."
 msgstr ""
 
-#: aleksis/core/views.py:623
+#: aleksis/core/views.py:579
 msgid "The announcement has been deleted."
 msgstr ""
 
-#: aleksis/core/views.py:707
+#: aleksis/core/views.py:663
 msgid "The preferences have been saved successfully."
 msgstr ""
 
-#: aleksis/core/views.py:731
+#: aleksis/core/views.py:687
 msgid "The person has been deleted."
 msgstr ""
 
-#: aleksis/core/views.py:745
+#: aleksis/core/views.py:701
 msgid "The group has been deleted."
 msgstr ""
 
-#: aleksis/core/views.py:777
+#: aleksis/core/views.py:733
 msgid "The additional_field has been saved."
 msgstr ""
 
-#: aleksis/core/views.py:811
+#: aleksis/core/views.py:767
 msgid "The additional field has been deleted."
 msgstr ""
 
-#: aleksis/core/views.py:836
+#: aleksis/core/views.py:792
 msgid "The group type has been saved."
 msgstr ""
 
-#: aleksis/core/views.py:866
+#: aleksis/core/views.py:822
 msgid "The group type has been deleted."
 msgstr ""
 
-#: aleksis/core/views.py:899
+#: aleksis/core/views.py:855
 msgid "Progress: Run data checks"
 msgstr ""
 
-#: aleksis/core/views.py:900
+#: aleksis/core/views.py:856
 msgid "Run data checks …"
 msgstr ""
 
-#: aleksis/core/views.py:901
+#: aleksis/core/views.py:857
 msgid "The data checks were run successfully."
 msgstr ""
 
-#: aleksis/core/views.py:902
+#: aleksis/core/views.py:858
 msgid "There was a problem while running data checks."
 msgstr ""
 
-#: aleksis/core/views.py:918
+#: aleksis/core/views.py:874
 #, python-brace-format
 msgid "The solve option '{solve_option_obj.verbose_name}' "
 msgstr ""
 
-#: aleksis/core/views.py:960
+#: aleksis/core/views.py:916
 msgid "The dashboard widget has been saved."
 msgstr ""
 
-#: aleksis/core/views.py:990
+#: aleksis/core/views.py:946
 msgid "The dashboard widget has been created."
 msgstr ""
 
-#: aleksis/core/views.py:1000
+#: aleksis/core/views.py:956
 msgid "The dashboard widget has been deleted."
 msgstr ""
 
-#: aleksis/core/views.py:1067
+#: aleksis/core/views.py:1023
 msgid "Your dashboard configuration has been saved successfully."
 msgstr ""
 
-#: aleksis/core/views.py:1069
+#: aleksis/core/views.py:1025
 msgid "The configuration of the default dashboard has been saved successfully."
 msgstr ""
 
-#: aleksis/core/views.py:1197
+#: aleksis/core/views.py:1153
 msgid "The third-party account could not be disconnected because it is the only login method available."
 msgstr ""
 
-#: aleksis/core/views.py:1204
+#: aleksis/core/views.py:1160
 msgid "The third-party account has been successfully disconnected."
 msgstr ""
+
+#, fuzzy
+#~| msgid "Contact details"
+#~ msgid "Can link persons to accounts"
+#~ msgstr "Détails de contact"
diff --git a/aleksis/core/locale/fr/LC_MESSAGES/djangojs.po b/aleksis/core/locale/fr/LC_MESSAGES/djangojs.po
index d8b7ad352c6960cdc4dd763358d91f4004435949..bbd51395a6ee28d076da3de7bd4d65b198574194 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: 2021-08-28 17:53+0200\n"
+"POT-Creation-Date: 2021-10-28 16:18+0200\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"
diff --git a/aleksis/core/locale/la/LC_MESSAGES/django.po b/aleksis/core/locale/la/LC_MESSAGES/django.po
index 0badcc66b6e356e9988b64d155b1dfa53ee3381b..c34a5cc0811a09a7a1b1bf4430463e56cff5be3f 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: 2021-08-28 17:53+0200\n"
+"POT-Creation-Date: 2021-10-28 16:18+0200\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,27 +18,27 @@ msgstr ""
 "Plural-Forms: nplurals=2; plural=n != 1;\n"
 "X-Generator: Weblate 4.3.2\n"
 
-#: aleksis/core/apps.py:148 aleksis/core/settings.py:343
+#: aleksis/core/apps.py:150
 msgid "OpenID Connect scope"
 msgstr ""
 
-#: aleksis/core/apps.py:149 aleksis/core/settings.py:344
+#: aleksis/core/apps.py:151
 msgid "Given name, family name, link to profile and picture if existing."
 msgstr ""
 
-#: aleksis/core/apps.py:150 aleksis/core/settings.py:345
+#: aleksis/core/apps.py:152
 #, fuzzy
 #| msgid "E-mail address"
 msgid "Full home postal address"
 msgstr "Inscriptio electronica"
 
-#: aleksis/core/apps.py:151 aleksis/core/settings.py:346
+#: aleksis/core/apps.py:153
 #, fuzzy
 #| msgid "E-mail address"
 msgid "Email address"
 msgstr "Inscriptio electronica"
 
-#: aleksis/core/apps.py:152 aleksis/core/settings.py:347
+#: aleksis/core/apps.py:154
 #, fuzzy
 #| msgid "Mobile phone"
 msgid "Home and mobile phone"
@@ -86,134 +86,134 @@ msgstr "Quaerere cum breve nomine"
 msgid "Search by contact details"
 msgstr "Inscriptio electronica"
 
-#: aleksis/core/forms.py:62
-msgid "You cannot set a new username when also selecting an existing user."
-msgstr ""
-
-#: aleksis/core/forms.py:66
-msgid "This username is already in use."
-msgstr ""
-
-#: aleksis/core/forms.py:90 aleksis/core/forms.py:412
+#: aleksis/core/forms.py:41 aleksis/core/forms.py:387
 msgid "Base data"
 msgstr ""
 
-#: aleksis/core/forms.py:96
+#: aleksis/core/forms.py:47
 #, fuzzy
 #| msgid "E-mail address"
 msgid "Address"
 msgstr "Inscriptio electronica"
 
-#: aleksis/core/forms.py:97
+#: aleksis/core/forms.py:48
 msgid "Contact data"
 msgstr ""
 
-#: aleksis/core/forms.py:99
+#: aleksis/core/forms.py:50
 msgid "Advanced personal data"
 msgstr ""
 
-#: aleksis/core/forms.py:142
+#: aleksis/core/forms.py:93
 msgid "New user"
 msgstr ""
 
-#: aleksis/core/forms.py:142
+#: aleksis/core/forms.py:93
 #, fuzzy
 #| msgid "Persons and accounts"
 msgid "Create a new account"
 msgstr "Personae et computi"
 
-#: aleksis/core/forms.py:170 aleksis/core/models.py:116
+#: aleksis/core/forms.py:124
+msgid "You cannot set a new username when also selecting an existing user."
+msgstr ""
+
+#: aleksis/core/forms.py:128
+msgid "This username is already in use."
+msgstr ""
+
+#: aleksis/core/forms.py:145 aleksis/core/models.py:117
 msgid "School term"
 msgstr "Anus scolae"
 
-#: aleksis/core/forms.py:171
+#: aleksis/core/forms.py:146
 #, fuzzy
 #| msgid "Data management"
 msgid "Common data"
 msgstr "Adminstratio datarum"
 
-#: aleksis/core/forms.py:172 aleksis/core/forms.py:221
-#: aleksis/core/menus.py:238 aleksis/core/models.py:139
+#: aleksis/core/forms.py:147 aleksis/core/forms.py:196
+#: aleksis/core/menus.py:238 aleksis/core/models.py:140
 #: aleksis/core/templates/core/person/list.html:8
 #: aleksis/core/templates/core/person/list.html:9
 msgid "Persons"
 msgstr "personae"
 
-#: aleksis/core/forms.py:173
+#: aleksis/core/forms.py:148
 #, fuzzy
 #| msgid "Additional name(s)"
 msgid "Additional data"
 msgstr "addita nomines"
 
-#: aleksis/core/forms.py:213 aleksis/core/forms.py:216
-#: aleksis/core/models.py:59
+#: aleksis/core/forms.py:188 aleksis/core/forms.py:191
+#: aleksis/core/models.py:60
 msgid "Date"
 msgstr "dies"
 
-#: aleksis/core/forms.py:214 aleksis/core/forms.py:217
-#: aleksis/core/models.py:67
+#: aleksis/core/forms.py:189 aleksis/core/forms.py:192
+#: aleksis/core/models.py:68
 msgid "Time"
 msgstr "tempus"
 
-#: aleksis/core/forms.py:234 aleksis/core/menus.py:249
-#: aleksis/core/models.py:381 aleksis/core/templates/core/group/list.html:8
+#: aleksis/core/forms.py:209 aleksis/core/menus.py:249
+#: aleksis/core/models.py:398 aleksis/core/templates/core/group/list.html:8
 #: aleksis/core/templates/core/group/list.html:9
 #: aleksis/core/templates/core/person/full.html:144
 msgid "Groups"
 msgstr "Greges"
 
-#: aleksis/core/forms.py:244
+#: aleksis/core/forms.py:219
 msgid "From when until when should the announcement be displayed?"
 msgstr ""
 
-#: aleksis/core/forms.py:247
+#: aleksis/core/forms.py:222
 msgid "Who should see the announcement?"
 msgstr "Quis nuntium videatne?"
 
-#: aleksis/core/forms.py:248
+#: aleksis/core/forms.py:223
 msgid "Write your announcement:"
 msgstr "Scribe nuntium:"
 
-#: aleksis/core/forms.py:287
+#: aleksis/core/forms.py:262
 msgid "You are not allowed to create announcements which are only valid in the past."
 msgstr ""
 
-#: aleksis/core/forms.py:291
+#: aleksis/core/forms.py:266
 msgid "The from date and time must be earlier then the until date and time."
 msgstr ""
 
-#: aleksis/core/forms.py:300
+#: aleksis/core/forms.py:275
 msgid "You need at least one recipient."
 msgstr ""
 
-#: aleksis/core/forms.py:414
+#: aleksis/core/forms.py:389
 #, fuzzy
 #| msgid "Data management"
 msgid "Account data"
 msgstr "Adminstratio datarum"
 
-#: aleksis/core/forms.py:416
+#: aleksis/core/forms.py:391
 msgid "Consents"
 msgstr ""
 
-#: aleksis/core/forms.py:421
+#: aleksis/core/forms.py:396
 msgid "Password"
 msgstr ""
 
-#: aleksis/core/forms.py:427
+#: aleksis/core/forms.py:402
 msgid "Password (again)"
 msgstr ""
 
-#: aleksis/core/forms.py:436
+#: aleksis/core/forms.py:411
 #, python-brace-format
 msgid "I have read the <a href='{privacy_policy}'>Privacy policy</a> and agree with them."
 msgstr ""
 
-#: aleksis/core/forms.py:460
+#: aleksis/core/forms.py:435
 msgid "You must type the same password each time."
 msgstr ""
 
-#: aleksis/core/forms.py:605
+#: aleksis/core/forms.py:580
 msgid "No valid selection."
 msgstr ""
 
@@ -246,8 +246,8 @@ msgid "{task.status} - {task.result}"
 msgstr ""
 
 #: aleksis/core/menus.py:9 aleksis/core/templates/two_factor/core/login.html:6
-#: aleksis/core/templates/two_factor/core/login.html:20
-#: aleksis/core/templates/two_factor/core/login.html:95
+#: aleksis/core/templates/two_factor/core/login.html:22
+#: aleksis/core/templates/two_factor/core/login.html:76
 msgid "Login"
 msgstr "nomen profiteri"
 
@@ -260,7 +260,7 @@ msgstr ""
 msgid "Dashboard"
 msgstr "Forum"
 
-#: aleksis/core/menus.py:32 aleksis/core/models.py:588
+#: aleksis/core/menus.py:32 aleksis/core/models.py:605
 #: aleksis/core/preferences.py:26
 #: aleksis/core/templates/core/notifications.html:4
 #: aleksis/core/templates/core/notifications.html:5
@@ -322,13 +322,13 @@ msgstr "Nuntii"
 msgid "Admin"
 msgstr "Administratio"
 
-#: aleksis/core/menus.py:127 aleksis/core/models.py:687
+#: aleksis/core/menus.py:127 aleksis/core/models.py:704
 #: aleksis/core/templates/core/announcement/list.html:7
 #: aleksis/core/templates/core/announcement/list.html:8
 msgid "Announcements"
 msgstr "Nuntii"
 
-#: aleksis/core/menus.py:138 aleksis/core/models.py:117
+#: aleksis/core/menus.py:138 aleksis/core/models.py:118
 #: aleksis/core/templates/core/school_term/list.html:8
 #: aleksis/core/templates/core/school_term/list.html:9
 msgid "School terms"
@@ -387,7 +387,7 @@ msgstr "Nuntii"
 msgid "People"
 msgstr "Personae"
 
-#: aleksis/core/menus.py:260 aleksis/core/models.py:941
+#: aleksis/core/menus.py:260 aleksis/core/models.py:958
 #: aleksis/core/templates/core/group_type/list.html:8
 #: aleksis/core/templates/core/group_type/list.html:9
 #, fuzzy
@@ -396,14 +396,10 @@ msgid "Group types"
 msgstr "Greges"
 
 #: aleksis/core/menus.py:271
-msgid "Persons and accounts"
-msgstr "Personae et computi"
-
-#: aleksis/core/menus.py:282
 msgid "Groups and child groups"
 msgstr ""
 
-#: aleksis/core/menus.py:293 aleksis/core/models.py:429
+#: aleksis/core/menus.py:282 aleksis/core/models.py:446
 #: aleksis/core/templates/core/additional_field/list.html:8
 #: aleksis/core/templates/core/additional_field/list.html:9
 #, fuzzy
@@ -411,614 +407,607 @@ msgstr ""
 msgid "Additional fields"
 msgstr "addita nomines"
 
-#: aleksis/core/menus.py:308
+#: aleksis/core/menus.py:297
 #: aleksis/core/templates/core/group/child_groups.html:7
 #: aleksis/core/templates/core/group/child_groups.html:9
 msgid "Assign child groups to groups"
 msgstr ""
 
-#: aleksis/core/mixins.py:475
+#: aleksis/core/mixins.py:498
 #, fuzzy
 #| msgid "Edit school term"
 msgid "Linked school term"
 msgstr "Muta anum scolae"
 
-#: aleksis/core/models.py:57
+#: aleksis/core/models.py:58
 msgid "Boolean (Yes/No)"
 msgstr ""
 
-#: aleksis/core/models.py:58
+#: aleksis/core/models.py:59
 msgid "Text (one line)"
 msgstr ""
 
-#: aleksis/core/models.py:60
+#: aleksis/core/models.py:61
 msgid "Date and time"
 msgstr "Dies et hora"
 
-#: aleksis/core/models.py:61
+#: aleksis/core/models.py:62
 msgid "Decimal number"
 msgstr ""
 
-#: aleksis/core/models.py:62 aleksis/core/models.py:185
+#: aleksis/core/models.py:63 aleksis/core/models.py:186
 msgid "E-mail address"
 msgstr "Inscriptio electronica"
 
-#: aleksis/core/models.py:63
+#: aleksis/core/models.py:64
 msgid "Integer"
 msgstr ""
 
-#: aleksis/core/models.py:64
+#: aleksis/core/models.py:65
 #, fuzzy
 #| msgid "E-mail address"
 msgid "IP address"
 msgstr "Inscriptio electronica"
 
-#: aleksis/core/models.py:65
+#: aleksis/core/models.py:66
 msgid "Boolean or empty (Yes/No/Neither)"
 msgstr ""
 
-#: aleksis/core/models.py:66
+#: aleksis/core/models.py:67
 msgid "Text (multi-line)"
 msgstr ""
 
-#: aleksis/core/models.py:68
+#: aleksis/core/models.py:69
 msgid "URL / Link"
 msgstr ""
 
-#: aleksis/core/models.py:80 aleksis/core/models.py:910
+#: aleksis/core/models.py:81 aleksis/core/models.py:927
 msgid "Name"
 msgstr "Nomen"
 
-#: aleksis/core/models.py:82
+#: aleksis/core/models.py:83
 msgid "Start date"
 msgstr ""
 
-#: aleksis/core/models.py:83
+#: aleksis/core/models.py:84
 msgid "End date"
 msgstr ""
 
-#: aleksis/core/models.py:102
+#: aleksis/core/models.py:103
 msgid "The start date must be earlier than the end date."
 msgstr ""
 
-#: aleksis/core/models.py:109
+#: aleksis/core/models.py:110
 msgid "There is already a school term for this time or a part of this time."
 msgstr ""
 
-#: aleksis/core/models.py:138 aleksis/core/models.py:859
-#: aleksis/core/templates/core/person/accounts.html:41
+#: aleksis/core/models.py:139 aleksis/core/models.py:876
 msgid "Person"
 msgstr "Persona"
 
-#: aleksis/core/models.py:141
+#: aleksis/core/models.py:142
 #, fuzzy
 #| msgid "E-mail address"
 msgid "Can view address"
 msgstr "Inscriptio electronica"
 
-#: aleksis/core/models.py:142
+#: aleksis/core/models.py:143
 #, fuzzy
 #| msgid "E-mail address"
 msgid "Can view contact details"
 msgstr "Inscriptio electronica"
 
-#: aleksis/core/models.py:143
+#: aleksis/core/models.py:144
 #, fuzzy
 #| msgid "E-mail address"
 msgid "Can view photo"
 msgstr "Inscriptio electronica"
 
-#: aleksis/core/models.py:144
+#: aleksis/core/models.py:145
 #, fuzzy
 #| msgid "Persons and accounts"
 msgid "Can view persons groups"
 msgstr "Personae et computi"
 
-#: aleksis/core/models.py:145
+#: aleksis/core/models.py:146
 #, fuzzy
 #| msgid "Stop impersonation"
 msgid "Can view personal details"
 msgstr "Simulandum aliquem finire"
 
-#: aleksis/core/models.py:155
+#: aleksis/core/models.py:156
 msgid "female"
 msgstr "femininum"
 
-#: aleksis/core/models.py:155
+#: aleksis/core/models.py:156
 msgid "male"
 msgstr "maskulinum"
 
-#: aleksis/core/models.py:163
+#: aleksis/core/models.py:164
 msgid "Linked user"
 msgstr ""
 
-#: aleksis/core/models.py:165
+#: aleksis/core/models.py:166
 #, fuzzy
 #| msgid "Impersonation"
 msgid "Is person active?"
 msgstr "Simulare aliquem"
 
-#: aleksis/core/models.py:167
+#: aleksis/core/models.py:168
 msgid "First name"
 msgstr "Primus nomen"
 
-#: aleksis/core/models.py:168
+#: aleksis/core/models.py:169
 msgid "Last name"
 msgstr "Secondus nomen"
 
-#: aleksis/core/models.py:170
+#: aleksis/core/models.py:171
 msgid "Additional name(s)"
 msgstr "addita nomines"
 
-#: aleksis/core/models.py:174 aleksis/core/models.py:398
+#: aleksis/core/models.py:175 aleksis/core/models.py:415
 msgid "Short name"
 msgstr "Breve nomen"
 
-#: aleksis/core/models.py:177
+#: aleksis/core/models.py:178
 msgid "Street"
 msgstr "Via"
 
-#: aleksis/core/models.py:178
+#: aleksis/core/models.py:179
 msgid "Street number"
 msgstr "Numerus domini"
 
-#: aleksis/core/models.py:179
+#: aleksis/core/models.py:180
 msgid "Postal code"
 msgstr "Numerus directorius"
 
-#: aleksis/core/models.py:180
+#: aleksis/core/models.py:181
 msgid "Place"
 msgstr "Urbs"
 
-#: aleksis/core/models.py:182
+#: aleksis/core/models.py:183
 msgid "Home phone"
 msgstr "Numerus telephoni domi"
 
-#: aleksis/core/models.py:183
+#: aleksis/core/models.py:184
 msgid "Mobile phone"
 msgstr "Numerus telephoni mobilis"
 
-#: aleksis/core/models.py:187
+#: aleksis/core/models.py:188
 msgid "Date of birth"
 msgstr "Dies natalis"
 
-#: aleksis/core/models.py:188
+#: aleksis/core/models.py:189
 msgid "Sex"
 msgstr "Genus"
 
-#: aleksis/core/models.py:190
+#: aleksis/core/models.py:191
 msgid "Photo"
 msgstr "Photographia"
 
-#: aleksis/core/models.py:194 aleksis/core/templates/core/person/full.html:137
+#: aleksis/core/models.py:195 aleksis/core/templates/core/person/full.html:137
 msgid "Guardians / Parents"
 msgstr "Parentes"
 
-#: aleksis/core/models.py:201
+#: aleksis/core/models.py:202
 msgid "Primary group"
 msgstr ""
 
-#: aleksis/core/models.py:204 aleksis/core/models.py:546
-#: aleksis/core/models.py:570 aleksis/core/models.py:655
-#: aleksis/core/models.py:934 aleksis/core/templates/core/person/full.html:120
+#: aleksis/core/models.py:205 aleksis/core/models.py:563
+#: aleksis/core/models.py:587 aleksis/core/models.py:672
+#: aleksis/core/models.py:951 aleksis/core/templates/core/person/full.html:120
 msgid "Description"
 msgstr "Descriptio"
 
-#: aleksis/core/models.py:353
+#: aleksis/core/models.py:370
 msgid "Title of field"
 msgstr ""
 
-#: aleksis/core/models.py:355
+#: aleksis/core/models.py:372
 msgid "Type of field"
 msgstr ""
 
-#: aleksis/core/models.py:362
+#: aleksis/core/models.py:379
 #, fuzzy
 #| msgid "Additional name(s)"
 msgid "Addtitional field for groups"
 msgstr "addita nomines"
 
-#: aleksis/core/models.py:363
+#: aleksis/core/models.py:380
 #, fuzzy
 #| msgid "Additional name(s)"
 msgid "Addtitional fields for groups"
 msgstr "addita nomines"
 
-#: aleksis/core/models.py:380
+#: aleksis/core/models.py:397
 msgid "Group"
 msgstr "Grex"
 
-#: aleksis/core/models.py:383
+#: aleksis/core/models.py:400
 msgid "Can assign child groups to groups"
 msgstr ""
 
-#: aleksis/core/models.py:384
+#: aleksis/core/models.py:401
 #, fuzzy
 #| msgid "Persons and accounts"
 msgid "Can view statistics about group."
 msgstr "Personae et computi"
 
-#: aleksis/core/models.py:396
+#: aleksis/core/models.py:413
 #, fuzzy
 #| msgid "Last name"
 msgid "Long name"
 msgstr "Secondus nomen"
 
-#: aleksis/core/models.py:406 aleksis/core/templates/core/group/full.html:85
+#: aleksis/core/models.py:423 aleksis/core/templates/core/group/full.html:85
 msgid "Members"
 msgstr ""
 
-#: aleksis/core/models.py:409 aleksis/core/templates/core/group/full.html:82
+#: aleksis/core/models.py:426 aleksis/core/templates/core/group/full.html:82
 msgid "Owners"
 msgstr ""
 
-#: aleksis/core/models.py:416 aleksis/core/templates/core/group/full.html:55
+#: aleksis/core/models.py:433 aleksis/core/templates/core/group/full.html:55
 msgid "Parent groups"
 msgstr ""
 
-#: aleksis/core/models.py:424
+#: aleksis/core/models.py:441
 msgid "Type of group"
 msgstr ""
 
-#: aleksis/core/models.py:542
+#: aleksis/core/models.py:559
 msgid "User"
 msgstr ""
 
-#: aleksis/core/models.py:545 aleksis/core/models.py:569
-#: aleksis/core/models.py:654
+#: aleksis/core/models.py:562 aleksis/core/models.py:586
+#: aleksis/core/models.py:671
 #: aleksis/core/templates/core/announcement/list.html:18
 msgid "Title"
 msgstr "Titulus"
 
-#: aleksis/core/models.py:548
+#: aleksis/core/models.py:565
 msgid "Application"
 msgstr ""
 
-#: aleksis/core/models.py:554
+#: aleksis/core/models.py:571
 msgid "Activity"
 msgstr ""
 
-#: aleksis/core/models.py:555
+#: aleksis/core/models.py:572
 msgid "Activities"
 msgstr ""
 
-#: aleksis/core/models.py:561
+#: aleksis/core/models.py:578
 msgid "Sender"
 msgstr "Mittens"
 
-#: aleksis/core/models.py:566
+#: aleksis/core/models.py:583
 msgid "Recipient"
 msgstr ""
 
-#: aleksis/core/models.py:571 aleksis/core/models.py:911
+#: aleksis/core/models.py:588 aleksis/core/models.py:928
 msgid "Link"
 msgstr ""
 
-#: aleksis/core/models.py:573
+#: aleksis/core/models.py:590
 msgid "Read"
 msgstr ""
 
-#: aleksis/core/models.py:574
+#: aleksis/core/models.py:591
 msgid "Sent"
 msgstr ""
 
-#: aleksis/core/models.py:587
+#: aleksis/core/models.py:604
 #, fuzzy
 #| msgid "Notifications"
 msgid "Notification"
 msgstr "Nuntii"
 
-#: aleksis/core/models.py:656
+#: aleksis/core/models.py:673
 msgid "Link to detailed view"
 msgstr ""
 
-#: aleksis/core/models.py:659
+#: aleksis/core/models.py:676
 msgid "Date and time from when to show"
 msgstr ""
 
-#: aleksis/core/models.py:662
+#: aleksis/core/models.py:679
 msgid "Date and time until when to show"
 msgstr ""
 
-#: aleksis/core/models.py:686
+#: aleksis/core/models.py:703
 #, fuzzy
 #| msgid "Announcements"
 msgid "Announcement"
 msgstr "Nuntii"
 
-#: aleksis/core/models.py:724
+#: aleksis/core/models.py:741
 #, fuzzy
 #| msgid "Announcements"
 msgid "Announcement recipient"
 msgstr "Nuntii"
 
-#: aleksis/core/models.py:725
+#: aleksis/core/models.py:742
 #, fuzzy
 #| msgid "Announcements"
 msgid "Announcement recipients"
 msgstr "Nuntii"
 
-#: aleksis/core/models.py:780
+#: aleksis/core/models.py:797
 #, fuzzy
 #| msgid "Site title"
 msgid "Widget Title"
 msgstr "Titulus paginae"
 
-#: aleksis/core/models.py:781
+#: aleksis/core/models.py:798
 msgid "Activate Widget"
 msgstr ""
 
-#: aleksis/core/models.py:782
+#: aleksis/core/models.py:799
 #, fuzzy
 #| msgid "Site title"
 msgid "Widget is broken"
 msgstr "Titulus paginae"
 
-#: aleksis/core/models.py:785
+#: aleksis/core/models.py:802
 msgid "Size on mobile devices"
 msgstr ""
 
-#: aleksis/core/models.py:786
+#: aleksis/core/models.py:803
 msgid "<= 600 px, 12 columns"
 msgstr ""
 
-#: aleksis/core/models.py:791
+#: aleksis/core/models.py:808
 msgid "Size on tablet devices"
 msgstr ""
 
-#: aleksis/core/models.py:792
+#: aleksis/core/models.py:809
 msgid "> 600 px, 12 columns"
 msgstr ""
 
-#: aleksis/core/models.py:797
+#: aleksis/core/models.py:814
 msgid "Size on desktop devices"
 msgstr ""
 
-#: aleksis/core/models.py:798
+#: aleksis/core/models.py:815
 msgid "> 992 px, 12 columns"
 msgstr ""
 
-#: aleksis/core/models.py:803
+#: aleksis/core/models.py:820
 msgid "Size on large desktop devices"
 msgstr ""
 
-#: aleksis/core/models.py:804
+#: aleksis/core/models.py:821
 msgid "> 1200 px>, 12 columns"
 msgstr ""
 
-#: aleksis/core/models.py:835
+#: aleksis/core/models.py:852
 #, fuzzy
 #| msgid "Dashboard"
 msgid "Can edit default dashboard"
 msgstr "Forum"
 
-#: aleksis/core/models.py:836
+#: aleksis/core/models.py:853
 #, fuzzy
 #| msgid "Dashboard"
 msgid "Dashboard Widget"
 msgstr "Forum"
 
-#: aleksis/core/models.py:837
+#: aleksis/core/models.py:854
 #, fuzzy
 #| msgid "Dashboard"
 msgid "Dashboard Widgets"
 msgstr "Forum"
 
-#: aleksis/core/models.py:843
+#: aleksis/core/models.py:860
 msgid "URL"
 msgstr ""
 
-#: aleksis/core/models.py:844
+#: aleksis/core/models.py:861
 #, fuzzy
 #| msgid "Icon"
 msgid "Icon URL"
 msgstr "Nota"
 
-#: aleksis/core/models.py:850
+#: aleksis/core/models.py:867
 msgid "External link widget"
 msgstr ""
 
-#: aleksis/core/models.py:851
+#: aleksis/core/models.py:868
 msgid "External link widgets"
 msgstr ""
 
-#: aleksis/core/models.py:856
+#: aleksis/core/models.py:873
 #, fuzzy
 #| msgid "Dashboard"
 msgid "Dashboard widget"
 msgstr "Forum"
 
-#: aleksis/core/models.py:861
+#: aleksis/core/models.py:878
 msgid "Order"
 msgstr ""
 
-#: aleksis/core/models.py:862
+#: aleksis/core/models.py:879
 msgid "Part of the default dashboard"
 msgstr ""
 
-#: aleksis/core/models.py:877
+#: aleksis/core/models.py:894
 #, fuzzy
 #| msgid "Dashboard"
 msgid "Dashboard widget order"
 msgstr "Forum"
 
-#: aleksis/core/models.py:878
+#: aleksis/core/models.py:895
 #, fuzzy
 #| msgid "Dashboard"
 msgid "Dashboard widget orders"
 msgstr "Forum"
 
-#: aleksis/core/models.py:884
+#: aleksis/core/models.py:901
 msgid "Menu ID"
 msgstr ""
 
-#: aleksis/core/models.py:897
+#: aleksis/core/models.py:914
 msgid "Custom menu"
 msgstr ""
 
-#: aleksis/core/models.py:898
+#: aleksis/core/models.py:915
 msgid "Custom menus"
 msgstr ""
 
-#: aleksis/core/models.py:908
+#: aleksis/core/models.py:925
 msgid "Menu"
 msgstr ""
 
-#: aleksis/core/models.py:912
+#: aleksis/core/models.py:929
 msgid "Icon"
 msgstr "Nota"
 
-#: aleksis/core/models.py:918
+#: aleksis/core/models.py:935
 msgid "Custom menu item"
 msgstr ""
 
-#: aleksis/core/models.py:919
+#: aleksis/core/models.py:936
 msgid "Custom menu items"
 msgstr ""
 
-#: aleksis/core/models.py:933
+#: aleksis/core/models.py:950
 msgid "Title of type"
 msgstr ""
 
-#: aleksis/core/models.py:940 aleksis/core/templates/core/group/full.html:47
+#: aleksis/core/models.py:957 aleksis/core/templates/core/group/full.html:47
 #, fuzzy
 #| msgid "Group"
 msgid "Group type"
 msgstr "Grex"
 
-#: aleksis/core/models.py:954
+#: aleksis/core/models.py:971
 #, fuzzy
 #| msgid "System status"
 msgid "Can view system status"
 msgstr "Status systemae"
 
-#: aleksis/core/models.py:955
-#, fuzzy
-#| msgid "Persons and accounts"
-msgid "Can link persons to accounts"
-msgstr "Personae et computi"
-
-#: aleksis/core/models.py:956
+#: aleksis/core/models.py:972
 #, fuzzy
 #| msgid "Data management"
 msgid "Can manage data"
 msgstr "Adminstratio datarum"
 
-#: aleksis/core/models.py:957
+#: aleksis/core/models.py:973
 #, fuzzy
 #| msgid "Stop impersonation"
 msgid "Can impersonate"
 msgstr "Simulandum aliquem finire"
 
-#: aleksis/core/models.py:958
+#: aleksis/core/models.py:974
 msgid "Can use search"
 msgstr ""
 
-#: aleksis/core/models.py:959
+#: aleksis/core/models.py:975
 msgid "Can change site preferences"
 msgstr ""
 
-#: aleksis/core/models.py:960
+#: aleksis/core/models.py:976
 msgid "Can change person preferences"
 msgstr ""
 
-#: aleksis/core/models.py:961
+#: aleksis/core/models.py:977
 msgid "Can change group preferences"
 msgstr ""
 
-#: aleksis/core/models.py:962
+#: aleksis/core/models.py:978
 msgid "Can add oauth applications"
 msgstr ""
 
-#: aleksis/core/models.py:963
+#: aleksis/core/models.py:979
 msgid "Can list oauth applications"
 msgstr ""
 
-#: aleksis/core/models.py:964
+#: aleksis/core/models.py:980
 #, fuzzy
 #| msgid "E-mail address"
 msgid "Can view oauth applications"
 msgstr "Inscriptio electronica"
 
-#: aleksis/core/models.py:965
+#: aleksis/core/models.py:981
 msgid "Can update oauth applications"
 msgstr ""
 
-#: aleksis/core/models.py:966
+#: aleksis/core/models.py:982
 msgid "Can delete oauth applications"
 msgstr ""
 
-#: aleksis/core/models.py:967
+#: aleksis/core/models.py:983
 msgid "Can test PDF generation"
 msgstr ""
 
-#: aleksis/core/models.py:1003
+#: aleksis/core/models.py:1019
 msgid "Related data check task"
 msgstr ""
 
-#: aleksis/core/models.py:1011
+#: aleksis/core/models.py:1027
 msgid "Issue solved"
 msgstr ""
 
-#: aleksis/core/models.py:1012
+#: aleksis/core/models.py:1028
 #, fuzzy
 #| msgid "Notifications"
 msgid "Notification sent"
 msgstr "Nuntii"
 
-#: aleksis/core/models.py:1025
+#: aleksis/core/models.py:1041
 msgid "Data check result"
 msgstr ""
 
-#: aleksis/core/models.py:1026
+#: aleksis/core/models.py:1042
 msgid "Data check results"
 msgstr ""
 
-#: aleksis/core/models.py:1028
+#: aleksis/core/models.py:1044
 msgid "Can run data checks"
 msgstr ""
 
-#: aleksis/core/models.py:1029
+#: aleksis/core/models.py:1045
 msgid "Can solve data check problems"
 msgstr ""
 
-#: aleksis/core/models.py:1044
+#: aleksis/core/models.py:1060
 msgid "Owner"
 msgstr ""
 
-#: aleksis/core/models.py:1048
+#: aleksis/core/models.py:1064
 msgid "File expires at"
 msgstr ""
 
-#: aleksis/core/models.py:1050
+#: aleksis/core/models.py:1066
 msgid "Generated HTML file"
 msgstr ""
 
-#: aleksis/core/models.py:1052
+#: aleksis/core/models.py:1068
 msgid "Generated PDF file"
 msgstr ""
 
-#: aleksis/core/models.py:1059
+#: aleksis/core/models.py:1075
 msgid "PDF file"
 msgstr ""
 
-#: aleksis/core/models.py:1060
+#: aleksis/core/models.py:1076
 msgid "PDF files"
 msgstr ""
 
-#: aleksis/core/models.py:1065
+#: aleksis/core/models.py:1081
 msgid "Task result"
 msgstr ""
 
-#: aleksis/core/models.py:1068
+#: aleksis/core/models.py:1084
 msgid "Task user"
 msgstr ""
 
-#: aleksis/core/models.py:1080
+#: aleksis/core/models.py:1096
 msgid "Task user assignment"
 msgstr ""
 
-#: aleksis/core/models.py:1081
+#: aleksis/core/models.py:1097
 msgid "Task user assignments"
 msgstr ""
 
@@ -1144,75 +1133,71 @@ msgstr ""
 msgid "Official name of the school, e.g. as given by supervisory authority"
 msgstr "Officialis nomen scolae, e. g."
 
-#: aleksis/core/preferences.py:256
-msgid "Enabled custom authentication backends"
-msgstr ""
-
-#: aleksis/core/preferences.py:268
+#: aleksis/core/preferences.py:254
 msgid "Allow users to change their passwords"
 msgstr ""
 
-#: aleksis/core/preferences.py:276
+#: aleksis/core/preferences.py:262
 msgid "Enable signup"
 msgstr ""
 
-#: aleksis/core/preferences.py:287
+#: aleksis/core/preferences.py:273
 msgid "Available languages"
 msgstr ""
 
-#: aleksis/core/preferences.py:299
+#: aleksis/core/preferences.py:285
 msgid "Send emails if data checks detect problems"
 msgstr ""
 
-#: aleksis/core/preferences.py:310
+#: aleksis/core/preferences.py:296
 msgid "Email recipients for data checks problem emails"
 msgstr ""
 
-#: aleksis/core/preferences.py:321
+#: aleksis/core/preferences.py:307
 msgid "Email recipient groups for data checks problem emails"
 msgstr ""
 
-#: aleksis/core/preferences.py:330
+#: aleksis/core/preferences.py:316
 msgid "Show dashboard to users without login"
 msgstr ""
 
-#: aleksis/core/preferences.py:339
+#: aleksis/core/preferences.py:325
 msgid "Allow users to edit their dashboard"
 msgstr ""
 
-#: aleksis/core/preferences.py:350
+#: aleksis/core/preferences.py:336
 msgid "Fields on person model which are editable by themselves."
 msgstr ""
 
-#: aleksis/core/preferences.py:364
+#: aleksis/core/preferences.py:350
 msgid "Editable fields on person model which should trigger a notification on change"
 msgstr ""
 
-#: aleksis/core/preferences.py:377
+#: aleksis/core/preferences.py:363
 msgid "Contact for notification if a person changes their data"
 msgstr ""
 
-#: aleksis/core/preferences.py:387
+#: aleksis/core/preferences.py:373
 msgid "PDF file expiration duration"
 msgstr ""
 
-#: aleksis/core/preferences.py:388
+#: aleksis/core/preferences.py:374
 msgid "in minutes"
 msgstr ""
 
-#: aleksis/core/preferences.py:398
+#: aleksis/core/preferences.py:384
 msgid "Automatically update the dashboard and its widgets"
 msgstr ""
 
-#: aleksis/core/preferences.py:408
+#: aleksis/core/preferences.py:394
 msgid "Automatically update the dashboard and its widgets sitewide"
 msgstr ""
 
-#: aleksis/core/settings.py:468
+#: aleksis/core/settings.py:452
 msgid "English"
 msgstr "Britannicus"
 
-#: aleksis/core/settings.py:469
+#: aleksis/core/settings.py:453
 msgid "German"
 msgstr "Germanus"
 
@@ -1380,7 +1365,7 @@ msgstr ""
 #: aleksis/core/templates/account/password_reset_done.html:5
 #: aleksis/core/templates/account/verification_email_required.html:5
 #: aleksis/core/templates/account/verification_email_required.html:6
-#: aleksis/core/templates/two_factor/core/login.html:100
+#: aleksis/core/templates/two_factor/core/login.html:81
 msgid "Reset password"
 msgstr ""
 
@@ -2169,35 +2154,13 @@ msgid ""
 "          "
 msgstr ""
 
-#: aleksis/core/templates/core/person/accounts.html:12
-#: aleksis/core/templates/core/person/accounts.html:14
+#: aleksis/core/templates/core/person/create.html:12
+#: aleksis/core/templates/core/person/create.html:13
+#: aleksis/core/templates/core/person/list.html:17
 #, fuzzy
-#| msgid "Persons and accounts"
-msgid "Link persons to accounts"
-msgstr "Personae et computi"
-
-#: aleksis/core/templates/core/person/accounts.html:21
-msgid ""
-"\n"
-"        You can use this form to assign user accounts to persons. Use the\n"
-"        dropdowns to select existing accounts; use the text fields to create new\n"
-"        accounts on-the-fly. The latter will create a new account with the\n"
-"        entered username and copy all other details from the person.\n"
-"      "
-msgstr ""
-
-#: aleksis/core/templates/core/person/accounts.html:36
-#: aleksis/core/templates/core/person/accounts.html:60
-msgid "Update"
-msgstr ""
-
-#: aleksis/core/templates/core/person/accounts.html:42
-msgid "Existing account"
-msgstr ""
-
-#: aleksis/core/templates/core/person/accounts.html:43
-msgid "New account"
-msgstr ""
+#| msgid "Stop impersonation"
+msgid "Create person"
+msgstr "Simulandum aliquem finire"
 
 #: aleksis/core/templates/core/person/edit.html:12
 #: aleksis/core/templates/core/person/edit.html:13
@@ -2205,6 +2168,8 @@ msgid "Edit person"
 msgstr ""
 
 #: aleksis/core/templates/core/person/full.html:44
+#: aleksis/core/templates/impersonate/list_users.html:7
+#: aleksis/core/templates/impersonate/list_users.html:8
 #, fuzzy
 #| msgid "Impersonation"
 msgid "Impersonate"
@@ -2218,12 +2183,6 @@ msgstr ""
 msgid "Children"
 msgstr ""
 
-#: aleksis/core/templates/core/person/list.html:17
-#, fuzzy
-#| msgid "Stop impersonation"
-msgid "Create person"
-msgstr "Simulandum aliquem finire"
-
 #: aleksis/core/templates/core/person/list.html:21
 msgid "Filter persons"
 msgstr ""
@@ -2262,12 +2221,6 @@ msgstr ""
 msgid "Save preferences"
 msgstr ""
 
-#: aleksis/core/templates/impersonate/list_users.html:8
-#, fuzzy
-#| msgid "Impersonation"
-msgid "Impersonate user"
-msgstr "Simulare aliquem"
-
 #: aleksis/core/templates/oauth2_provider/application_confirm_delete.html:5
 #: aleksis/core/templates/oauth2_provider/application_confirm_delete.html:6
 msgid "Delete application"
@@ -2637,64 +2590,70 @@ msgstr ""
 msgid "Generate Tokens"
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:18
+#: aleksis/core/templates/two_factor/core/login.html:20
 msgid "Login with username and password"
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:26
-msgid "You have no permission to view this page. Please login with an other account."
+#: aleksis/core/templates/two_factor/core/login.html:28
+msgid ""
+"You have no permission to view this page. Please login with an other\n"
+"                    account."
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:33
+#: aleksis/core/templates/two_factor/core/login.html:36
 msgid "Please login to see this page."
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:43
+#: aleksis/core/templates/two_factor/core/login.html:46
 msgid ""
 "\n"
-"                      We are calling your phone right now, please enter the\n"
-"                      digits you hear.\n"
-"                    "
+"                        We are calling your phone right now, please enter the\n"
+"                        digits you hear.\n"
+"                      "
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:48
+#: aleksis/core/templates/two_factor/core/login.html:51
 msgid ""
 "\n"
-"                      We sent you a text message, please enter the tokens we\n"
-"                      sent.\n"
-"                    "
+"                        We sent you a text message, please enter the tokens we\n"
+"                        sent.\n"
+"                      "
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:53
+#: aleksis/core/templates/two_factor/core/login.html:56
 msgid ""
 "\n"
-"                      Please enter the tokens generated by your token\n"
-"                      generator.\n"
-"                    "
+"                        Please enter the tokens generated by your token\n"
+"                        generator.\n"
+"                      "
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:59
+#: aleksis/core/templates/two_factor/core/login.html:62
 msgid ""
 "\n"
-"                    Use this form for entering backup tokens for logging in.\n"
-"                    These tokens have been generated for you to print and keep safe. Please\n"
-"                    enter one of these backup tokens to login to your account.\n"
-"                  "
+"                      Use this form for entering backup tokens for logging in.\n"
+"                      These tokens have been generated for you to print and keep safe. Please\n"
+"                      enter one of these backup tokens to login to your account.\n"
+"                    "
+msgstr ""
+
+#: aleksis/core/templates/two_factor/core/login.html:90
+msgid "Device currently not available?"
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:74
+#: aleksis/core/templates/two_factor/core/login.html:92
 msgid "Or, alternatively, use one of your backup phones:"
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:84
+#: aleksis/core/templates/two_factor/core/login.html:102
 msgid "As a last resort, you can use a backup token:"
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:87
+#: aleksis/core/templates/two_factor/core/login.html:105
 msgid "Use Backup Token"
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:110
+#: aleksis/core/templates/two_factor/core/login.html:116
 msgid "Use alternative login options"
 msgstr ""
 
@@ -2959,113 +2918,131 @@ msgstr ""
 msgid "Download PDF"
 msgstr ""
 
-#: aleksis/core/views.py:253
+#: aleksis/core/views.py:251
 msgid "The school term has been created."
 msgstr ""
 
-#: aleksis/core/views.py:265
+#: aleksis/core/views.py:263
 msgid "The school term has been saved."
 msgstr ""
 
-#: aleksis/core/views.py:410
+#: aleksis/core/views.py:387
 msgid "The child groups were successfully saved."
 msgstr ""
 
-#: aleksis/core/views.py:471
+#: aleksis/core/views.py:406 aleksis/core/views.py:416
 msgid "The person has been saved."
 msgstr ""
 
-#: aleksis/core/views.py:510
+#: aleksis/core/views.py:466
 msgid "The group has been saved."
 msgstr ""
 
-#: aleksis/core/views.py:607
+#: aleksis/core/views.py:563
 msgid "The announcement has been saved."
 msgstr ""
 
-#: aleksis/core/views.py:623
+#: aleksis/core/views.py:579
 msgid "The announcement has been deleted."
 msgstr ""
 
-#: aleksis/core/views.py:707
+#: aleksis/core/views.py:663
 msgid "The preferences have been saved successfully."
 msgstr ""
 
-#: aleksis/core/views.py:731
+#: aleksis/core/views.py:687
 msgid "The person has been deleted."
 msgstr ""
 
-#: aleksis/core/views.py:745
+#: aleksis/core/views.py:701
 msgid "The group has been deleted."
 msgstr ""
 
-#: aleksis/core/views.py:777
+#: aleksis/core/views.py:733
 msgid "The additional_field has been saved."
 msgstr ""
 
-#: aleksis/core/views.py:811
+#: aleksis/core/views.py:767
 msgid "The additional field has been deleted."
 msgstr ""
 
-#: aleksis/core/views.py:836
+#: aleksis/core/views.py:792
 msgid "The group type has been saved."
 msgstr ""
 
-#: aleksis/core/views.py:866
+#: aleksis/core/views.py:822
 msgid "The group type has been deleted."
 msgstr ""
 
-#: aleksis/core/views.py:899
+#: aleksis/core/views.py:855
 msgid "Progress: Run data checks"
 msgstr ""
 
-#: aleksis/core/views.py:900
+#: aleksis/core/views.py:856
 #, fuzzy
 #| msgid "System status"
 msgid "Run data checks …"
 msgstr "Status systemae"
 
-#: aleksis/core/views.py:901
+#: aleksis/core/views.py:857
 msgid "The data checks were run successfully."
 msgstr ""
 
-#: aleksis/core/views.py:902
+#: aleksis/core/views.py:858
 msgid "There was a problem while running data checks."
 msgstr ""
 
-#: aleksis/core/views.py:918
+#: aleksis/core/views.py:874
 #, python-brace-format
 msgid "The solve option '{solve_option_obj.verbose_name}' "
 msgstr ""
 
-#: aleksis/core/views.py:960
+#: aleksis/core/views.py:916
 msgid "The dashboard widget has been saved."
 msgstr ""
 
-#: aleksis/core/views.py:990
+#: aleksis/core/views.py:946
 msgid "The dashboard widget has been created."
 msgstr ""
 
-#: aleksis/core/views.py:1000
+#: aleksis/core/views.py:956
 msgid "The dashboard widget has been deleted."
 msgstr ""
 
-#: aleksis/core/views.py:1067
+#: aleksis/core/views.py:1023
 msgid "Your dashboard configuration has been saved successfully."
 msgstr ""
 
-#: aleksis/core/views.py:1069
+#: aleksis/core/views.py:1025
 msgid "The configuration of the default dashboard has been saved successfully."
 msgstr ""
 
-#: aleksis/core/views.py:1197
+#: aleksis/core/views.py:1153
 msgid "The third-party account could not be disconnected because it is the only login method available."
 msgstr ""
 
-#: aleksis/core/views.py:1204
+#: aleksis/core/views.py:1160
 msgid "The third-party account has been successfully disconnected."
 msgstr ""
 
+#~ msgid "Persons and accounts"
+#~ msgstr "Personae et computi"
+
+#, fuzzy
+#~| msgid "Persons and accounts"
+#~ msgid "Can link persons to accounts"
+#~ msgstr "Personae et computi"
+
+#, fuzzy
+#~| msgid "Persons and accounts"
+#~ msgid "Link persons to accounts"
+#~ msgstr "Personae et computi"
+
+#, fuzzy
+#~| msgid "Impersonation"
+#~ msgid "Impersonate user"
+#~ msgstr "Simulare aliquem"
+
 #~ msgid "School logo"
 #~ msgstr "Imago scolae"
 
diff --git a/aleksis/core/locale/la/LC_MESSAGES/djangojs.po b/aleksis/core/locale/la/LC_MESSAGES/djangojs.po
index e10a495775fcb643cbe11cc1ce0daf4c5fc649ef..dc6d028e5442a3666f35a7cb46e39e5c01cdd3f9 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: 2021-08-28 17:53+0200\n"
+"POT-Creation-Date: 2021-10-28 16:18+0200\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"
diff --git a/aleksis/core/locale/nb_NO/LC_MESSAGES/django.po b/aleksis/core/locale/nb_NO/LC_MESSAGES/django.po
index 8bb678db92f9b2860f4b806ddb7fc40e3a6d9149..ae2f8d194fcacd2bae0d16bb3350dfbaa978aaee 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: 2021-08-28 17:53+0200\n"
+"POT-Creation-Date: 2021-10-28 16:18+0200\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,23 +17,23 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: aleksis/core/apps.py:148 aleksis/core/settings.py:343
+#: aleksis/core/apps.py:150
 msgid "OpenID Connect scope"
 msgstr ""
 
-#: aleksis/core/apps.py:149 aleksis/core/settings.py:344
+#: aleksis/core/apps.py:151
 msgid "Given name, family name, link to profile and picture if existing."
 msgstr ""
 
-#: aleksis/core/apps.py:150 aleksis/core/settings.py:345
+#: aleksis/core/apps.py:152
 msgid "Full home postal address"
 msgstr ""
 
-#: aleksis/core/apps.py:151 aleksis/core/settings.py:346
+#: aleksis/core/apps.py:153
 msgid "Email address"
 msgstr ""
 
-#: aleksis/core/apps.py:152 aleksis/core/settings.py:347
+#: aleksis/core/apps.py:154
 msgid "Home and mobile phone"
 msgstr ""
 
@@ -75,124 +75,124 @@ msgstr ""
 msgid "Search by contact details"
 msgstr ""
 
-#: aleksis/core/forms.py:62
-msgid "You cannot set a new username when also selecting an existing user."
-msgstr ""
-
-#: aleksis/core/forms.py:66
-msgid "This username is already in use."
-msgstr ""
-
-#: aleksis/core/forms.py:90 aleksis/core/forms.py:412
+#: aleksis/core/forms.py:41 aleksis/core/forms.py:387
 msgid "Base data"
 msgstr ""
 
-#: aleksis/core/forms.py:96
+#: aleksis/core/forms.py:47
 msgid "Address"
 msgstr ""
 
-#: aleksis/core/forms.py:97
+#: aleksis/core/forms.py:48
 msgid "Contact data"
 msgstr ""
 
-#: aleksis/core/forms.py:99
+#: aleksis/core/forms.py:50
 msgid "Advanced personal data"
 msgstr ""
 
-#: aleksis/core/forms.py:142
+#: aleksis/core/forms.py:93
 msgid "New user"
 msgstr ""
 
-#: aleksis/core/forms.py:142
+#: aleksis/core/forms.py:93
 msgid "Create a new account"
 msgstr ""
 
-#: aleksis/core/forms.py:170 aleksis/core/models.py:116
+#: aleksis/core/forms.py:124
+msgid "You cannot set a new username when also selecting an existing user."
+msgstr ""
+
+#: aleksis/core/forms.py:128
+msgid "This username is already in use."
+msgstr ""
+
+#: aleksis/core/forms.py:145 aleksis/core/models.py:117
 msgid "School term"
 msgstr ""
 
-#: aleksis/core/forms.py:171
+#: aleksis/core/forms.py:146
 msgid "Common data"
 msgstr ""
 
-#: aleksis/core/forms.py:172 aleksis/core/forms.py:221
-#: aleksis/core/menus.py:238 aleksis/core/models.py:139
+#: aleksis/core/forms.py:147 aleksis/core/forms.py:196
+#: aleksis/core/menus.py:238 aleksis/core/models.py:140
 #: aleksis/core/templates/core/person/list.html:8
 #: aleksis/core/templates/core/person/list.html:9
 msgid "Persons"
 msgstr ""
 
-#: aleksis/core/forms.py:173
+#: aleksis/core/forms.py:148
 msgid "Additional data"
 msgstr ""
 
-#: aleksis/core/forms.py:213 aleksis/core/forms.py:216
-#: aleksis/core/models.py:59
+#: aleksis/core/forms.py:188 aleksis/core/forms.py:191
+#: aleksis/core/models.py:60
 msgid "Date"
 msgstr ""
 
-#: aleksis/core/forms.py:214 aleksis/core/forms.py:217
-#: aleksis/core/models.py:67
+#: aleksis/core/forms.py:189 aleksis/core/forms.py:192
+#: aleksis/core/models.py:68
 msgid "Time"
 msgstr ""
 
-#: aleksis/core/forms.py:234 aleksis/core/menus.py:249
-#: aleksis/core/models.py:381 aleksis/core/templates/core/group/list.html:8
+#: aleksis/core/forms.py:209 aleksis/core/menus.py:249
+#: aleksis/core/models.py:398 aleksis/core/templates/core/group/list.html:8
 #: aleksis/core/templates/core/group/list.html:9
 #: aleksis/core/templates/core/person/full.html:144
 msgid "Groups"
 msgstr ""
 
-#: aleksis/core/forms.py:244
+#: aleksis/core/forms.py:219
 msgid "From when until when should the announcement be displayed?"
 msgstr ""
 
-#: aleksis/core/forms.py:247
+#: aleksis/core/forms.py:222
 msgid "Who should see the announcement?"
 msgstr ""
 
-#: aleksis/core/forms.py:248
+#: aleksis/core/forms.py:223
 msgid "Write your announcement:"
 msgstr ""
 
-#: aleksis/core/forms.py:287
+#: aleksis/core/forms.py:262
 msgid "You are not allowed to create announcements which are only valid in the past."
 msgstr ""
 
-#: aleksis/core/forms.py:291
+#: aleksis/core/forms.py:266
 msgid "The from date and time must be earlier then the until date and time."
 msgstr ""
 
-#: aleksis/core/forms.py:300
+#: aleksis/core/forms.py:275
 msgid "You need at least one recipient."
 msgstr ""
 
-#: aleksis/core/forms.py:414
+#: aleksis/core/forms.py:389
 msgid "Account data"
 msgstr ""
 
-#: aleksis/core/forms.py:416
+#: aleksis/core/forms.py:391
 msgid "Consents"
 msgstr ""
 
-#: aleksis/core/forms.py:421
+#: aleksis/core/forms.py:396
 msgid "Password"
 msgstr ""
 
-#: aleksis/core/forms.py:427
+#: aleksis/core/forms.py:402
 msgid "Password (again)"
 msgstr ""
 
-#: aleksis/core/forms.py:436
+#: aleksis/core/forms.py:411
 #, python-brace-format
 msgid "I have read the <a href='{privacy_policy}'>Privacy policy</a> and agree with them."
 msgstr ""
 
-#: aleksis/core/forms.py:460
+#: aleksis/core/forms.py:435
 msgid "You must type the same password each time."
 msgstr ""
 
-#: aleksis/core/forms.py:605
+#: aleksis/core/forms.py:580
 msgid "No valid selection."
 msgstr ""
 
@@ -223,8 +223,8 @@ msgid "{task.status} - {task.result}"
 msgstr ""
 
 #: aleksis/core/menus.py:9 aleksis/core/templates/two_factor/core/login.html:6
-#: aleksis/core/templates/two_factor/core/login.html:20
-#: aleksis/core/templates/two_factor/core/login.html:95
+#: aleksis/core/templates/two_factor/core/login.html:22
+#: aleksis/core/templates/two_factor/core/login.html:76
 msgid "Login"
 msgstr ""
 
@@ -237,7 +237,7 @@ msgstr ""
 msgid "Dashboard"
 msgstr ""
 
-#: aleksis/core/menus.py:32 aleksis/core/models.py:588
+#: aleksis/core/menus.py:32 aleksis/core/models.py:605
 #: aleksis/core/preferences.py:26
 #: aleksis/core/templates/core/notifications.html:4
 #: aleksis/core/templates/core/notifications.html:5
@@ -295,13 +295,13 @@ msgstr ""
 msgid "Admin"
 msgstr ""
 
-#: aleksis/core/menus.py:127 aleksis/core/models.py:687
+#: aleksis/core/menus.py:127 aleksis/core/models.py:704
 #: aleksis/core/templates/core/announcement/list.html:7
 #: aleksis/core/templates/core/announcement/list.html:8
 msgid "Announcements"
 msgstr ""
 
-#: aleksis/core/menus.py:138 aleksis/core/models.py:117
+#: aleksis/core/menus.py:138 aleksis/core/models.py:118
 #: aleksis/core/templates/core/school_term/list.html:8
 #: aleksis/core/templates/core/school_term/list.html:9
 msgid "School terms"
@@ -352,570 +352,561 @@ msgstr ""
 msgid "People"
 msgstr ""
 
-#: aleksis/core/menus.py:260 aleksis/core/models.py:941
+#: aleksis/core/menus.py:260 aleksis/core/models.py:958
 #: aleksis/core/templates/core/group_type/list.html:8
 #: aleksis/core/templates/core/group_type/list.html:9
 msgid "Group types"
 msgstr ""
 
 #: aleksis/core/menus.py:271
-msgid "Persons and accounts"
-msgstr ""
-
-#: aleksis/core/menus.py:282
 msgid "Groups and child groups"
 msgstr ""
 
-#: aleksis/core/menus.py:293 aleksis/core/models.py:429
+#: aleksis/core/menus.py:282 aleksis/core/models.py:446
 #: aleksis/core/templates/core/additional_field/list.html:8
 #: aleksis/core/templates/core/additional_field/list.html:9
 msgid "Additional fields"
 msgstr ""
 
-#: aleksis/core/menus.py:308
+#: aleksis/core/menus.py:297
 #: aleksis/core/templates/core/group/child_groups.html:7
 #: aleksis/core/templates/core/group/child_groups.html:9
 msgid "Assign child groups to groups"
 msgstr ""
 
-#: aleksis/core/mixins.py:475
+#: aleksis/core/mixins.py:498
 msgid "Linked school term"
 msgstr ""
 
-#: aleksis/core/models.py:57
+#: aleksis/core/models.py:58
 msgid "Boolean (Yes/No)"
 msgstr ""
 
-#: aleksis/core/models.py:58
+#: aleksis/core/models.py:59
 msgid "Text (one line)"
 msgstr ""
 
-#: aleksis/core/models.py:60
+#: aleksis/core/models.py:61
 msgid "Date and time"
 msgstr ""
 
-#: aleksis/core/models.py:61
+#: aleksis/core/models.py:62
 msgid "Decimal number"
 msgstr ""
 
-#: aleksis/core/models.py:62 aleksis/core/models.py:185
+#: aleksis/core/models.py:63 aleksis/core/models.py:186
 msgid "E-mail address"
 msgstr ""
 
-#: aleksis/core/models.py:63
+#: aleksis/core/models.py:64
 msgid "Integer"
 msgstr ""
 
-#: aleksis/core/models.py:64
+#: aleksis/core/models.py:65
 msgid "IP address"
 msgstr ""
 
-#: aleksis/core/models.py:65
+#: aleksis/core/models.py:66
 msgid "Boolean or empty (Yes/No/Neither)"
 msgstr ""
 
-#: aleksis/core/models.py:66
+#: aleksis/core/models.py:67
 msgid "Text (multi-line)"
 msgstr ""
 
-#: aleksis/core/models.py:68
+#: aleksis/core/models.py:69
 msgid "URL / Link"
 msgstr ""
 
-#: aleksis/core/models.py:80 aleksis/core/models.py:910
+#: aleksis/core/models.py:81 aleksis/core/models.py:927
 msgid "Name"
 msgstr ""
 
-#: aleksis/core/models.py:82
+#: aleksis/core/models.py:83
 msgid "Start date"
 msgstr ""
 
-#: aleksis/core/models.py:83
+#: aleksis/core/models.py:84
 msgid "End date"
 msgstr ""
 
-#: aleksis/core/models.py:102
+#: aleksis/core/models.py:103
 msgid "The start date must be earlier than the end date."
 msgstr ""
 
-#: aleksis/core/models.py:109
+#: aleksis/core/models.py:110
 msgid "There is already a school term for this time or a part of this time."
 msgstr ""
 
-#: aleksis/core/models.py:138 aleksis/core/models.py:859
-#: aleksis/core/templates/core/person/accounts.html:41
+#: aleksis/core/models.py:139 aleksis/core/models.py:876
 msgid "Person"
 msgstr ""
 
-#: aleksis/core/models.py:141
+#: aleksis/core/models.py:142
 msgid "Can view address"
 msgstr ""
 
-#: aleksis/core/models.py:142
+#: aleksis/core/models.py:143
 msgid "Can view contact details"
 msgstr ""
 
-#: aleksis/core/models.py:143
+#: aleksis/core/models.py:144
 msgid "Can view photo"
 msgstr ""
 
-#: aleksis/core/models.py:144
+#: aleksis/core/models.py:145
 msgid "Can view persons groups"
 msgstr ""
 
-#: aleksis/core/models.py:145
+#: aleksis/core/models.py:146
 msgid "Can view personal details"
 msgstr ""
 
-#: aleksis/core/models.py:155
+#: aleksis/core/models.py:156
 msgid "female"
 msgstr ""
 
-#: aleksis/core/models.py:155
+#: aleksis/core/models.py:156
 msgid "male"
 msgstr ""
 
-#: aleksis/core/models.py:163
+#: aleksis/core/models.py:164
 msgid "Linked user"
 msgstr ""
 
-#: aleksis/core/models.py:165
+#: aleksis/core/models.py:166
 msgid "Is person active?"
 msgstr ""
 
-#: aleksis/core/models.py:167
+#: aleksis/core/models.py:168
 msgid "First name"
 msgstr ""
 
-#: aleksis/core/models.py:168
+#: aleksis/core/models.py:169
 msgid "Last name"
 msgstr ""
 
-#: aleksis/core/models.py:170
+#: aleksis/core/models.py:171
 msgid "Additional name(s)"
 msgstr ""
 
-#: aleksis/core/models.py:174 aleksis/core/models.py:398
+#: aleksis/core/models.py:175 aleksis/core/models.py:415
 msgid "Short name"
 msgstr ""
 
-#: aleksis/core/models.py:177
+#: aleksis/core/models.py:178
 msgid "Street"
 msgstr ""
 
-#: aleksis/core/models.py:178
+#: aleksis/core/models.py:179
 msgid "Street number"
 msgstr ""
 
-#: aleksis/core/models.py:179
+#: aleksis/core/models.py:180
 msgid "Postal code"
 msgstr ""
 
-#: aleksis/core/models.py:180
+#: aleksis/core/models.py:181
 msgid "Place"
 msgstr ""
 
-#: aleksis/core/models.py:182
+#: aleksis/core/models.py:183
 msgid "Home phone"
 msgstr ""
 
-#: aleksis/core/models.py:183
+#: aleksis/core/models.py:184
 msgid "Mobile phone"
 msgstr ""
 
-#: aleksis/core/models.py:187
+#: aleksis/core/models.py:188
 msgid "Date of birth"
 msgstr ""
 
-#: aleksis/core/models.py:188
+#: aleksis/core/models.py:189
 msgid "Sex"
 msgstr ""
 
-#: aleksis/core/models.py:190
+#: aleksis/core/models.py:191
 msgid "Photo"
 msgstr ""
 
-#: aleksis/core/models.py:194 aleksis/core/templates/core/person/full.html:137
+#: aleksis/core/models.py:195 aleksis/core/templates/core/person/full.html:137
 msgid "Guardians / Parents"
 msgstr ""
 
-#: aleksis/core/models.py:201
+#: aleksis/core/models.py:202
 msgid "Primary group"
 msgstr ""
 
-#: aleksis/core/models.py:204 aleksis/core/models.py:546
-#: aleksis/core/models.py:570 aleksis/core/models.py:655
-#: aleksis/core/models.py:934 aleksis/core/templates/core/person/full.html:120
+#: aleksis/core/models.py:205 aleksis/core/models.py:563
+#: aleksis/core/models.py:587 aleksis/core/models.py:672
+#: aleksis/core/models.py:951 aleksis/core/templates/core/person/full.html:120
 msgid "Description"
 msgstr ""
 
-#: aleksis/core/models.py:353
+#: aleksis/core/models.py:370
 msgid "Title of field"
 msgstr ""
 
-#: aleksis/core/models.py:355
+#: aleksis/core/models.py:372
 msgid "Type of field"
 msgstr ""
 
-#: aleksis/core/models.py:362
+#: aleksis/core/models.py:379
 msgid "Addtitional field for groups"
 msgstr ""
 
-#: aleksis/core/models.py:363
+#: aleksis/core/models.py:380
 msgid "Addtitional fields for groups"
 msgstr ""
 
-#: aleksis/core/models.py:380
+#: aleksis/core/models.py:397
 msgid "Group"
 msgstr ""
 
-#: aleksis/core/models.py:383
+#: aleksis/core/models.py:400
 msgid "Can assign child groups to groups"
 msgstr ""
 
-#: aleksis/core/models.py:384
+#: aleksis/core/models.py:401
 msgid "Can view statistics about group."
 msgstr ""
 
-#: aleksis/core/models.py:396
+#: aleksis/core/models.py:413
 msgid "Long name"
 msgstr ""
 
-#: aleksis/core/models.py:406 aleksis/core/templates/core/group/full.html:85
+#: aleksis/core/models.py:423 aleksis/core/templates/core/group/full.html:85
 msgid "Members"
 msgstr ""
 
-#: aleksis/core/models.py:409 aleksis/core/templates/core/group/full.html:82
+#: aleksis/core/models.py:426 aleksis/core/templates/core/group/full.html:82
 msgid "Owners"
 msgstr ""
 
-#: aleksis/core/models.py:416 aleksis/core/templates/core/group/full.html:55
+#: aleksis/core/models.py:433 aleksis/core/templates/core/group/full.html:55
 msgid "Parent groups"
 msgstr ""
 
-#: aleksis/core/models.py:424
+#: aleksis/core/models.py:441
 msgid "Type of group"
 msgstr ""
 
-#: aleksis/core/models.py:542
+#: aleksis/core/models.py:559
 msgid "User"
 msgstr ""
 
-#: aleksis/core/models.py:545 aleksis/core/models.py:569
-#: aleksis/core/models.py:654
+#: aleksis/core/models.py:562 aleksis/core/models.py:586
+#: aleksis/core/models.py:671
 #: aleksis/core/templates/core/announcement/list.html:18
 msgid "Title"
 msgstr ""
 
-#: aleksis/core/models.py:548
+#: aleksis/core/models.py:565
 msgid "Application"
 msgstr ""
 
-#: aleksis/core/models.py:554
+#: aleksis/core/models.py:571
 msgid "Activity"
 msgstr ""
 
-#: aleksis/core/models.py:555
+#: aleksis/core/models.py:572
 msgid "Activities"
 msgstr ""
 
-#: aleksis/core/models.py:561
+#: aleksis/core/models.py:578
 msgid "Sender"
 msgstr ""
 
-#: aleksis/core/models.py:566
+#: aleksis/core/models.py:583
 msgid "Recipient"
 msgstr ""
 
-#: aleksis/core/models.py:571 aleksis/core/models.py:911
+#: aleksis/core/models.py:588 aleksis/core/models.py:928
 msgid "Link"
 msgstr ""
 
-#: aleksis/core/models.py:573
+#: aleksis/core/models.py:590
 msgid "Read"
 msgstr ""
 
-#: aleksis/core/models.py:574
+#: aleksis/core/models.py:591
 msgid "Sent"
 msgstr ""
 
-#: aleksis/core/models.py:587
+#: aleksis/core/models.py:604
 msgid "Notification"
 msgstr ""
 
-#: aleksis/core/models.py:656
+#: aleksis/core/models.py:673
 msgid "Link to detailed view"
 msgstr ""
 
-#: aleksis/core/models.py:659
+#: aleksis/core/models.py:676
 msgid "Date and time from when to show"
 msgstr ""
 
-#: aleksis/core/models.py:662
+#: aleksis/core/models.py:679
 msgid "Date and time until when to show"
 msgstr ""
 
-#: aleksis/core/models.py:686
+#: aleksis/core/models.py:703
 msgid "Announcement"
 msgstr ""
 
-#: aleksis/core/models.py:724
+#: aleksis/core/models.py:741
 msgid "Announcement recipient"
 msgstr ""
 
-#: aleksis/core/models.py:725
+#: aleksis/core/models.py:742
 msgid "Announcement recipients"
 msgstr ""
 
-#: aleksis/core/models.py:780
+#: aleksis/core/models.py:797
 msgid "Widget Title"
 msgstr ""
 
-#: aleksis/core/models.py:781
+#: aleksis/core/models.py:798
 msgid "Activate Widget"
 msgstr ""
 
-#: aleksis/core/models.py:782
+#: aleksis/core/models.py:799
 msgid "Widget is broken"
 msgstr ""
 
-#: aleksis/core/models.py:785
+#: aleksis/core/models.py:802
 msgid "Size on mobile devices"
 msgstr ""
 
-#: aleksis/core/models.py:786
+#: aleksis/core/models.py:803
 msgid "<= 600 px, 12 columns"
 msgstr ""
 
-#: aleksis/core/models.py:791
+#: aleksis/core/models.py:808
 msgid "Size on tablet devices"
 msgstr ""
 
-#: aleksis/core/models.py:792
+#: aleksis/core/models.py:809
 msgid "> 600 px, 12 columns"
 msgstr ""
 
-#: aleksis/core/models.py:797
+#: aleksis/core/models.py:814
 msgid "Size on desktop devices"
 msgstr ""
 
-#: aleksis/core/models.py:798
+#: aleksis/core/models.py:815
 msgid "> 992 px, 12 columns"
 msgstr ""
 
-#: aleksis/core/models.py:803
+#: aleksis/core/models.py:820
 msgid "Size on large desktop devices"
 msgstr ""
 
-#: aleksis/core/models.py:804
+#: aleksis/core/models.py:821
 msgid "> 1200 px>, 12 columns"
 msgstr ""
 
-#: aleksis/core/models.py:835
+#: aleksis/core/models.py:852
 msgid "Can edit default dashboard"
 msgstr ""
 
-#: aleksis/core/models.py:836
+#: aleksis/core/models.py:853
 msgid "Dashboard Widget"
 msgstr ""
 
-#: aleksis/core/models.py:837
+#: aleksis/core/models.py:854
 msgid "Dashboard Widgets"
 msgstr ""
 
-#: aleksis/core/models.py:843
+#: aleksis/core/models.py:860
 msgid "URL"
 msgstr ""
 
-#: aleksis/core/models.py:844
+#: aleksis/core/models.py:861
 msgid "Icon URL"
 msgstr ""
 
-#: aleksis/core/models.py:850
+#: aleksis/core/models.py:867
 msgid "External link widget"
 msgstr ""
 
-#: aleksis/core/models.py:851
+#: aleksis/core/models.py:868
 msgid "External link widgets"
 msgstr ""
 
-#: aleksis/core/models.py:856
+#: aleksis/core/models.py:873
 msgid "Dashboard widget"
 msgstr ""
 
-#: aleksis/core/models.py:861
+#: aleksis/core/models.py:878
 msgid "Order"
 msgstr ""
 
-#: aleksis/core/models.py:862
+#: aleksis/core/models.py:879
 msgid "Part of the default dashboard"
 msgstr ""
 
-#: aleksis/core/models.py:877
+#: aleksis/core/models.py:894
 msgid "Dashboard widget order"
 msgstr ""
 
-#: aleksis/core/models.py:878
+#: aleksis/core/models.py:895
 msgid "Dashboard widget orders"
 msgstr ""
 
-#: aleksis/core/models.py:884
+#: aleksis/core/models.py:901
 msgid "Menu ID"
 msgstr ""
 
-#: aleksis/core/models.py:897
+#: aleksis/core/models.py:914
 msgid "Custom menu"
 msgstr ""
 
-#: aleksis/core/models.py:898
+#: aleksis/core/models.py:915
 msgid "Custom menus"
 msgstr ""
 
-#: aleksis/core/models.py:908
+#: aleksis/core/models.py:925
 msgid "Menu"
 msgstr ""
 
-#: aleksis/core/models.py:912
+#: aleksis/core/models.py:929
 msgid "Icon"
 msgstr ""
 
-#: aleksis/core/models.py:918
+#: aleksis/core/models.py:935
 msgid "Custom menu item"
 msgstr ""
 
-#: aleksis/core/models.py:919
+#: aleksis/core/models.py:936
 msgid "Custom menu items"
 msgstr ""
 
-#: aleksis/core/models.py:933
+#: aleksis/core/models.py:950
 msgid "Title of type"
 msgstr ""
 
-#: aleksis/core/models.py:940 aleksis/core/templates/core/group/full.html:47
+#: aleksis/core/models.py:957 aleksis/core/templates/core/group/full.html:47
 msgid "Group type"
 msgstr ""
 
-#: aleksis/core/models.py:954
+#: aleksis/core/models.py:971
 msgid "Can view system status"
 msgstr ""
 
-#: aleksis/core/models.py:955
-msgid "Can link persons to accounts"
-msgstr ""
-
-#: aleksis/core/models.py:956
+#: aleksis/core/models.py:972
 msgid "Can manage data"
 msgstr ""
 
-#: aleksis/core/models.py:957
+#: aleksis/core/models.py:973
 msgid "Can impersonate"
 msgstr ""
 
-#: aleksis/core/models.py:958
+#: aleksis/core/models.py:974
 msgid "Can use search"
 msgstr ""
 
-#: aleksis/core/models.py:959
+#: aleksis/core/models.py:975
 msgid "Can change site preferences"
 msgstr ""
 
-#: aleksis/core/models.py:960
+#: aleksis/core/models.py:976
 msgid "Can change person preferences"
 msgstr ""
 
-#: aleksis/core/models.py:961
+#: aleksis/core/models.py:977
 msgid "Can change group preferences"
 msgstr ""
 
-#: aleksis/core/models.py:962
+#: aleksis/core/models.py:978
 msgid "Can add oauth applications"
 msgstr ""
 
-#: aleksis/core/models.py:963
+#: aleksis/core/models.py:979
 msgid "Can list oauth applications"
 msgstr ""
 
-#: aleksis/core/models.py:964
+#: aleksis/core/models.py:980
 msgid "Can view oauth applications"
 msgstr ""
 
-#: aleksis/core/models.py:965
+#: aleksis/core/models.py:981
 msgid "Can update oauth applications"
 msgstr ""
 
-#: aleksis/core/models.py:966
+#: aleksis/core/models.py:982
 msgid "Can delete oauth applications"
 msgstr ""
 
-#: aleksis/core/models.py:967
+#: aleksis/core/models.py:983
 msgid "Can test PDF generation"
 msgstr ""
 
-#: aleksis/core/models.py:1003
+#: aleksis/core/models.py:1019
 msgid "Related data check task"
 msgstr ""
 
-#: aleksis/core/models.py:1011
+#: aleksis/core/models.py:1027
 msgid "Issue solved"
 msgstr ""
 
-#: aleksis/core/models.py:1012
+#: aleksis/core/models.py:1028
 msgid "Notification sent"
 msgstr ""
 
-#: aleksis/core/models.py:1025
+#: aleksis/core/models.py:1041
 msgid "Data check result"
 msgstr ""
 
-#: aleksis/core/models.py:1026
+#: aleksis/core/models.py:1042
 msgid "Data check results"
 msgstr ""
 
-#: aleksis/core/models.py:1028
+#: aleksis/core/models.py:1044
 msgid "Can run data checks"
 msgstr ""
 
-#: aleksis/core/models.py:1029
+#: aleksis/core/models.py:1045
 msgid "Can solve data check problems"
 msgstr ""
 
-#: aleksis/core/models.py:1044
+#: aleksis/core/models.py:1060
 msgid "Owner"
 msgstr ""
 
-#: aleksis/core/models.py:1048
+#: aleksis/core/models.py:1064
 msgid "File expires at"
 msgstr ""
 
-#: aleksis/core/models.py:1050
+#: aleksis/core/models.py:1066
 msgid "Generated HTML file"
 msgstr ""
 
-#: aleksis/core/models.py:1052
+#: aleksis/core/models.py:1068
 msgid "Generated PDF file"
 msgstr ""
 
-#: aleksis/core/models.py:1059
+#: aleksis/core/models.py:1075
 msgid "PDF file"
 msgstr ""
 
-#: aleksis/core/models.py:1060
+#: aleksis/core/models.py:1076
 msgid "PDF files"
 msgstr ""
 
-#: aleksis/core/models.py:1065
+#: aleksis/core/models.py:1081
 msgid "Task result"
 msgstr ""
 
-#: aleksis/core/models.py:1068
+#: aleksis/core/models.py:1084
 msgid "Task user"
 msgstr ""
 
-#: aleksis/core/models.py:1080
+#: aleksis/core/models.py:1096
 msgid "Task user assignment"
 msgstr ""
 
-#: aleksis/core/models.py:1081
+#: aleksis/core/models.py:1097
 msgid "Task user assignments"
 msgstr ""
 
@@ -1027,75 +1018,71 @@ msgstr ""
 msgid "Official name of the school, e.g. as given by supervisory authority"
 msgstr ""
 
-#: aleksis/core/preferences.py:256
-msgid "Enabled custom authentication backends"
-msgstr ""
-
-#: aleksis/core/preferences.py:268
+#: aleksis/core/preferences.py:254
 msgid "Allow users to change their passwords"
 msgstr ""
 
-#: aleksis/core/preferences.py:276
+#: aleksis/core/preferences.py:262
 msgid "Enable signup"
 msgstr ""
 
-#: aleksis/core/preferences.py:287
+#: aleksis/core/preferences.py:273
 msgid "Available languages"
 msgstr ""
 
-#: aleksis/core/preferences.py:299
+#: aleksis/core/preferences.py:285
 msgid "Send emails if data checks detect problems"
 msgstr ""
 
-#: aleksis/core/preferences.py:310
+#: aleksis/core/preferences.py:296
 msgid "Email recipients for data checks problem emails"
 msgstr ""
 
-#: aleksis/core/preferences.py:321
+#: aleksis/core/preferences.py:307
 msgid "Email recipient groups for data checks problem emails"
 msgstr ""
 
-#: aleksis/core/preferences.py:330
+#: aleksis/core/preferences.py:316
 msgid "Show dashboard to users without login"
 msgstr ""
 
-#: aleksis/core/preferences.py:339
+#: aleksis/core/preferences.py:325
 msgid "Allow users to edit their dashboard"
 msgstr ""
 
-#: aleksis/core/preferences.py:350
+#: aleksis/core/preferences.py:336
 msgid "Fields on person model which are editable by themselves."
 msgstr ""
 
-#: aleksis/core/preferences.py:364
+#: aleksis/core/preferences.py:350
 msgid "Editable fields on person model which should trigger a notification on change"
 msgstr ""
 
-#: aleksis/core/preferences.py:377
+#: aleksis/core/preferences.py:363
 msgid "Contact for notification if a person changes their data"
 msgstr ""
 
-#: aleksis/core/preferences.py:387
+#: aleksis/core/preferences.py:373
 msgid "PDF file expiration duration"
 msgstr ""
 
-#: aleksis/core/preferences.py:388
+#: aleksis/core/preferences.py:374
 msgid "in minutes"
 msgstr ""
 
-#: aleksis/core/preferences.py:398
+#: aleksis/core/preferences.py:384
 msgid "Automatically update the dashboard and its widgets"
 msgstr ""
 
-#: aleksis/core/preferences.py:408
+#: aleksis/core/preferences.py:394
 msgid "Automatically update the dashboard and its widgets sitewide"
 msgstr ""
 
-#: aleksis/core/settings.py:468
+#: aleksis/core/settings.py:452
 msgid "English"
 msgstr ""
 
-#: aleksis/core/settings.py:469
+#: aleksis/core/settings.py:453
 msgid "German"
 msgstr ""
 
@@ -1259,7 +1246,7 @@ msgstr ""
 #: aleksis/core/templates/account/password_reset_done.html:5
 #: aleksis/core/templates/account/verification_email_required.html:5
 #: aleksis/core/templates/account/verification_email_required.html:6
-#: aleksis/core/templates/two_factor/core/login.html:100
+#: aleksis/core/templates/two_factor/core/login.html:81
 msgid "Reset password"
 msgstr ""
 
@@ -1996,32 +1983,10 @@ msgid ""
 "          "
 msgstr ""
 
-#: aleksis/core/templates/core/person/accounts.html:12
-#: aleksis/core/templates/core/person/accounts.html:14
-msgid "Link persons to accounts"
-msgstr ""
-
-#: aleksis/core/templates/core/person/accounts.html:21
-msgid ""
-"\n"
-"        You can use this form to assign user accounts to persons. Use the\n"
-"        dropdowns to select existing accounts; use the text fields to create new\n"
-"        accounts on-the-fly. The latter will create a new account with the\n"
-"        entered username and copy all other details from the person.\n"
-"      "
-msgstr ""
-
-#: aleksis/core/templates/core/person/accounts.html:36
-#: aleksis/core/templates/core/person/accounts.html:60
-msgid "Update"
-msgstr ""
-
-#: aleksis/core/templates/core/person/accounts.html:42
-msgid "Existing account"
-msgstr ""
-
-#: aleksis/core/templates/core/person/accounts.html:43
-msgid "New account"
+#: aleksis/core/templates/core/person/create.html:12
+#: aleksis/core/templates/core/person/create.html:13
+#: aleksis/core/templates/core/person/list.html:17
+msgid "Create person"
 msgstr ""
 
 #: aleksis/core/templates/core/person/edit.html:12
@@ -2030,6 +1995,8 @@ msgid "Edit person"
 msgstr ""
 
 #: aleksis/core/templates/core/person/full.html:44
+#: aleksis/core/templates/impersonate/list_users.html:7
+#: aleksis/core/templates/impersonate/list_users.html:8
 msgid "Impersonate"
 msgstr ""
 
@@ -2041,10 +2008,6 @@ msgstr ""
 msgid "Children"
 msgstr ""
 
-#: aleksis/core/templates/core/person/list.html:17
-msgid "Create person"
-msgstr ""
-
 #: aleksis/core/templates/core/person/list.html:21
 msgid "Filter persons"
 msgstr ""
@@ -2081,10 +2044,6 @@ msgstr ""
 msgid "Save preferences"
 msgstr ""
 
-#: aleksis/core/templates/impersonate/list_users.html:8
-msgid "Impersonate user"
-msgstr ""
-
 #: aleksis/core/templates/oauth2_provider/application_confirm_delete.html:5
 #: aleksis/core/templates/oauth2_provider/application_confirm_delete.html:6
 msgid "Delete application"
@@ -2437,64 +2396,70 @@ msgstr ""
 msgid "Generate Tokens"
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:18
+#: aleksis/core/templates/two_factor/core/login.html:20
 msgid "Login with username and password"
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:26
-msgid "You have no permission to view this page. Please login with an other account."
+#: aleksis/core/templates/two_factor/core/login.html:28
+msgid ""
+"You have no permission to view this page. Please login with an other\n"
+"                    account."
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:33
+#: aleksis/core/templates/two_factor/core/login.html:36
 msgid "Please login to see this page."
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:43
+#: aleksis/core/templates/two_factor/core/login.html:46
 msgid ""
 "\n"
-"                      We are calling your phone right now, please enter the\n"
-"                      digits you hear.\n"
-"                    "
+"                        We are calling your phone right now, please enter the\n"
+"                        digits you hear.\n"
+"                      "
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:48
+#: aleksis/core/templates/two_factor/core/login.html:51
 msgid ""
 "\n"
-"                      We sent you a text message, please enter the tokens we\n"
-"                      sent.\n"
-"                    "
+"                        We sent you a text message, please enter the tokens we\n"
+"                        sent.\n"
+"                      "
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:53
+#: aleksis/core/templates/two_factor/core/login.html:56
 msgid ""
 "\n"
-"                      Please enter the tokens generated by your token\n"
-"                      generator.\n"
-"                    "
+"                        Please enter the tokens generated by your token\n"
+"                        generator.\n"
+"                      "
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:59
+#: aleksis/core/templates/two_factor/core/login.html:62
 msgid ""
 "\n"
-"                    Use this form for entering backup tokens for logging in.\n"
-"                    These tokens have been generated for you to print and keep safe. Please\n"
-"                    enter one of these backup tokens to login to your account.\n"
-"                  "
+"                      Use this form for entering backup tokens for logging in.\n"
+"                      These tokens have been generated for you to print and keep safe. Please\n"
+"                      enter one of these backup tokens to login to your account.\n"
+"                    "
+msgstr ""
+
+#: aleksis/core/templates/two_factor/core/login.html:90
+msgid "Device currently not available?"
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:74
+#: aleksis/core/templates/two_factor/core/login.html:92
 msgid "Or, alternatively, use one of your backup phones:"
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:84
+#: aleksis/core/templates/two_factor/core/login.html:102
 msgid "As a last resort, you can use a backup token:"
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:87
+#: aleksis/core/templates/two_factor/core/login.html:105
 msgid "Use Backup Token"
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:110
+#: aleksis/core/templates/two_factor/core/login.html:116
 msgid "Use alternative login options"
 msgstr ""
 
@@ -2759,108 +2724,108 @@ msgstr ""
 msgid "Download PDF"
 msgstr ""
 
-#: aleksis/core/views.py:253
+#: aleksis/core/views.py:251
 msgid "The school term has been created."
 msgstr ""
 
-#: aleksis/core/views.py:265
+#: aleksis/core/views.py:263
 msgid "The school term has been saved."
 msgstr ""
 
-#: aleksis/core/views.py:410
+#: aleksis/core/views.py:387
 msgid "The child groups were successfully saved."
 msgstr ""
 
-#: aleksis/core/views.py:471
+#: aleksis/core/views.py:406 aleksis/core/views.py:416
 msgid "The person has been saved."
 msgstr ""
 
-#: aleksis/core/views.py:510
+#: aleksis/core/views.py:466
 msgid "The group has been saved."
 msgstr ""
 
-#: aleksis/core/views.py:607
+#: aleksis/core/views.py:563
 msgid "The announcement has been saved."
 msgstr ""
 
-#: aleksis/core/views.py:623
+#: aleksis/core/views.py:579
 msgid "The announcement has been deleted."
 msgstr ""
 
-#: aleksis/core/views.py:707
+#: aleksis/core/views.py:663
 msgid "The preferences have been saved successfully."
 msgstr ""
 
-#: aleksis/core/views.py:731
+#: aleksis/core/views.py:687
 msgid "The person has been deleted."
 msgstr ""
 
-#: aleksis/core/views.py:745
+#: aleksis/core/views.py:701
 msgid "The group has been deleted."
 msgstr ""
 
-#: aleksis/core/views.py:777
+#: aleksis/core/views.py:733
 msgid "The additional_field has been saved."
 msgstr ""
 
-#: aleksis/core/views.py:811
+#: aleksis/core/views.py:767
 msgid "The additional field has been deleted."
 msgstr ""
 
-#: aleksis/core/views.py:836
+#: aleksis/core/views.py:792
 msgid "The group type has been saved."
 msgstr ""
 
-#: aleksis/core/views.py:866
+#: aleksis/core/views.py:822
 msgid "The group type has been deleted."
 msgstr ""
 
-#: aleksis/core/views.py:899
+#: aleksis/core/views.py:855
 msgid "Progress: Run data checks"
 msgstr ""
 
-#: aleksis/core/views.py:900
+#: aleksis/core/views.py:856
 msgid "Run data checks …"
 msgstr ""
 
-#: aleksis/core/views.py:901
+#: aleksis/core/views.py:857
 msgid "The data checks were run successfully."
 msgstr ""
 
-#: aleksis/core/views.py:902
+#: aleksis/core/views.py:858
 msgid "There was a problem while running data checks."
 msgstr ""
 
-#: aleksis/core/views.py:918
+#: aleksis/core/views.py:874
 #, python-brace-format
 msgid "The solve option '{solve_option_obj.verbose_name}' "
 msgstr ""
 
-#: aleksis/core/views.py:960
+#: aleksis/core/views.py:916
 msgid "The dashboard widget has been saved."
 msgstr ""
 
-#: aleksis/core/views.py:990
+#: aleksis/core/views.py:946
 msgid "The dashboard widget has been created."
 msgstr ""
 
-#: aleksis/core/views.py:1000
+#: aleksis/core/views.py:956
 msgid "The dashboard widget has been deleted."
 msgstr ""
 
-#: aleksis/core/views.py:1067
+#: aleksis/core/views.py:1023
 msgid "Your dashboard configuration has been saved successfully."
 msgstr ""
 
-#: aleksis/core/views.py:1069
+#: aleksis/core/views.py:1025
 msgid "The configuration of the default dashboard has been saved successfully."
 msgstr ""
 
-#: aleksis/core/views.py:1197
+#: aleksis/core/views.py:1153
 msgid "The third-party account could not be disconnected because it is the only login method available."
 msgstr ""
 
-#: aleksis/core/views.py:1204
+#: aleksis/core/views.py:1160
 msgid "The third-party account has been successfully disconnected."
 msgstr ""
 
diff --git a/aleksis/core/locale/nb_NO/LC_MESSAGES/djangojs.po b/aleksis/core/locale/nb_NO/LC_MESSAGES/djangojs.po
index e10a495775fcb643cbe11cc1ce0daf4c5fc649ef..dc6d028e5442a3666f35a7cb46e39e5c01cdd3f9 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: 2021-08-28 17:53+0200\n"
+"POT-Creation-Date: 2021-10-28 16:18+0200\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"
diff --git a/aleksis/core/locale/tr_TR/LC_MESSAGES/django.po b/aleksis/core/locale/tr_TR/LC_MESSAGES/django.po
index 1aca6607879e022ab2144b35ec41324db819b2ac..c1f28664922a7b5cbdac80d557c812092765b16f 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: 2021-08-28 17:53+0200\n"
+"POT-Creation-Date: 2021-10-28 16:18+0200\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,23 +17,23 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: aleksis/core/apps.py:148 aleksis/core/settings.py:343
+#: aleksis/core/apps.py:150
 msgid "OpenID Connect scope"
 msgstr ""
 
-#: aleksis/core/apps.py:149 aleksis/core/settings.py:344
+#: aleksis/core/apps.py:151
 msgid "Given name, family name, link to profile and picture if existing."
 msgstr ""
 
-#: aleksis/core/apps.py:150 aleksis/core/settings.py:345
+#: aleksis/core/apps.py:152
 msgid "Full home postal address"
 msgstr ""
 
-#: aleksis/core/apps.py:151 aleksis/core/settings.py:346
+#: aleksis/core/apps.py:153
 msgid "Email address"
 msgstr ""
 
-#: aleksis/core/apps.py:152 aleksis/core/settings.py:347
+#: aleksis/core/apps.py:154
 msgid "Home and mobile phone"
 msgstr ""
 
@@ -75,124 +75,124 @@ msgstr ""
 msgid "Search by contact details"
 msgstr ""
 
-#: aleksis/core/forms.py:62
-msgid "You cannot set a new username when also selecting an existing user."
-msgstr ""
-
-#: aleksis/core/forms.py:66
-msgid "This username is already in use."
-msgstr ""
-
-#: aleksis/core/forms.py:90 aleksis/core/forms.py:412
+#: aleksis/core/forms.py:41 aleksis/core/forms.py:387
 msgid "Base data"
 msgstr ""
 
-#: aleksis/core/forms.py:96
+#: aleksis/core/forms.py:47
 msgid "Address"
 msgstr ""
 
-#: aleksis/core/forms.py:97
+#: aleksis/core/forms.py:48
 msgid "Contact data"
 msgstr ""
 
-#: aleksis/core/forms.py:99
+#: aleksis/core/forms.py:50
 msgid "Advanced personal data"
 msgstr ""
 
-#: aleksis/core/forms.py:142
+#: aleksis/core/forms.py:93
 msgid "New user"
 msgstr ""
 
-#: aleksis/core/forms.py:142
+#: aleksis/core/forms.py:93
 msgid "Create a new account"
 msgstr ""
 
-#: aleksis/core/forms.py:170 aleksis/core/models.py:116
+#: aleksis/core/forms.py:124
+msgid "You cannot set a new username when also selecting an existing user."
+msgstr ""
+
+#: aleksis/core/forms.py:128
+msgid "This username is already in use."
+msgstr ""
+
+#: aleksis/core/forms.py:145 aleksis/core/models.py:117
 msgid "School term"
 msgstr ""
 
-#: aleksis/core/forms.py:171
+#: aleksis/core/forms.py:146
 msgid "Common data"
 msgstr ""
 
-#: aleksis/core/forms.py:172 aleksis/core/forms.py:221
-#: aleksis/core/menus.py:238 aleksis/core/models.py:139
+#: aleksis/core/forms.py:147 aleksis/core/forms.py:196
+#: aleksis/core/menus.py:238 aleksis/core/models.py:140
 #: aleksis/core/templates/core/person/list.html:8
 #: aleksis/core/templates/core/person/list.html:9
 msgid "Persons"
 msgstr ""
 
-#: aleksis/core/forms.py:173
+#: aleksis/core/forms.py:148
 msgid "Additional data"
 msgstr ""
 
-#: aleksis/core/forms.py:213 aleksis/core/forms.py:216
-#: aleksis/core/models.py:59
+#: aleksis/core/forms.py:188 aleksis/core/forms.py:191
+#: aleksis/core/models.py:60
 msgid "Date"
 msgstr ""
 
-#: aleksis/core/forms.py:214 aleksis/core/forms.py:217
-#: aleksis/core/models.py:67
+#: aleksis/core/forms.py:189 aleksis/core/forms.py:192
+#: aleksis/core/models.py:68
 msgid "Time"
 msgstr ""
 
-#: aleksis/core/forms.py:234 aleksis/core/menus.py:249
-#: aleksis/core/models.py:381 aleksis/core/templates/core/group/list.html:8
+#: aleksis/core/forms.py:209 aleksis/core/menus.py:249
+#: aleksis/core/models.py:398 aleksis/core/templates/core/group/list.html:8
 #: aleksis/core/templates/core/group/list.html:9
 #: aleksis/core/templates/core/person/full.html:144
 msgid "Groups"
 msgstr ""
 
-#: aleksis/core/forms.py:244
+#: aleksis/core/forms.py:219
 msgid "From when until when should the announcement be displayed?"
 msgstr ""
 
-#: aleksis/core/forms.py:247
+#: aleksis/core/forms.py:222
 msgid "Who should see the announcement?"
 msgstr ""
 
-#: aleksis/core/forms.py:248
+#: aleksis/core/forms.py:223
 msgid "Write your announcement:"
 msgstr ""
 
-#: aleksis/core/forms.py:287
+#: aleksis/core/forms.py:262
 msgid "You are not allowed to create announcements which are only valid in the past."
 msgstr ""
 
-#: aleksis/core/forms.py:291
+#: aleksis/core/forms.py:266
 msgid "The from date and time must be earlier then the until date and time."
 msgstr ""
 
-#: aleksis/core/forms.py:300
+#: aleksis/core/forms.py:275
 msgid "You need at least one recipient."
 msgstr ""
 
-#: aleksis/core/forms.py:414
+#: aleksis/core/forms.py:389
 msgid "Account data"
 msgstr ""
 
-#: aleksis/core/forms.py:416
+#: aleksis/core/forms.py:391
 msgid "Consents"
 msgstr ""
 
-#: aleksis/core/forms.py:421
+#: aleksis/core/forms.py:396
 msgid "Password"
 msgstr ""
 
-#: aleksis/core/forms.py:427
+#: aleksis/core/forms.py:402
 msgid "Password (again)"
 msgstr ""
 
-#: aleksis/core/forms.py:436
+#: aleksis/core/forms.py:411
 #, python-brace-format
 msgid "I have read the <a href='{privacy_policy}'>Privacy policy</a> and agree with them."
 msgstr ""
 
-#: aleksis/core/forms.py:460
+#: aleksis/core/forms.py:435
 msgid "You must type the same password each time."
 msgstr ""
 
-#: aleksis/core/forms.py:605
+#: aleksis/core/forms.py:580
 msgid "No valid selection."
 msgstr ""
 
@@ -223,8 +223,8 @@ msgid "{task.status} - {task.result}"
 msgstr ""
 
 #: aleksis/core/menus.py:9 aleksis/core/templates/two_factor/core/login.html:6
-#: aleksis/core/templates/two_factor/core/login.html:20
-#: aleksis/core/templates/two_factor/core/login.html:95
+#: aleksis/core/templates/two_factor/core/login.html:22
+#: aleksis/core/templates/two_factor/core/login.html:76
 msgid "Login"
 msgstr ""
 
@@ -237,7 +237,7 @@ msgstr ""
 msgid "Dashboard"
 msgstr ""
 
-#: aleksis/core/menus.py:32 aleksis/core/models.py:588
+#: aleksis/core/menus.py:32 aleksis/core/models.py:605
 #: aleksis/core/preferences.py:26
 #: aleksis/core/templates/core/notifications.html:4
 #: aleksis/core/templates/core/notifications.html:5
@@ -295,13 +295,13 @@ msgstr ""
 msgid "Admin"
 msgstr ""
 
-#: aleksis/core/menus.py:127 aleksis/core/models.py:687
+#: aleksis/core/menus.py:127 aleksis/core/models.py:704
 #: aleksis/core/templates/core/announcement/list.html:7
 #: aleksis/core/templates/core/announcement/list.html:8
 msgid "Announcements"
 msgstr ""
 
-#: aleksis/core/menus.py:138 aleksis/core/models.py:117
+#: aleksis/core/menus.py:138 aleksis/core/models.py:118
 #: aleksis/core/templates/core/school_term/list.html:8
 #: aleksis/core/templates/core/school_term/list.html:9
 msgid "School terms"
@@ -352,570 +352,561 @@ msgstr ""
 msgid "People"
 msgstr ""
 
-#: aleksis/core/menus.py:260 aleksis/core/models.py:941
+#: aleksis/core/menus.py:260 aleksis/core/models.py:958
 #: aleksis/core/templates/core/group_type/list.html:8
 #: aleksis/core/templates/core/group_type/list.html:9
 msgid "Group types"
 msgstr ""
 
 #: aleksis/core/menus.py:271
-msgid "Persons and accounts"
-msgstr ""
-
-#: aleksis/core/menus.py:282
 msgid "Groups and child groups"
 msgstr ""
 
-#: aleksis/core/menus.py:293 aleksis/core/models.py:429
+#: aleksis/core/menus.py:282 aleksis/core/models.py:446
 #: aleksis/core/templates/core/additional_field/list.html:8
 #: aleksis/core/templates/core/additional_field/list.html:9
 msgid "Additional fields"
 msgstr ""
 
-#: aleksis/core/menus.py:308
+#: aleksis/core/menus.py:297
 #: aleksis/core/templates/core/group/child_groups.html:7
 #: aleksis/core/templates/core/group/child_groups.html:9
 msgid "Assign child groups to groups"
 msgstr ""
 
-#: aleksis/core/mixins.py:475
+#: aleksis/core/mixins.py:498
 msgid "Linked school term"
 msgstr ""
 
-#: aleksis/core/models.py:57
+#: aleksis/core/models.py:58
 msgid "Boolean (Yes/No)"
 msgstr ""
 
-#: aleksis/core/models.py:58
+#: aleksis/core/models.py:59
 msgid "Text (one line)"
 msgstr ""
 
-#: aleksis/core/models.py:60
+#: aleksis/core/models.py:61
 msgid "Date and time"
 msgstr ""
 
-#: aleksis/core/models.py:61
+#: aleksis/core/models.py:62
 msgid "Decimal number"
 msgstr ""
 
-#: aleksis/core/models.py:62 aleksis/core/models.py:185
+#: aleksis/core/models.py:63 aleksis/core/models.py:186
 msgid "E-mail address"
 msgstr ""
 
-#: aleksis/core/models.py:63
+#: aleksis/core/models.py:64
 msgid "Integer"
 msgstr ""
 
-#: aleksis/core/models.py:64
+#: aleksis/core/models.py:65
 msgid "IP address"
 msgstr ""
 
-#: aleksis/core/models.py:65
+#: aleksis/core/models.py:66
 msgid "Boolean or empty (Yes/No/Neither)"
 msgstr ""
 
-#: aleksis/core/models.py:66
+#: aleksis/core/models.py:67
 msgid "Text (multi-line)"
 msgstr ""
 
-#: aleksis/core/models.py:68
+#: aleksis/core/models.py:69
 msgid "URL / Link"
 msgstr ""
 
-#: aleksis/core/models.py:80 aleksis/core/models.py:910
+#: aleksis/core/models.py:81 aleksis/core/models.py:927
 msgid "Name"
 msgstr ""
 
-#: aleksis/core/models.py:82
+#: aleksis/core/models.py:83
 msgid "Start date"
 msgstr ""
 
-#: aleksis/core/models.py:83
+#: aleksis/core/models.py:84
 msgid "End date"
 msgstr ""
 
-#: aleksis/core/models.py:102
+#: aleksis/core/models.py:103
 msgid "The start date must be earlier than the end date."
 msgstr ""
 
-#: aleksis/core/models.py:109
+#: aleksis/core/models.py:110
 msgid "There is already a school term for this time or a part of this time."
 msgstr ""
 
-#: aleksis/core/models.py:138 aleksis/core/models.py:859
-#: aleksis/core/templates/core/person/accounts.html:41
+#: aleksis/core/models.py:139 aleksis/core/models.py:876
 msgid "Person"
 msgstr ""
 
-#: aleksis/core/models.py:141
+#: aleksis/core/models.py:142
 msgid "Can view address"
 msgstr ""
 
-#: aleksis/core/models.py:142
+#: aleksis/core/models.py:143
 msgid "Can view contact details"
 msgstr ""
 
-#: aleksis/core/models.py:143
+#: aleksis/core/models.py:144
 msgid "Can view photo"
 msgstr ""
 
-#: aleksis/core/models.py:144
+#: aleksis/core/models.py:145
 msgid "Can view persons groups"
 msgstr ""
 
-#: aleksis/core/models.py:145
+#: aleksis/core/models.py:146
 msgid "Can view personal details"
 msgstr ""
 
-#: aleksis/core/models.py:155
+#: aleksis/core/models.py:156
 msgid "female"
 msgstr ""
 
-#: aleksis/core/models.py:155
+#: aleksis/core/models.py:156
 msgid "male"
 msgstr ""
 
-#: aleksis/core/models.py:163
+#: aleksis/core/models.py:164
 msgid "Linked user"
 msgstr ""
 
-#: aleksis/core/models.py:165
+#: aleksis/core/models.py:166
 msgid "Is person active?"
 msgstr ""
 
-#: aleksis/core/models.py:167
+#: aleksis/core/models.py:168
 msgid "First name"
 msgstr ""
 
-#: aleksis/core/models.py:168
+#: aleksis/core/models.py:169
 msgid "Last name"
 msgstr ""
 
-#: aleksis/core/models.py:170
+#: aleksis/core/models.py:171
 msgid "Additional name(s)"
 msgstr ""
 
-#: aleksis/core/models.py:174 aleksis/core/models.py:398
+#: aleksis/core/models.py:175 aleksis/core/models.py:415
 msgid "Short name"
 msgstr ""
 
-#: aleksis/core/models.py:177
+#: aleksis/core/models.py:178
 msgid "Street"
 msgstr ""
 
-#: aleksis/core/models.py:178
+#: aleksis/core/models.py:179
 msgid "Street number"
 msgstr ""
 
-#: aleksis/core/models.py:179
+#: aleksis/core/models.py:180
 msgid "Postal code"
 msgstr ""
 
-#: aleksis/core/models.py:180
+#: aleksis/core/models.py:181
 msgid "Place"
 msgstr ""
 
-#: aleksis/core/models.py:182
+#: aleksis/core/models.py:183
 msgid "Home phone"
 msgstr ""
 
-#: aleksis/core/models.py:183
+#: aleksis/core/models.py:184
 msgid "Mobile phone"
 msgstr ""
 
-#: aleksis/core/models.py:187
+#: aleksis/core/models.py:188
 msgid "Date of birth"
 msgstr ""
 
-#: aleksis/core/models.py:188
+#: aleksis/core/models.py:189
 msgid "Sex"
 msgstr ""
 
-#: aleksis/core/models.py:190
+#: aleksis/core/models.py:191
 msgid "Photo"
 msgstr ""
 
-#: aleksis/core/models.py:194 aleksis/core/templates/core/person/full.html:137
+#: aleksis/core/models.py:195 aleksis/core/templates/core/person/full.html:137
 msgid "Guardians / Parents"
 msgstr ""
 
-#: aleksis/core/models.py:201
+#: aleksis/core/models.py:202
 msgid "Primary group"
 msgstr ""
 
-#: aleksis/core/models.py:204 aleksis/core/models.py:546
-#: aleksis/core/models.py:570 aleksis/core/models.py:655
-#: aleksis/core/models.py:934 aleksis/core/templates/core/person/full.html:120
+#: aleksis/core/models.py:205 aleksis/core/models.py:563
+#: aleksis/core/models.py:587 aleksis/core/models.py:672
+#: aleksis/core/models.py:951 aleksis/core/templates/core/person/full.html:120
 msgid "Description"
 msgstr ""
 
-#: aleksis/core/models.py:353
+#: aleksis/core/models.py:370
 msgid "Title of field"
 msgstr ""
 
-#: aleksis/core/models.py:355
+#: aleksis/core/models.py:372
 msgid "Type of field"
 msgstr ""
 
-#: aleksis/core/models.py:362
+#: aleksis/core/models.py:379
 msgid "Addtitional field for groups"
 msgstr ""
 
-#: aleksis/core/models.py:363
+#: aleksis/core/models.py:380
 msgid "Addtitional fields for groups"
 msgstr ""
 
-#: aleksis/core/models.py:380
+#: aleksis/core/models.py:397
 msgid "Group"
 msgstr ""
 
-#: aleksis/core/models.py:383
+#: aleksis/core/models.py:400
 msgid "Can assign child groups to groups"
 msgstr ""
 
-#: aleksis/core/models.py:384
+#: aleksis/core/models.py:401
 msgid "Can view statistics about group."
 msgstr ""
 
-#: aleksis/core/models.py:396
+#: aleksis/core/models.py:413
 msgid "Long name"
 msgstr ""
 
-#: aleksis/core/models.py:406 aleksis/core/templates/core/group/full.html:85
+#: aleksis/core/models.py:423 aleksis/core/templates/core/group/full.html:85
 msgid "Members"
 msgstr ""
 
-#: aleksis/core/models.py:409 aleksis/core/templates/core/group/full.html:82
+#: aleksis/core/models.py:426 aleksis/core/templates/core/group/full.html:82
 msgid "Owners"
 msgstr ""
 
-#: aleksis/core/models.py:416 aleksis/core/templates/core/group/full.html:55
+#: aleksis/core/models.py:433 aleksis/core/templates/core/group/full.html:55
 msgid "Parent groups"
 msgstr ""
 
-#: aleksis/core/models.py:424
+#: aleksis/core/models.py:441
 msgid "Type of group"
 msgstr ""
 
-#: aleksis/core/models.py:542
+#: aleksis/core/models.py:559
 msgid "User"
 msgstr ""
 
-#: aleksis/core/models.py:545 aleksis/core/models.py:569
-#: aleksis/core/models.py:654
+#: aleksis/core/models.py:562 aleksis/core/models.py:586
+#: aleksis/core/models.py:671
 #: aleksis/core/templates/core/announcement/list.html:18
 msgid "Title"
 msgstr ""
 
-#: aleksis/core/models.py:548
+#: aleksis/core/models.py:565
 msgid "Application"
 msgstr ""
 
-#: aleksis/core/models.py:554
+#: aleksis/core/models.py:571
 msgid "Activity"
 msgstr ""
 
-#: aleksis/core/models.py:555
+#: aleksis/core/models.py:572
 msgid "Activities"
 msgstr ""
 
-#: aleksis/core/models.py:561
+#: aleksis/core/models.py:578
 msgid "Sender"
 msgstr ""
 
-#: aleksis/core/models.py:566
+#: aleksis/core/models.py:583
 msgid "Recipient"
 msgstr ""
 
-#: aleksis/core/models.py:571 aleksis/core/models.py:911
+#: aleksis/core/models.py:588 aleksis/core/models.py:928
 msgid "Link"
 msgstr ""
 
-#: aleksis/core/models.py:573
+#: aleksis/core/models.py:590
 msgid "Read"
 msgstr ""
 
-#: aleksis/core/models.py:574
+#: aleksis/core/models.py:591
 msgid "Sent"
 msgstr ""
 
-#: aleksis/core/models.py:587
+#: aleksis/core/models.py:604
 msgid "Notification"
 msgstr ""
 
-#: aleksis/core/models.py:656
+#: aleksis/core/models.py:673
 msgid "Link to detailed view"
 msgstr ""
 
-#: aleksis/core/models.py:659
+#: aleksis/core/models.py:676
 msgid "Date and time from when to show"
 msgstr ""
 
-#: aleksis/core/models.py:662
+#: aleksis/core/models.py:679
 msgid "Date and time until when to show"
 msgstr ""
 
-#: aleksis/core/models.py:686
+#: aleksis/core/models.py:703
 msgid "Announcement"
 msgstr ""
 
-#: aleksis/core/models.py:724
+#: aleksis/core/models.py:741
 msgid "Announcement recipient"
 msgstr ""
 
-#: aleksis/core/models.py:725
+#: aleksis/core/models.py:742
 msgid "Announcement recipients"
 msgstr ""
 
-#: aleksis/core/models.py:780
+#: aleksis/core/models.py:797
 msgid "Widget Title"
 msgstr ""
 
-#: aleksis/core/models.py:781
+#: aleksis/core/models.py:798
 msgid "Activate Widget"
 msgstr ""
 
-#: aleksis/core/models.py:782
+#: aleksis/core/models.py:799
 msgid "Widget is broken"
 msgstr ""
 
-#: aleksis/core/models.py:785
+#: aleksis/core/models.py:802
 msgid "Size on mobile devices"
 msgstr ""
 
-#: aleksis/core/models.py:786
+#: aleksis/core/models.py:803
 msgid "<= 600 px, 12 columns"
 msgstr ""
 
-#: aleksis/core/models.py:791
+#: aleksis/core/models.py:808
 msgid "Size on tablet devices"
 msgstr ""
 
-#: aleksis/core/models.py:792
+#: aleksis/core/models.py:809
 msgid "> 600 px, 12 columns"
 msgstr ""
 
-#: aleksis/core/models.py:797
+#: aleksis/core/models.py:814
 msgid "Size on desktop devices"
 msgstr ""
 
-#: aleksis/core/models.py:798
+#: aleksis/core/models.py:815
 msgid "> 992 px, 12 columns"
 msgstr ""
 
-#: aleksis/core/models.py:803
+#: aleksis/core/models.py:820
 msgid "Size on large desktop devices"
 msgstr ""
 
-#: aleksis/core/models.py:804
+#: aleksis/core/models.py:821
 msgid "> 1200 px>, 12 columns"
 msgstr ""
 
-#: aleksis/core/models.py:835
+#: aleksis/core/models.py:852
 msgid "Can edit default dashboard"
 msgstr ""
 
-#: aleksis/core/models.py:836
+#: aleksis/core/models.py:853
 msgid "Dashboard Widget"
 msgstr ""
 
-#: aleksis/core/models.py:837
+#: aleksis/core/models.py:854
 msgid "Dashboard Widgets"
 msgstr ""
 
-#: aleksis/core/models.py:843
+#: aleksis/core/models.py:860
 msgid "URL"
 msgstr ""
 
-#: aleksis/core/models.py:844
+#: aleksis/core/models.py:861
 msgid "Icon URL"
 msgstr ""
 
-#: aleksis/core/models.py:850
+#: aleksis/core/models.py:867
 msgid "External link widget"
 msgstr ""
 
-#: aleksis/core/models.py:851
+#: aleksis/core/models.py:868
 msgid "External link widgets"
 msgstr ""
 
-#: aleksis/core/models.py:856
+#: aleksis/core/models.py:873
 msgid "Dashboard widget"
 msgstr ""
 
-#: aleksis/core/models.py:861
+#: aleksis/core/models.py:878
 msgid "Order"
 msgstr ""
 
-#: aleksis/core/models.py:862
+#: aleksis/core/models.py:879
 msgid "Part of the default dashboard"
 msgstr ""
 
-#: aleksis/core/models.py:877
+#: aleksis/core/models.py:894
 msgid "Dashboard widget order"
 msgstr ""
 
-#: aleksis/core/models.py:878
+#: aleksis/core/models.py:895
 msgid "Dashboard widget orders"
 msgstr ""
 
-#: aleksis/core/models.py:884
+#: aleksis/core/models.py:901
 msgid "Menu ID"
 msgstr ""
 
-#: aleksis/core/models.py:897
+#: aleksis/core/models.py:914
 msgid "Custom menu"
 msgstr ""
 
-#: aleksis/core/models.py:898
+#: aleksis/core/models.py:915
 msgid "Custom menus"
 msgstr ""
 
-#: aleksis/core/models.py:908
+#: aleksis/core/models.py:925
 msgid "Menu"
 msgstr ""
 
-#: aleksis/core/models.py:912
+#: aleksis/core/models.py:929
 msgid "Icon"
 msgstr ""
 
-#: aleksis/core/models.py:918
+#: aleksis/core/models.py:935
 msgid "Custom menu item"
 msgstr ""
 
-#: aleksis/core/models.py:919
+#: aleksis/core/models.py:936
 msgid "Custom menu items"
 msgstr ""
 
-#: aleksis/core/models.py:933
+#: aleksis/core/models.py:950
 msgid "Title of type"
 msgstr ""
 
-#: aleksis/core/models.py:940 aleksis/core/templates/core/group/full.html:47
+#: aleksis/core/models.py:957 aleksis/core/templates/core/group/full.html:47
 msgid "Group type"
 msgstr ""
 
-#: aleksis/core/models.py:954
+#: aleksis/core/models.py:971
 msgid "Can view system status"
 msgstr ""
 
-#: aleksis/core/models.py:955
-msgid "Can link persons to accounts"
-msgstr ""
-
-#: aleksis/core/models.py:956
+#: aleksis/core/models.py:972
 msgid "Can manage data"
 msgstr ""
 
-#: aleksis/core/models.py:957
+#: aleksis/core/models.py:973
 msgid "Can impersonate"
 msgstr ""
 
-#: aleksis/core/models.py:958
+#: aleksis/core/models.py:974
 msgid "Can use search"
 msgstr ""
 
-#: aleksis/core/models.py:959
+#: aleksis/core/models.py:975
 msgid "Can change site preferences"
 msgstr ""
 
-#: aleksis/core/models.py:960
+#: aleksis/core/models.py:976
 msgid "Can change person preferences"
 msgstr ""
 
-#: aleksis/core/models.py:961
+#: aleksis/core/models.py:977
 msgid "Can change group preferences"
 msgstr ""
 
-#: aleksis/core/models.py:962
+#: aleksis/core/models.py:978
 msgid "Can add oauth applications"
 msgstr ""
 
-#: aleksis/core/models.py:963
+#: aleksis/core/models.py:979
 msgid "Can list oauth applications"
 msgstr ""
 
-#: aleksis/core/models.py:964
+#: aleksis/core/models.py:980
 msgid "Can view oauth applications"
 msgstr ""
 
-#: aleksis/core/models.py:965
+#: aleksis/core/models.py:981
 msgid "Can update oauth applications"
 msgstr ""
 
-#: aleksis/core/models.py:966
+#: aleksis/core/models.py:982
 msgid "Can delete oauth applications"
 msgstr ""
 
-#: aleksis/core/models.py:967
+#: aleksis/core/models.py:983
 msgid "Can test PDF generation"
 msgstr ""
 
-#: aleksis/core/models.py:1003
+#: aleksis/core/models.py:1019
 msgid "Related data check task"
 msgstr ""
 
-#: aleksis/core/models.py:1011
+#: aleksis/core/models.py:1027
 msgid "Issue solved"
 msgstr ""
 
-#: aleksis/core/models.py:1012
+#: aleksis/core/models.py:1028
 msgid "Notification sent"
 msgstr ""
 
-#: aleksis/core/models.py:1025
+#: aleksis/core/models.py:1041
 msgid "Data check result"
 msgstr ""
 
-#: aleksis/core/models.py:1026
+#: aleksis/core/models.py:1042
 msgid "Data check results"
 msgstr ""
 
-#: aleksis/core/models.py:1028
+#: aleksis/core/models.py:1044
 msgid "Can run data checks"
 msgstr ""
 
-#: aleksis/core/models.py:1029
+#: aleksis/core/models.py:1045
 msgid "Can solve data check problems"
 msgstr ""
 
-#: aleksis/core/models.py:1044
+#: aleksis/core/models.py:1060
 msgid "Owner"
 msgstr ""
 
-#: aleksis/core/models.py:1048
+#: aleksis/core/models.py:1064
 msgid "File expires at"
 msgstr ""
 
-#: aleksis/core/models.py:1050
+#: aleksis/core/models.py:1066
 msgid "Generated HTML file"
 msgstr ""
 
-#: aleksis/core/models.py:1052
+#: aleksis/core/models.py:1068
 msgid "Generated PDF file"
 msgstr ""
 
-#: aleksis/core/models.py:1059
+#: aleksis/core/models.py:1075
 msgid "PDF file"
 msgstr ""
 
-#: aleksis/core/models.py:1060
+#: aleksis/core/models.py:1076
 msgid "PDF files"
 msgstr ""
 
-#: aleksis/core/models.py:1065
+#: aleksis/core/models.py:1081
 msgid "Task result"
 msgstr ""
 
-#: aleksis/core/models.py:1068
+#: aleksis/core/models.py:1084
 msgid "Task user"
 msgstr ""
 
-#: aleksis/core/models.py:1080
+#: aleksis/core/models.py:1096
 msgid "Task user assignment"
 msgstr ""
 
-#: aleksis/core/models.py:1081
+#: aleksis/core/models.py:1097
 msgid "Task user assignments"
 msgstr ""
 
@@ -1027,75 +1018,71 @@ msgstr ""
 msgid "Official name of the school, e.g. as given by supervisory authority"
 msgstr ""
 
-#: aleksis/core/preferences.py:256
-msgid "Enabled custom authentication backends"
-msgstr ""
-
-#: aleksis/core/preferences.py:268
+#: aleksis/core/preferences.py:254
 msgid "Allow users to change their passwords"
 msgstr ""
 
-#: aleksis/core/preferences.py:276
+#: aleksis/core/preferences.py:262
 msgid "Enable signup"
 msgstr ""
 
-#: aleksis/core/preferences.py:287
+#: aleksis/core/preferences.py:273
 msgid "Available languages"
 msgstr ""
 
-#: aleksis/core/preferences.py:299
+#: aleksis/core/preferences.py:285
 msgid "Send emails if data checks detect problems"
 msgstr ""
 
-#: aleksis/core/preferences.py:310
+#: aleksis/core/preferences.py:296
 msgid "Email recipients for data checks problem emails"
 msgstr ""
 
-#: aleksis/core/preferences.py:321
+#: aleksis/core/preferences.py:307
 msgid "Email recipient groups for data checks problem emails"
 msgstr ""
 
-#: aleksis/core/preferences.py:330
+#: aleksis/core/preferences.py:316
 msgid "Show dashboard to users without login"
 msgstr ""
 
-#: aleksis/core/preferences.py:339
+#: aleksis/core/preferences.py:325
 msgid "Allow users to edit their dashboard"
 msgstr ""
 
-#: aleksis/core/preferences.py:350
+#: aleksis/core/preferences.py:336
 msgid "Fields on person model which are editable by themselves."
 msgstr ""
 
-#: aleksis/core/preferences.py:364
+#: aleksis/core/preferences.py:350
 msgid "Editable fields on person model which should trigger a notification on change"
 msgstr ""
 
-#: aleksis/core/preferences.py:377
+#: aleksis/core/preferences.py:363
 msgid "Contact for notification if a person changes their data"
 msgstr ""
 
-#: aleksis/core/preferences.py:387
+#: aleksis/core/preferences.py:373
 msgid "PDF file expiration duration"
 msgstr ""
 
-#: aleksis/core/preferences.py:388
+#: aleksis/core/preferences.py:374
 msgid "in minutes"
 msgstr ""
 
-#: aleksis/core/preferences.py:398
+#: aleksis/core/preferences.py:384
 msgid "Automatically update the dashboard and its widgets"
 msgstr ""
 
-#: aleksis/core/preferences.py:408
+#: aleksis/core/preferences.py:394
 msgid "Automatically update the dashboard and its widgets sitewide"
 msgstr ""
 
-#: aleksis/core/settings.py:468
+#: aleksis/core/settings.py:452
 msgid "English"
 msgstr ""
 
-#: aleksis/core/settings.py:469
+#: aleksis/core/settings.py:453
 msgid "German"
 msgstr ""
 
@@ -1259,7 +1246,7 @@ msgstr ""
 #: aleksis/core/templates/account/password_reset_done.html:5
 #: aleksis/core/templates/account/verification_email_required.html:5
 #: aleksis/core/templates/account/verification_email_required.html:6
-#: aleksis/core/templates/two_factor/core/login.html:100
+#: aleksis/core/templates/two_factor/core/login.html:81
 msgid "Reset password"
 msgstr ""
 
@@ -1996,32 +1983,10 @@ msgid ""
 "          "
 msgstr ""
 
-#: aleksis/core/templates/core/person/accounts.html:12
-#: aleksis/core/templates/core/person/accounts.html:14
-msgid "Link persons to accounts"
-msgstr ""
-
-#: aleksis/core/templates/core/person/accounts.html:21
-msgid ""
-"\n"
-"        You can use this form to assign user accounts to persons. Use the\n"
-"        dropdowns to select existing accounts; use the text fields to create new\n"
-"        accounts on-the-fly. The latter will create a new account with the\n"
-"        entered username and copy all other details from the person.\n"
-"      "
-msgstr ""
-
-#: aleksis/core/templates/core/person/accounts.html:36
-#: aleksis/core/templates/core/person/accounts.html:60
-msgid "Update"
-msgstr ""
-
-#: aleksis/core/templates/core/person/accounts.html:42
-msgid "Existing account"
-msgstr ""
-
-#: aleksis/core/templates/core/person/accounts.html:43
-msgid "New account"
+#: aleksis/core/templates/core/person/create.html:12
+#: aleksis/core/templates/core/person/create.html:13
+#: aleksis/core/templates/core/person/list.html:17
+msgid "Create person"
 msgstr ""
 
 #: aleksis/core/templates/core/person/edit.html:12
@@ -2030,6 +1995,8 @@ msgid "Edit person"
 msgstr ""
 
 #: aleksis/core/templates/core/person/full.html:44
+#: aleksis/core/templates/impersonate/list_users.html:7
+#: aleksis/core/templates/impersonate/list_users.html:8
 msgid "Impersonate"
 msgstr ""
 
@@ -2041,10 +2008,6 @@ msgstr ""
 msgid "Children"
 msgstr ""
 
-#: aleksis/core/templates/core/person/list.html:17
-msgid "Create person"
-msgstr ""
-
 #: aleksis/core/templates/core/person/list.html:21
 msgid "Filter persons"
 msgstr ""
@@ -2081,10 +2044,6 @@ msgstr ""
 msgid "Save preferences"
 msgstr ""
 
-#: aleksis/core/templates/impersonate/list_users.html:8
-msgid "Impersonate user"
-msgstr ""
-
 #: aleksis/core/templates/oauth2_provider/application_confirm_delete.html:5
 #: aleksis/core/templates/oauth2_provider/application_confirm_delete.html:6
 msgid "Delete application"
@@ -2437,64 +2396,70 @@ msgstr ""
 msgid "Generate Tokens"
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:18
+#: aleksis/core/templates/two_factor/core/login.html:20
 msgid "Login with username and password"
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:26
-msgid "You have no permission to view this page. Please login with an other account."
+#: aleksis/core/templates/two_factor/core/login.html:28
+msgid ""
+"You have no permission to view this page. Please login with an other\n"
+"                    account."
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:33
+#: aleksis/core/templates/two_factor/core/login.html:36
 msgid "Please login to see this page."
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:43
+#: aleksis/core/templates/two_factor/core/login.html:46
 msgid ""
 "\n"
-"                      We are calling your phone right now, please enter the\n"
-"                      digits you hear.\n"
-"                    "
+"                        We are calling your phone right now, please enter the\n"
+"                        digits you hear.\n"
+"                      "
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:48
+#: aleksis/core/templates/two_factor/core/login.html:51
 msgid ""
 "\n"
-"                      We sent you a text message, please enter the tokens we\n"
-"                      sent.\n"
-"                    "
+"                        We sent you a text message, please enter the tokens we\n"
+"                        sent.\n"
+"                      "
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:53
+#: aleksis/core/templates/two_factor/core/login.html:56
 msgid ""
 "\n"
-"                      Please enter the tokens generated by your token\n"
-"                      generator.\n"
-"                    "
+"                        Please enter the tokens generated by your token\n"
+"                        generator.\n"
+"                      "
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:59
+#: aleksis/core/templates/two_factor/core/login.html:62
 msgid ""
 "\n"
-"                    Use this form for entering backup tokens for logging in.\n"
-"                    These tokens have been generated for you to print and keep safe. Please\n"
-"                    enter one of these backup tokens to login to your account.\n"
-"                  "
+"                      Use this form for entering backup tokens for logging in.\n"
+"                      These tokens have been generated for you to print and keep safe. Please\n"
+"                      enter one of these backup tokens to login to your account.\n"
+"                    "
+msgstr ""
+
+#: aleksis/core/templates/two_factor/core/login.html:90
+msgid "Device currently not available?"
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:74
+#: aleksis/core/templates/two_factor/core/login.html:92
 msgid "Or, alternatively, use one of your backup phones:"
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:84
+#: aleksis/core/templates/two_factor/core/login.html:102
 msgid "As a last resort, you can use a backup token:"
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:87
+#: aleksis/core/templates/two_factor/core/login.html:105
 msgid "Use Backup Token"
 msgstr ""
 
-#: aleksis/core/templates/two_factor/core/login.html:110
+#: aleksis/core/templates/two_factor/core/login.html:116
 msgid "Use alternative login options"
 msgstr ""
 
@@ -2759,107 +2724,107 @@ msgstr ""
 msgid "Download PDF"
 msgstr ""
 
-#: aleksis/core/views.py:253
+#: aleksis/core/views.py:251
 msgid "The school term has been created."
 msgstr ""
 
-#: aleksis/core/views.py:265
+#: aleksis/core/views.py:263
 msgid "The school term has been saved."
 msgstr ""
 
-#: aleksis/core/views.py:410
+#: aleksis/core/views.py:387
 msgid "The child groups were successfully saved."
 msgstr ""
 
-#: aleksis/core/views.py:471
+#: aleksis/core/views.py:406 aleksis/core/views.py:416
 msgid "The person has been saved."
 msgstr ""
 
-#: aleksis/core/views.py:510
+#: aleksis/core/views.py:466
 msgid "The group has been saved."
 msgstr ""
 
-#: aleksis/core/views.py:607
+#: aleksis/core/views.py:563
 msgid "The announcement has been saved."
 msgstr ""
 
-#: aleksis/core/views.py:623
+#: aleksis/core/views.py:579
 msgid "The announcement has been deleted."
 msgstr ""
 
-#: aleksis/core/views.py:707
+#: aleksis/core/views.py:663
 msgid "The preferences have been saved successfully."
 msgstr ""
 
-#: aleksis/core/views.py:731
+#: aleksis/core/views.py:687
 msgid "The person has been deleted."
 msgstr ""
 
-#: aleksis/core/views.py:745
+#: aleksis/core/views.py:701
 msgid "The group has been deleted."
 msgstr ""
 
-#: aleksis/core/views.py:777
+#: aleksis/core/views.py:733
 msgid "The additional_field has been saved."
 msgstr ""
 
-#: aleksis/core/views.py:811
+#: aleksis/core/views.py:767
 msgid "The additional field has been deleted."
 msgstr ""
 
-#: aleksis/core/views.py:836
+#: aleksis/core/views.py:792
 msgid "The group type has been saved."
 msgstr ""
 
-#: aleksis/core/views.py:866
+#: aleksis/core/views.py:822
 msgid "The group type has been deleted."
 msgstr ""
 
-#: aleksis/core/views.py:899
+#: aleksis/core/views.py:855
 msgid "Progress: Run data checks"
 msgstr ""
 
-#: aleksis/core/views.py:900
+#: aleksis/core/views.py:856
 msgid "Run data checks …"
 msgstr ""
 
-#: aleksis/core/views.py:901
+#: aleksis/core/views.py:857
 msgid "The data checks were run successfully."
 msgstr ""
 
-#: aleksis/core/views.py:902
+#: aleksis/core/views.py:858
 msgid "There was a problem while running data checks."
 msgstr ""
 
-#: aleksis/core/views.py:918
+#: aleksis/core/views.py:874
 #, python-brace-format
 msgid "The solve option '{solve_option_obj.verbose_name}' "
 msgstr ""
 
-#: aleksis/core/views.py:960
+#: aleksis/core/views.py:916
 msgid "The dashboard widget has been saved."
 msgstr ""
 
-#: aleksis/core/views.py:990
+#: aleksis/core/views.py:946
 msgid "The dashboard widget has been created."
 msgstr ""
 
-#: aleksis/core/views.py:1000
+#: aleksis/core/views.py:956
 msgid "The dashboard widget has been deleted."
 msgstr ""
 
-#: aleksis/core/views.py:1067
+#: aleksis/core/views.py:1023
 msgid "Your dashboard configuration has been saved successfully."
 msgstr ""
 
-#: aleksis/core/views.py:1069
+#: aleksis/core/views.py:1025
 msgid "The configuration of the default dashboard has been saved successfully."
 msgstr ""
 
-#: aleksis/core/views.py:1197
+#: aleksis/core/views.py:1153
 msgid "The third-party account could not be disconnected because it is the only login method available."
 msgstr ""
 
-#: aleksis/core/views.py:1204
+#: aleksis/core/views.py:1160
 msgid "The third-party account has been successfully disconnected."
 msgstr ""
diff --git a/aleksis/core/locale/tr_TR/LC_MESSAGES/djangojs.po b/aleksis/core/locale/tr_TR/LC_MESSAGES/djangojs.po
index e10a495775fcb643cbe11cc1ce0daf4c5fc649ef..dc6d028e5442a3666f35a7cb46e39e5c01cdd3f9 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: 2021-08-28 17:53+0200\n"
+"POT-Creation-Date: 2021-10-28 16:18+0200\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"
diff --git a/aleksis/core/managers.py b/aleksis/core/managers.py
index ade623230aff2b8663e976ae4c133c3e24b979b4..aed4cab72d4b0cd53d3544b20f0180a7087dfd2c 100644
--- a/aleksis/core/managers.py
+++ b/aleksis/core/managers.py
@@ -120,3 +120,7 @@ class InstalledWidgetsDashboardWidgetOrderManager(Manager):
 
         # [obj["id"] for obj in list(Person.objects.all().values("id"))]
         return super().get_queryset().filter(widget_id__in=dashboard_widget_pks)
+
+
+class PolymorphicCurrentSiteManager(_CurrentSiteManager, PolymorphicManager):
+    """Default manager for extensible, polymorphic models."""
diff --git a/aleksis/core/menus.py b/aleksis/core/menus.py
index b368a6c702e4b2514afc903fb5ff48417ef22bfa..d9fd84b0f78a1ce141537725d233f57b43a4fbea 100644
--- a/aleksis/core/menus.py
+++ b/aleksis/core/menus.py
@@ -267,17 +267,6 @@ MENUS = {
                         )
                     ],
                 },
-                {
-                    "name": _("Persons and accounts"),
-                    "url": "persons_accounts",
-                    "icon": "person_add",
-                    "validators": [
-                        (
-                            "aleksis.core.util.predicates.permission_validator",
-                            "core.link_persons_accounts_rule",
-                        )
-                    ],
-                },
                 {
                     "name": _("Groups and child groups"),
                     "url": "groups_child_groups",
diff --git a/aleksis/core/migrations/0021_drop_persons_accounts_perm.py b/aleksis/core/migrations/0021_drop_persons_accounts_perm.py
new file mode 100644
index 0000000000000000000000000000000000000000..576efcec16e706a27059d80d9c256052c0e74dab
--- /dev/null
+++ b/aleksis/core/migrations/0021_drop_persons_accounts_perm.py
@@ -0,0 +1,17 @@
+# Generated by Django 3.2.8 on 2021-10-24 13:43
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('core', '0020_pdf_file_person_optional'),
+    ]
+
+    operations = [
+        migrations.AlterModelOptions(
+            name='globalpermissions',
+            options={'default_permissions': (), 'managed': False, 'permissions': (('view_system_status', 'Can view system status'), ('manage_data', 'Can manage data'), ('impersonate', 'Can impersonate'), ('search', 'Can use search'), ('change_site_preferences', 'Can change site preferences'), ('change_person_preferences', 'Can change person preferences'), ('change_group_preferences', 'Can change group preferences'), ('add_oauth_applications', 'Can add oauth applications'), ('list_oauth_applications', 'Can list oauth applications'), ('view_oauth_applications', 'Can view oauth applications'), ('update_oauth_applications', 'Can update oauth applications'), ('delete_oauth_applications', 'Can delete oauth applications'), ('test_pdf', 'Can test PDF generation'))},
+        ),
+    ]
diff --git a/aleksis/core/migrations/0022_public_favicon.py b/aleksis/core/migrations/0022_public_favicon.py
new file mode 100644
index 0000000000000000000000000000000000000000..13864fdaebfb1811ac7629ed891c745595afc5bc
--- /dev/null
+++ b/aleksis/core/migrations/0022_public_favicon.py
@@ -0,0 +1,28 @@
+# Generated by Django 3.2.4 on 2021-07-24 13:14
+import os
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('core', '0021_drop_persons_accounts_perm'),
+        ('favicon', '0004_faviconimg_favicon_size_rel_unique'),
+    ]
+
+    def _migrate_favicons(apps, schema_editor):
+        FaviconImg = apps.get_model('favicon', "FaviconImg")
+        for favicon_img in FaviconImg.objects.all():
+            old_name = favicon_img.faviconImage.name
+            new_name = os.path.join("public", old_name)
+            storage = favicon_img.faviconImage.storage
+            if storage.exists(old_name):
+                storage.save(new_name, favicon_img.faviconImage.file)
+                favicon_img.faviconImage.name = new_name
+                favicon_img.save()
+
+    operations = [
+        migrations.RunPython(_migrate_favicons)
+    ]
diff --git a/aleksis/core/mixins.py b/aleksis/core/mixins.py
index fa6c4fa29a67ec2904e42dba173ce72575c0e6ba..1e4fd42168f66d4ca986dca670f277ead0cbf3e7 100644
--- a/aleksis/core/mixins.py
+++ b/aleksis/core/mixins.py
@@ -24,9 +24,16 @@ from guardian.admin import GuardedModelAdmin
 from guardian.core import ObjectPermissionChecker
 from jsonstore.fields import IntegerField, JSONFieldMixin
 from material.base import Layout, LayoutNode
+from polymorphic.base import PolymorphicModelBase
+from polymorphic.managers import PolymorphicManager
+from polymorphic.models import PolymorphicModel
 from rules.contrib.admin import ObjectPermissionsModelAdmin
 
-from aleksis.core.managers import CurrentSiteManagerWithoutMigrations, SchoolTermRelatedQuerySet
+from aleksis.core.managers import (
+    CurrentSiteManagerWithoutMigrations,
+    PolymorphicCurrentSiteManager,
+    SchoolTermRelatedQuerySet,
+)
 
 
 class _ExtensibleModelBase(models.base.ModelBase):
@@ -351,6 +358,22 @@ class ExtensibleModel(models.Model, metaclass=_ExtensibleModelBase):
         abstract = True
 
 
+class _ExtensiblePolymorphicModelBase(_ExtensibleModelBase, PolymorphicModelBase):
+    """Base class for extensible, polymorphic models."""
+
+
+class ExtensiblePolymorphicModel(
+    ExtensibleModel, PolymorphicModel, metaclass=_ExtensiblePolymorphicModelBase
+):
+    """Model class for extensible, polymorphic models."""
+
+    objects = PolymorphicCurrentSiteManager()
+    objects_all_sites = PolymorphicManager()
+
+    class Meta:
+        abstract = True
+
+
 class PureDjangoModel(object):
     """No-op mixin to mark a model as deliberately not using ExtensibleModel."""
 
diff --git a/aleksis/core/models.py b/aleksis/core/models.py
index 8fffbe122638eebee19e199914ce0b7edbc91837..1264b645ef56da31c215f3b42b0e59162935b6a0 100644
--- a/aleksis/core/models.py
+++ b/aleksis/core/models.py
@@ -32,6 +32,7 @@ from model_utils import FieldTracker
 from model_utils.models import TimeStampedModel
 from phonenumber_field.modelfields import PhoneNumberField
 from polymorphic.models import PolymorphicModel
+from templated_email import send_templated_mail
 
 from aleksis.core.data_checks import BrokenDashboardWidgetDataCheck, DataCheck, DataCheckRegistry
 
@@ -329,6 +330,22 @@ class Person(ExtensibleModel):
             if force or not self.primary_group:
                 self.primary_group = self.member_of.filter(**{f"{field}__regex": pattern}).first()
 
+    def notify_about_changed_data(
+        self, changed_fields: Iterable[str], recipients: Optional[List[str]] = None
+    ):
+        """Notify (configured) recipients about changed data of this person."""
+        context = {"person": self, "changed_fields": changed_fields}
+        recipients = recipients or [
+            get_site_preferences()["account__person_change_notification_contact"]
+        ]
+        send_templated_mail(
+            template_name="person_changed",
+            from_email=self.mail_sender_via,
+            headers={"Reply-To": self.mail_sender, "Sender": self.mail_sender,},
+            recipient_list=recipients,
+            context=context,
+        )
+
 
 class DummyPerson(Person):
     """A dummy person that is not stored into the database.
@@ -952,7 +969,6 @@ class GlobalPermissions(GlobalPermissionModel):
     class Meta(GlobalPermissionModel.Meta):
         permissions = (
             ("view_system_status", _("Can view system status")),
-            ("link_persons_accounts", _("Can link persons to accounts")),
             ("manage_data", _("Can manage data")),
             ("impersonate", _("Can impersonate")),
             ("search", _("Can use search")),
diff --git a/aleksis/core/rules.py b/aleksis/core/rules.py
index 9b8f7cc1f3c9aafcbb91a5ed06685d33e15db7d5..e8e5443e15396554befa1f14c2536c66231c76cf 100644
--- a/aleksis/core/rules.py
+++ b/aleksis/core/rules.py
@@ -2,7 +2,6 @@ import rules
 
 from .models import AdditionalField, Announcement, Group, GroupType, Person
 from .util.predicates import (
-    contains_site_preference_value,
     has_any_object,
     has_global_perm,
     has_object_perm,
@@ -80,10 +79,6 @@ delete_person_predicate = has_person & (
 )
 rules.add_perm("core.delete_person_rule", delete_person_predicate)
 
-# Link persons with accounts
-link_persons_accounts_predicate = has_person & has_global_perm("core.link_persons_accounts")
-rules.add_perm("core.link_persons_accounts_rule", link_persons_accounts_predicate)
-
 # View groups
 view_groups_predicate = has_person & (
     has_global_perm("core.view_group") | has_any_object("core.view_group", Group)
@@ -158,12 +153,7 @@ rules.add_perm("core.view_system_status_rule", view_system_status_predicate)
 rules.add_perm(
     "core.view_people_menu_rule",
     has_person
-    & (
-        view_persons_predicate
-        | view_groups_predicate
-        | link_persons_accounts_predicate
-        | assign_child_groups_to_groups_predicate
-    ),
+    & (view_persons_predicate | view_groups_predicate | assign_child_groups_to_groups_predicate),
 )
 
 # View person personal details
@@ -350,15 +340,3 @@ rules.add_perm("core.upload_files_ckeditor_rule", upload_files_ckeditor_predicat
 
 test_pdf_generation_predicate = has_person & has_global_perm("core.test_pdf")
 rules.add_perm("core.test_pdf_rule", test_pdf_generation_predicate)
-
-# Generate rules for syncable fields
-for field in Person._meta.fields:
-    perm = (
-        has_global_perm("core.edit_person")
-        | has_object_perm("core.edit_person")
-        | (
-            is_current_person
-            & contains_site_preference_value("account", "editable_fields_person", field.name)
-        )
-    )
-    rules.add_perm(f"core.change_person_field_{field.name}_rule", perm)
diff --git a/aleksis/core/settings.py b/aleksis/core/settings.py
index 1e47350e6cc24416e7d80699c373237ee6cc2c5c..a53045585b13dc76f2b6b1cb1c2cfa275b1bfeda 100644
--- a/aleksis/core/settings.py
+++ b/aleksis/core/settings.py
@@ -525,9 +525,8 @@ SASS_PROCESSOR_CUSTOM_FUNCTIONS = {
     "get-preference": "aleksis.core.util.sass_helpers.get_preference",
 }
 SASS_PROCESSOR_INCLUDE_DIRS = [
-    _settings.get("materialize.sass_path", JS_ROOT + "/materialize-css/sass/"),
-    STATIC_ROOT + "/materialize-css/sass/",
-    STATIC_ROOT,
+    _settings.get("materialize.sass_path", os.path.join(JS_ROOT, "materialize-css", "sass")),
+    os.path.join(STATIC_ROOT, "public"),
 ]
 
 ADMINS = _settings.get("contact.admins", [AUTH_INITIAL_SUPERUSER["email"]])
@@ -638,6 +637,7 @@ PWA_ICONS_CONFIG = {
     "apple_splash": [192],
     "microsoft": [144],
 }
+FAVICON_PATH = os.path.join("public", "favicon")
 
 SERVICE_WORKER_PATH = os.path.join(STATIC_ROOT, "js", "serviceworker.js")
 
diff --git a/aleksis/core/static/materialize.scss b/aleksis/core/static/public/materialize-custom.scss
similarity index 100%
rename from aleksis/core/static/materialize.scss
rename to aleksis/core/static/public/materialize-custom.scss
diff --git a/aleksis/core/static/style.scss b/aleksis/core/static/public/style.scss
similarity index 99%
rename from aleksis/core/static/style.scss
rename to aleksis/core/static/public/style.scss
index 38ea2751beef343326090c1cf9bd58735b9e0b68..c2aa516e8cfcf88190aa13f43cc8f6aad5d747de 100644
--- a/aleksis/core/static/style.scss
+++ b/aleksis/core/static/public/style.scss
@@ -1,4 +1,4 @@
-@import "materialize";
+@import "materialize-custom";
 
 .primary-color {
   background-color: $primary-color !important;
diff --git a/aleksis/core/static/theme.scss b/aleksis/core/static/public/theme.scss
similarity index 100%
rename from aleksis/core/static/theme.scss
rename to aleksis/core/static/public/theme.scss
diff --git a/aleksis/core/templates/core/base.html b/aleksis/core/templates/core/base.html
index 65e16804897cdabfff3d992cc48bcef3dcc5102d..0dd75f2c6f237dea1ecac47b010abfac9453000f 100644
--- a/aleksis/core/templates/core/base.html
+++ b/aleksis/core/templates/core/base.html
@@ -24,7 +24,7 @@
   {% include_css "Roboto500" %}
   {% include_css "Roboto700" %}
   {% include_css "Roboto900" %}
-  <link rel="stylesheet" href="{% sass_src 'style.scss' %}">
+  <link rel="stylesheet" href="{% sass_src 'public/style.scss' %}">
 
   {# Add JS URL resolver #}
   <script src="{% url "js_reverse" %}" type="text/javascript"></script>
diff --git a/aleksis/core/templates/core/base_print.html b/aleksis/core/templates/core/base_print.html
index 7691cdf804b043b373e6a4f26802fc9cdb732205..428d28f2858406c771b635c20ff874bf5c9f9d5a 100644
--- a/aleksis/core/templates/core/base_print.html
+++ b/aleksis/core/templates/core/base_print.html
@@ -22,7 +22,7 @@
   {% include_css "Roboto700" %}
   {% include_css "Roboto900" %}
   {% include_css "paper-css" %}
-  <link rel="stylesheet" href="{% sass_src 'style.scss' %}"/>
+  <link rel="stylesheet" href="{% sass_src 'public/style.scss' %}"/>
   <link rel="stylesheet" href="{% static "print.css" %}"/>
   {% if landscape %}
     <link rel="stylesheet" href="{% static 'print_landscape.css' %}"/>
diff --git a/aleksis/core/templates/core/person/accounts.html b/aleksis/core/templates/core/person/accounts.html
deleted file mode 100644
index 03725518dfcbf8552a53199790daa44d541bac32..0000000000000000000000000000000000000000
--- a/aleksis/core/templates/core/person/accounts.html
+++ /dev/null
@@ -1,65 +0,0 @@
-{# -*- engine:django -*- #}
-
-{% extends "core/base.html" %}
-
-{% load i18n any_js %}
-
-{% block extra_head %}
-  {{ persons_accounts_formset.media.css }}
-  {% include_css "select2-materialize" %}
-{% endblock %}
-
-{% block browser_title %}{% blocktrans %}Link persons to accounts{% endblocktrans %}{% endblock %}
-{% block page_title %}
-  {% blocktrans %}Link persons to accounts{% endblocktrans %}
-{% endblock %}
-
-{% block content %}
-  <div class="alert info">
-    <p>
-      <i class="material-icons left">info</i>
-      {% blocktrans %}
-        You can use this form to assign user accounts to persons. Use the
-        dropdowns to select existing accounts; use the text fields to create new
-        accounts on-the-fly. The latter will create a new account with the
-        entered username and copy all other details from the person.
-      {% endblocktrans %}
-    </p>
-  </div>
-
-  <form method="post">
-    {% csrf_token %}
-    {{ persons_accounts_formset.management_form }}
-
-    <button type="submit" class="btn green waves-effect waves-light">
-      <i class="material-icons left">save</i>
-      {% blocktrans %}Update{% endblocktrans %}
-    </button>
-
-    <table>
-      <tr>
-        <th>{% blocktrans %}Person{% endblocktrans %}</th>
-        <th>{% blocktrans %}Existing account{% endblocktrans %}</th>
-        <th>{% blocktrans %}New account{% endblocktrans %}</th>
-      </tr>
-      {% for form in persons_accounts_formset %}
-        {{ form.id }}
-        <tr>
-          <td>
-            {{ form.last_name }}
-            {{ form.first_name }}
-          </td>
-          <td>{{ form.user }}</td>
-          <td>{{ form.new_user }}</td>
-        </tr>
-      {% endfor %}
-    </table>
-
-    <button type="submit" class="btn green waves-effect waves-light">
-      <i class="material-icons left">save</i>
-      {% blocktrans %}Update{% endblocktrans %}
-    </button>
-  </form>
-  {% include_js "select2-materialize" %}
-  {{ persons_accounts_formset.media.js }}
-{% endblock %}
diff --git a/aleksis/core/templates/core/person/create.html b/aleksis/core/templates/core/person/create.html
new file mode 100644
index 0000000000000000000000000000000000000000..08a6639e05e45f82912fd3e4adb25021264010c9
--- /dev/null
+++ b/aleksis/core/templates/core/person/create.html
@@ -0,0 +1,24 @@
+{# -*- engine:django -*- #}
+
+{% extends "core/base.html" %}
+
+{% load material_form i18n any_js %}
+
+{% block extra_head %}
+  {{ form.media.css }}
+  {% include_css "select2-materialize" %}
+{% endblock %}
+
+{% block browser_title %}{% blocktrans %}Create person{% endblocktrans %}{% endblock %}
+{% block page_title %}{% blocktrans %}Create person{% endblocktrans %}{% endblock %}
+
+
+{% block content %}
+  <form method="post" enctype="multipart/form-data">
+    {% csrf_token %}
+    {% form form=form %}{% endform %}
+    {% include "core/partials/save_button.html" %}
+  </form>
+  {% include_js "select2-materialize" %}
+  {{ form.media.js }}
+{% endblock %}
diff --git a/aleksis/core/templates/core/person/edit.html b/aleksis/core/templates/core/person/edit.html
index 3bf16ca3521ea744acfe48c6829dfae21db06eb5..788721c3541cba056c1ef05214eb0c39eb1b6f69 100644
--- a/aleksis/core/templates/core/person/edit.html
+++ b/aleksis/core/templates/core/person/edit.html
@@ -5,7 +5,7 @@
 {% load material_form i18n any_js %}
 
 {% block extra_head %}
-  {{ edit_person_form.media }}
+  {{ form.media.css }}
   {% include_css "select2-materialize" %}
 {% endblock %}
 
@@ -14,13 +14,11 @@
 
 
 {% block content %}
-
   <form method="post" enctype="multipart/form-data">
     {% csrf_token %}
-    {% form form=edit_person_form %}{% endform %}
+    {% form form=form %}{% endform %}
     {% include "core/partials/save_button.html" %}
   </form>
   {% include_js "select2-materialize" %}
-  {{ edit_group_form.media.js }}
-
+  {{ form.media.js }}
 {% endblock %}
diff --git a/aleksis/core/templates/impersonate/list_users.html b/aleksis/core/templates/impersonate/list_users.html
index aff2f8660ac374cebb1bbeff646bc038aee9e5f1..fd273ca60902e5defbc41e567a9205cfe99fb349 100644
--- a/aleksis/core/templates/impersonate/list_users.html
+++ b/aleksis/core/templates/impersonate/list_users.html
@@ -4,9 +4,8 @@
 {% extends "core/base.html" %}
 {% load i18n %}
 
-{% block page_title %}
-  {% blocktrans %}Impersonate user{% endblocktrans %}
-{% endblock %}
+{% block browser_title %}{% trans "Impersonate" %}{% endblock %}
+{% block page_title %}{% trans "Impersonate" %}{% endblock %}
 
 {% block content %}
   {% if page.object_list %}
diff --git a/aleksis/core/templates/templated_email/person_changed.email b/aleksis/core/templates/templated_email/person_changed.email
index 2e1db653256873d3f72afcd34a1e19914d116480..1e0d8be25684486bfdceac0b979b461253c21df7 100644
--- a/aleksis/core/templates/templated_email/person_changed.email
+++ b/aleksis/core/templates/templated_email/person_changed.email
@@ -11,7 +11,7 @@
    the person {{ person }} recently changed the following fields:
  {% endblocktrans %}
 
- {% for field in send_notification_fields %}
+ {% for field in changed_fields %}
   * {{ field }}
  {% endfor %}
 {% endblock %}
@@ -25,7 +25,7 @@
  </p>
 
  <ul>
-  {% for field in send_notification_fields %}
+  {% for field in changed_fields %}
    <li>{{ field }}</li>
   {% endfor %}
  </ul>
diff --git a/aleksis/core/urls.py b/aleksis/core/urls.py
index b09c6ff9456e1b7e749301a4f261fb5e642e380c..b3c2cc468aded72fe1b9e64af88e58b4fb936192 100644
--- a/aleksis/core/urls.py
+++ b/aleksis/core/urls.py
@@ -46,12 +46,11 @@ urlpatterns = [
     path("school_terms/create/", views.SchoolTermCreateView.as_view(), name="create_school_term"),
     path("school_terms/<int:pk>/", views.SchoolTermEditView.as_view(), name="edit_school_term"),
     path("persons", views.persons, name="persons"),
-    path("persons/accounts", views.persons_accounts, name="persons_accounts"),
-    path("person", views.person, name="person"),
-    path("person/create", views.edit_person, name="create_person"),
-    path("person/<int:id_>", views.person, name="person_by_id"),
-    path("person/<int:id_>/edit", views.edit_person, name="edit_person_by_id"),
-    path("person/<int:id_>/delete", views.delete_person, name="delete_person_by_id"),
+    path("person/", views.person, name="person"),
+    path("person/create/", views.CreatePersonView.as_view(), name="create_person"),
+    path("person/<int:id_>/", views.person, name="person_by_id"),
+    path("person/<int:pk>/edit/", views.EditPersonView.as_view(), name="edit_person_by_id"),
+    path("person/<int:id_>/delete/", views.delete_person, name="delete_person_by_id"),
     path("groups", views.groups, name="groups"),
     path("groups/additional_fields", views.additional_fields, name="additional_fields"),
     path("groups/child_groups/", views.groups_child_groups, name="groups_child_groups"),
diff --git a/aleksis/core/views.py b/aleksis/core/views.py
index e24bafa1705465173a8ae9d54669ae23d880ee04..8918f3c35d9ef661ae711faecbac6fb054fdb526 100644
--- a/aleksis/core/views.py
+++ b/aleksis/core/views.py
@@ -47,7 +47,6 @@ from oauth2_provider.models import Application
 from reversion import set_user
 from reversion.views import RevisionMixin
 from rules.contrib.views import PermissionRequiredMixin, permission_required
-from templated_email import send_templated_mail
 
 from aleksis.core.data_checks import DataCheckRegistry, check_data
 
@@ -60,10 +59,9 @@ from .forms import (
     EditAdditionalFieldForm,
     EditGroupForm,
     EditGroupTypeForm,
-    EditPersonForm,
     GroupPreferenceForm,
+    PersonForm,
     PersonPreferenceForm,
-    PersonsAccountsFormSet,
     SchoolTermForm,
     SitePreferenceForm,
 )
@@ -361,27 +359,6 @@ def groups(request: HttpRequest) -> HttpResponse:
     return render(request, "core/group/list.html", context)
 
 
-@never_cache
-@permission_required("core.link_persons_accounts_rule")
-def persons_accounts(request: HttpRequest) -> HttpResponse:
-    """View allowing to batch-process linking of users to persons."""
-    context = {}
-
-    # Get all persons
-    persons_qs = Person.objects.all()
-
-    # Form set with one form per known person
-    persons_accounts_formset = PersonsAccountsFormSet(request.POST or None, queryset=persons_qs)
-
-    if request.method == "POST":
-        if persons_accounts_formset.is_valid():
-            persons_accounts_formset.save()
-
-    context["persons_accounts_formset"] = persons_accounts_formset
-
-    return render(request, "core/person/accounts.html", context)
-
-
 @never_cache
 @permission_required("core.assign_child_groups_to_groups_rule")
 def groups_child_groups(request: HttpRequest) -> HttpResponse:
@@ -420,59 +397,38 @@ def groups_child_groups(request: HttpRequest) -> HttpResponse:
     return render(request, "core/group/child_groups.html", context)
 
 
-@never_cache
-@permission_required("core.edit_person_rule", fn=objectgetter_optional(Person))
-def edit_person(request: HttpRequest, id_: Optional[int] = None) -> HttpResponse:
-    """Edit view for a single person, defaulting to logged-in person."""
-    context = {}
-
-    person = objectgetter_optional(Person)(request, id_)
-    context["person"] = person
-
-    if id_:
-        # Edit form for existing group
-        edit_person_form = EditPersonForm(
-            request, request.POST or None, request.FILES or None, instance=person
-        )
-    else:
-        # Empty form to create a new group
-        if request.user.has_perm("core.create_person_rule"):
-            edit_person_form = EditPersonForm(request, request.POST or None, request.FILES or None)
-        else:
-            raise PermissionDenied()
-    if request.method == "POST":
-        if edit_person_form.is_valid():
-            if person and person == request.user.person:
-                # Check if user edited non-editable field
-                notification_fields = get_site_preferences()[
-                    "account__notification_on_person_change"
-                ]
-                send_notification_fields = set(edit_person_form.changed_data).intersection(
-                    set(notification_fields)
-                )
-                context["send_notification_fields"] = send_notification_fields
-                if send_notification_fields:
-                    context["send_notification_fields"] = send_notification_fields
-                    send_templated_mail(
-                        template_name="person_changed",
-                        from_email=request.user.person.mail_sender_via,
-                        headers={
-                            "Reply-To": request.user.person.mail_sender,
-                            "Sender": request.user.person.mail_sender,
-                        },
-                        recipient_list=[
-                            get_site_preferences()["account__person_change_notification_contact"]
-                        ],
-                        context=context,
-                    )
-            with reversion.create_revision():
-                set_user(request.user)
-                edit_person_form.save(commit=True)
-            messages.success(request, _("The person has been saved."))
+@method_decorator(never_cache, name="dispatch")
+class CreatePersonView(PermissionRequiredMixin, AdvancedCreateView):
+    form_class = PersonForm
+    model = Person
+    permission_required = "core.create_person_rule"
+    template_name = "core/person/create.html"
+    success_message = _("The person has been saved.")
 
-    context["edit_person_form"] = edit_person_form
 
-    return render(request, "core/person/edit.html", context)
+@method_decorator(never_cache, name="dispatch")
+class EditPersonView(PermissionRequiredMixin, RevisionMixin, AdvancedEditView):
+    form_class = PersonForm
+    model = Person
+    permission_required = "core.edit_person_rule"
+    context_object_name = "person"
+    template_name = "core/person/edit.html"
+    success_message = _("The person has been saved.")
+
+    def get_form_kwargs(self):
+        kwargs = super().get_form_kwargs()
+        kwargs["request"] = self.request
+        return kwargs
+
+    def form_valid(self, form):
+        if self.object == self.request.user.person:
+            # Get all changed fields and send a notification about them
+            notification_fields = get_site_preferences()["account__notification_on_person_change"]
+            send_notification_fields = set(form.changed_data).intersection(set(notification_fields))
+
+            if send_notification_fields:
+                self.object.notify_about_changed_data(send_notification_fields)
+        return super().form_valid(form)
 
 
 def get_group_by_id(request: HttpRequest, id_: Optional[int] = None):
diff --git a/dev.sh b/dev.sh
deleted file mode 100755
index fa77b4c47f287c48d7839801223bbeddac5c88e1..0000000000000000000000000000000000000000
--- a/dev.sh
+++ /dev/null
@@ -1,177 +0,0 @@
-#!/usr/bin/env mksh
-
-remove_pip_metadata() {
-    find . -type d -name pip-wheel-metadata -print0 | xargs -0r rm -rf --
-}
-
-case "$1" in
-    "install-all")
-	set -e
-	cd "$(dirname "$0")"
-	remove_pip_metadata
-	poetry lock
-	poetry install
-	for d in apps/official/*; do
-	    remove_pip_metadata
-	    poetry run sh -c "cd $d; poetry lock; poetry install"
-	done
-	remove_pip_metadata
-	poetry run ./manage.py compilemessages
-	poetry run ./manage.py yarn install
-	poetry run ./manage.py collectstatic --no-input
-	set +e
-	exit
-	;;
-    "makemessages")
-	cd "$(dirname "$0")"
-	manage_py=$(realpath manage.py)
-	locales="-l ar -l de_DE -l fr -l nb_NO -l tr_TR -l la"
-	for d in aleksis/core apps/official/*/aleksis/apps/*; do
-		echo; echo "Entering $d."
-		poetry run sh -c "cd $d; $manage_py makemessages --no-wrap -e html,txt,py,email -i static $locales"
-		poetry run sh -c "cd $d; $manage_py makemessages --no-wrap -d djangojs $locales"
-	done
-	exit
-	;;
-    "autopep8")
-	cd "$(dirname "$0")"
-	for d in aleksis/core apps/official/*/aleksis/apps/*; do
-		echo; echo "Entering $d."
-		poetry run sh -c "cd $d; autopep8 -i -r ."
-	done
-	exit
-	;;
-    "pylama")
-	cd "$(dirname "$0")"
-	tox_ini=$(realpath tox.ini)
-	for d in aleksis/core apps/official/*/aleksis/apps/*; do
-		echo; echo "Entering $d."
-		poetry run sh -c "cd $d; pylama -a -o $tox_ini ."
-	done
-	exit
-	;;
-    "gource")
-	for d in . apps/official/*; do
-		gource --output-custom-log - "$d"
-	done | sort -n | gource --log-format custom --background-image aleksis/core/static/img/aleksis-icon.png "$@" -
-	exit
-	;;
-
-    "devstats-commits")
-	# Copyright © 2018
-	#	mirabilos <m@mirbsd.org>
-	# Copyright © 2017
-	#	mirabilos <t.glaser@tarent.de>
-	# Copyright © 2015, 2017, 2020
-	#	mirabilos <thorsten.glaser@teckids.org>
-	#
-	# Provided that these terms and disclaimer and all copyright notices
-	# are retained or reproduced in an accompanying document, permission
-	# is granted to deal in this work without restriction, including un‐
-	# limited rights to use, publicly perform, distribute, sell, modify,
-	# merge, give away, or sublicence.
-	#
-	# This work is provided “AS IS” and WITHOUT WARRANTY of any kind, to
-	# the utmost extent permitted by applicable law, neither express nor
-	# implied; without malicious intent or gross negligence. In no event
-	# may a licensor, author or contributor be held liable for indirect,
-	# direct, other damage, loss, or other issues arising in any way out
-	# of dealing in the work, even if advised of the possibility of such
-	# damage or existence of a defect, except proven that it results out
-	# of said person’s immediate fault when using the work as intended.
-
-	set -e
-	set -o pipefail
-	unset LANGUAGE
-	export LC_ALL=C.UTF-8
-	set -o utf8-mode
-
-	for d in . apps/official/*; do
-		cd "$d"
-		if [[ ! -s pyproject.toml ]]; then
-			print -ru2 "E: missing pyproject.toml in ${d@Q}"
-			print -ru2 "N: maybe you forgot the submodules?"
-			print -ru2 "N: try git submodule update --init --recursive"
-			exit 1
-		fi
-		cd "$OLDPWD"
-	done
-	for d in . apps/official/*; do
-		cd "$d"
-		git log --pretty=tformat:%aN
-		cd "$OLDPWD"
-	done | sort | uniq -c | sort -nr |&
-	maxnum=0
-	maxlen=0
-	set -A nums
-	set -A names
-	nlines=0
-	while IFS= read -pr line; do
-		line=${line##*( )}
-		num=${line%% *}
-		line=${line##+([0-9]) }
-		#print -r -- "<$num><$line>"
-		(( maxnum = num > maxnum ? num : maxnum ))
-		len=${%line}
-		if (( len == -1 )); then
-			len=${#line}
-			print -ru2 -- "W: assuming length $len for author ${line@Q}"
-		fi
-		(( maxlen = len > maxlen ? len : maxlen ))
-		nums[nlines]=$num
-		names[nlines++]=$line
-	done
-	w=$COLUMNS
-	if (( (w -= 1 + maxlen + 1) < 1 )); then
-		print -ru2 -- "E: terminal too small, need $((-w+1)) more columns"
-		exit 1
-	fi
-	if (( maxnum < 1 )); then
-		print -ru2 -- "E: no commits"
-		exit 1
-	fi
-	set +e
-	typeset -R$maxlen pname
-	mbar=██
-	nlen=0
-	num=$maxnum
-	while ((# num > 0 )); do
-		mbar+=â–ˆ
-		((# ++nlen ))
-		((# num /= 10 ))
-	done
-	typeset -R$nlen pnum
-	print '\e[0m'
-	line=-1
-	while (( ++line < nlines )); do
-		bar=
-		((# num = (nums[line] * w * 8) / maxnum ))
-		while ((# num >= 8 )); do
-			bar+=â–ˆ
-			((# num -= 8 ))
-		done
-		case $num {
-		(7) bar+=â–‰ ;;
-		(6) bar+=â–Š ;;
-		(5) bar+=â–‹ ;;
-		(4) bar+=▌ ;;
-		(3) bar+=▍ ;;
-		(2) bar+=â–Ž ;;
-		(1) bar+=▏ ;;
-		}
-		pname=${names[line]}
-		if [[ $bar = "$mbar"* ]]; then
-			pnum=${nums[line]}
-			bar=$'\e[7m '$pnum$' \e[0m'${bar#"$mbar"}
-		else
-			bar+=" ${nums[line]}"
-		fi
-		print -r -- "$pname $bar"
-	done
-	exit
-	;;
-    *)
-	print -ru2 -- "E: unknown command ${1@Q}"
-	exit 1
-	;;
-esac
diff --git a/poetry.lock b/poetry.lock
index 086c97edd4665cdcb233441168fb198d0a1ca071..5b8035e59280dcc14adefa0cb88178c007ced081 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -6,11 +6,6 @@ category = "dev"
 optional = false
 python-versions = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "aleksis-builddeps"
 version = "4"
@@ -63,11 +58,6 @@ python-versions = ">=3.6"
 [package.dependencies]
 vine = "5.0.0"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "appdirs"
 version = "1.4.4"
@@ -76,11 +66,6 @@ category = "dev"
 optional = false
 python-versions = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "appnope"
 version = "0.1.2"
@@ -89,11 +74,6 @@ category = "main"
 optional = false
 python-versions = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "asgiref"
 version = "3.4.1"
@@ -105,11 +85,6 @@ python-versions = ">=3.6"
 [package.extras]
 tests = ["pytest", "pytest-asyncio", "mypy (>=0.800)"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "asn1crypto"
 version = "1.4.0"
@@ -118,11 +93,6 @@ category = "dev"
 optional = false
 python-versions = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "atomicwrites"
 version = "1.4.0"
@@ -131,11 +101,6 @@ category = "dev"
 optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "attrs"
 version = "21.2.0"
@@ -150,11 +115,6 @@ docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"]
 tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface"]
 tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "babel"
 version = "2.9.1"
@@ -166,11 +126,6 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
 [package.dependencies]
 pytz = ">=2015.7"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "backcall"
 version = "0.2.0"
@@ -179,11 +134,6 @@ category = "main"
 optional = false
 python-versions = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "bandit"
 version = "1.7.0"
@@ -199,11 +149,6 @@ PyYAML = ">=5.3.1"
 six = ">=1.10.0"
 stevedore = ">=1.20.0"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "beautifulsoup4"
 version = "4.10.0"
@@ -219,11 +164,6 @@ soupsieve = ">1.2"
 html5lib = ["html5lib"]
 lxml = ["lxml"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "billiard"
 version = "3.6.4.0"
@@ -232,11 +172,6 @@ category = "main"
 optional = false
 python-versions = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "black"
 version = "19.10b0"
@@ -257,11 +192,6 @@ typed-ast = ">=1.4.0"
 [package.extras]
 d = ["aiohttp (>=3.3.2)", "aiohttp-cors"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "bleach"
 version = "4.1.0"
@@ -275,11 +205,6 @@ packaging = "*"
 six = ">=1.9.0"
 webencodings = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "boolean.py"
 version = "3.8"
@@ -288,35 +213,25 @@ category = "main"
 optional = false
 python-versions = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "boto3"
-version = "1.19.2"
+version = "1.19.3"
 description = "The AWS SDK for Python"
 category = "main"
 optional = true
 python-versions = ">= 3.6"
 
 [package.dependencies]
-botocore = ">=1.22.2,<1.23.0"
+botocore = ">=1.22.3,<1.23.0"
 jmespath = ">=0.7.1,<1.0.0"
 s3transfer = ">=0.5.0,<0.6.0"
 
 [package.extras]
 crt = ["botocore[crt] (>=1.21.0,<2.0a0)"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "botocore"
-version = "1.22.2"
+version = "1.22.3"
 description = "Low-level, data-driven core of boto 3."
 category = "main"
 optional = true
@@ -330,15 +245,10 @@ urllib3 = ">=1.25.4,<1.27"
 [package.extras]
 crt = ["awscrt (==0.12.5)"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "bs4"
 version = "0.0.1"
-description = "Screen-scraping library"
+description = "Dummy package for Beautiful Soup"
 category = "main"
 optional = false
 python-versions = "*"
@@ -346,11 +256,6 @@ python-versions = "*"
 [package.dependencies]
 beautifulsoup4 = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "calendarweek"
 version = "0.5.0"
@@ -362,11 +267,6 @@ python-versions = ">=3.7,<4.0"
 [package.extras]
 django = ["Django (>=2.2,<4.0)"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "celery"
 version = "5.1.2"
@@ -420,11 +320,6 @@ yaml = ["PyYAML (>=3.10)"]
 zookeeper = ["kazoo (>=1.3.1)"]
 zstd = ["zstandard"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "celery-haystack-ng"
 version = "0.20.post2"
@@ -438,11 +333,6 @@ celery = ">=4.0"
 django-appconf = ">=0.4.1"
 django-haystack = ">=2.0"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "celery-progress"
 version = "0.1.1"
@@ -456,11 +346,6 @@ rabbitmq = ["channels-rabbitmq"]
 redis = ["channels-redis"]
 websockets = ["channels"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "certifi"
 version = "2021.10.8"
@@ -469,11 +354,6 @@ category = "main"
 optional = false
 python-versions = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "cffi"
 version = "1.15.0"
@@ -485,11 +365,6 @@ python-versions = "*"
 [package.dependencies]
 pycparser = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "charset-normalizer"
 version = "2.0.7"
@@ -501,11 +376,6 @@ python-versions = ">=3.5.0"
 [package.extras]
 unicode_backport = ["unicodedata2"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "click"
 version = "7.1.2"
@@ -514,11 +384,6 @@ category = "main"
 optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "click-didyoumean"
 version = "0.3.0"
@@ -530,11 +395,6 @@ python-versions = ">=3.6.2,<4.0.0"
 [package.dependencies]
 click = ">=7"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "click-plugins"
 version = "1.1.1"
@@ -549,11 +409,6 @@ click = ">=4.0"
 [package.extras]
 dev = ["pytest (>=3.6)", "pytest-cov", "wheel", "coveralls"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "click-repl"
 version = "0.2.0"
@@ -567,11 +422,6 @@ click = "*"
 prompt-toolkit = "*"
 six = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "colorama"
 version = "0.4.4"
@@ -580,11 +430,6 @@ category = "main"
 optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "colour"
 version = "0.1.5"
@@ -596,11 +441,6 @@ python-versions = "*"
 [package.extras]
 test = ["nose"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "configobj"
 version = "5.0.6"
@@ -612,11 +452,6 @@ python-versions = "*"
 [package.dependencies]
 six = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "coverage"
 version = "6.0.2"
@@ -628,11 +463,6 @@ python-versions = ">=3.6"
 [package.extras]
 toml = ["tomli"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "cryptography"
 version = "35.0.0"
@@ -652,11 +482,6 @@ sdist = ["setuptools_rust (>=0.11.4)"]
 ssh = ["bcrypt (>=3.1.5)"]
 test = ["pytest (>=6.2.0)", "pytest-cov", "pytest-subtests", "pytest-xdist", "pretend", "iso8601", "pytz", "hypothesis (>=1.11.4,!=3.79.2)"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "curlylint"
 version = "0.12.2"
@@ -675,11 +500,6 @@ toml = ">=0.9.4"
 [package.extras]
 dev = ["black (==19.10b0)", "flake8 (==3.8.4)", "mypy (==0.812)", "pytest (==6.2.2)", "coverage (==5.4)"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "decorator"
 version = "5.1.0"
@@ -688,11 +508,6 @@ category = "main"
 optional = false
 python-versions = ">=3.5"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "defusedxml"
 version = "0.7.1"
@@ -701,11 +516,6 @@ category = "main"
 optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "deprecated"
 version = "1.2.13"
@@ -720,11 +530,6 @@ wrapt = ">=1.10,<2"
 [package.extras]
 dev = ["tox", "bump2version (<1)", "sphinx (<2)", "importlib-metadata (<3)", "importlib-resources (<4)", "configparser (<5)", "sphinxcontrib-websupport (<2)", "zipp (<2)", "PyTest (<5)", "PyTest-Cov (<2.6)", "pytest", "pytest-cov"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "dj-database-url"
 version = "0.5.0"
@@ -733,11 +538,6 @@ category = "dev"
 optional = false
 python-versions = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django"
 version = "3.2.8"
@@ -755,11 +555,6 @@ sqlparse = ">=0.2.2"
 argon2 = ["argon2-cffi (>=19.1.0)"]
 bcrypt = ["bcrypt"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-allauth"
 version = "0.45.0"
@@ -775,11 +570,6 @@ python3-openid = ">=3.0.8"
 requests = "*"
 requests-oauthlib = ">=0.3.0"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-any-js"
 version = "1.1"
@@ -791,11 +581,6 @@ python-versions = ">=3.7,<4.0"
 [package.dependencies]
 Django = ">=2.2,<4.0"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-appconf"
 version = "1.0.5"
@@ -807,11 +592,6 @@ python-versions = ">=3.6"
 [package.dependencies]
 django = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-auth-ldap"
 version = "2.4.0"
@@ -824,11 +604,6 @@ python-versions = ">=3.6"
 Django = ">=2.2"
 python-ldap = ">=3.1"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-bleach"
 version = "0.8.0"
@@ -841,11 +616,6 @@ python-versions = "*"
 bleach = ">=1.5.0"
 Django = ">=1.11"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-cachalot"
 version = "2.4.3"
@@ -857,11 +627,6 @@ python-versions = "*"
 [package.dependencies]
 Django = ">=2.2,<3.3"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-cache-memoize"
 version = "0.1.10"
@@ -873,11 +638,6 @@ python-versions = ">=3.5"
 [package.extras]
 dev = ["flake8", "tox", "twine", "therapist", "black"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-celery-beat"
 version = "2.2.1"
@@ -892,11 +652,6 @@ Django = ">=2.2,<4.0"
 django-timezone-field = ">=4.1.0,<5.0"
 python-crontab = ">=2.3.4"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-celery-email"
 version = "3.0.0"
@@ -910,11 +665,6 @@ celery = ">=4.0"
 django = ">=2.2"
 django-appconf = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-celery-results"
 version = "2.2.0"
@@ -926,11 +676,6 @@ python-versions = "*"
 [package.dependencies]
 celery = ">=5.0,<6.0"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-ckeditor"
 version = "6.1.0"
@@ -942,11 +687,6 @@ python-versions = "*"
 [package.dependencies]
 django-js-asset = ">=1.2.2"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-cleanup"
 version = "5.2.0"
@@ -955,11 +695,6 @@ category = "main"
 optional = false
 python-versions = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-colorfield"
 version = "0.4.5"
@@ -968,11 +703,6 @@ category = "main"
 optional = false
 python-versions = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-dbbackup"
 version = "3.3.0"
@@ -986,11 +716,6 @@ Django = ">=1.5"
 pytz = "*"
 six = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-debug-toolbar"
 version = "3.2.2"
@@ -1003,11 +728,6 @@ python-versions = ">=3.6"
 Django = ">=2.2"
 sqlparse = ">=0.2.0"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-dynamic-preferences"
 version = "1.11.0"
@@ -1021,11 +741,6 @@ django = ">=1.11"
 persisting-theory = ">=0.2.1"
 six = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-extensions"
 version = "3.1.3"
@@ -1037,11 +752,6 @@ python-versions = ">=3.6"
 [package.dependencies]
 Django = ">=2.2"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-favicon-plus-reloaded"
 version = "1.1.3"
@@ -1054,11 +764,6 @@ python-versions = "*"
 django = "*"
 pillow = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-filter"
 version = "2.4.0"
@@ -1070,11 +775,6 @@ python-versions = ">=3.5"
 [package.dependencies]
 Django = ">=2.2"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-formtools"
 version = "2.3"
@@ -1086,11 +786,6 @@ python-versions = ">=3.6"
 [package.dependencies]
 Django = ">=2.2"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-guardian"
 version = "2.4.0"
@@ -1102,11 +797,6 @@ python-versions = ">=3.5"
 [package.dependencies]
 Django = ">=2.2"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-haystack"
 version = "3.0"
@@ -1118,11 +808,6 @@ python-versions = "*"
 [package.dependencies]
 Django = ">=2.2"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-health-check"
 version = "3.16.4"
@@ -1134,11 +819,6 @@ python-versions = "*"
 [package.dependencies]
 django = ">=2.2"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-impersonate"
 version = "1.7.3"
@@ -1147,11 +827,6 @@ category = "main"
 optional = false
 python-versions = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-ipware"
 version = "4.0.0"
@@ -1160,11 +835,6 @@ category = "main"
 optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-js-asset"
 version = "1.2.2"
@@ -1173,11 +843,6 @@ category = "main"
 optional = false
 python-versions = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-js-reverse"
 version = "0.9.1"
@@ -1189,11 +854,6 @@ python-versions = "*"
 [package.dependencies]
 Django = ">=1.5"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-jsonstore"
 version = "0.5.0"
@@ -1206,11 +866,6 @@ python-versions = "*"
 Django = ">=1.11"
 six = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-maintenance-mode"
 version = "0.16.1"
@@ -1219,11 +874,6 @@ category = "main"
 optional = false
 python-versions = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-material"
 version = "1.9.0"
@@ -1235,11 +885,6 @@ python-versions = "*"
 [package.dependencies]
 six = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-menu-generator-ng"
 version = "1.2.3"
@@ -1248,11 +893,6 @@ category = "main"
 optional = false
 python-versions = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-model-utils"
 version = "4.2.0"
@@ -1264,11 +904,6 @@ python-versions = "*"
 [package.dependencies]
 Django = ">=2.0.1"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-oauth-toolkit"
 version = "1.5.0"
@@ -1284,11 +919,6 @@ oauthlib = ">=3.1.0"
 requests = ">=2.13.0"
 six = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-otp"
 version = "1.1.1"
@@ -1303,11 +933,6 @@ django = ">=2.2"
 [package.extras]
 qrcode = ["qrcode"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-otp-yubikey"
 version = "1.0.0.post1"
@@ -1320,11 +945,6 @@ python-versions = "*"
 django-otp = ">=1.0.0"
 YubiOTP = ">=0.2.2"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-phonenumber-field"
 version = "5.2.0"
@@ -1341,11 +961,6 @@ phonenumbers = {version = ">=7.0.2", optional = true, markers = "extra == \"phon
 phonenumbers = ["phonenumbers (>=7.0.2)"]
 phonenumberslite = ["phonenumberslite (>=7.0.2)"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-polymorphic"
 version = "3.0.0"
@@ -1357,11 +972,6 @@ python-versions = "*"
 [package.dependencies]
 Django = ">=2.1"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-prometheus"
 version = "2.1.0"
@@ -1373,11 +983,6 @@ python-versions = "*"
 [package.dependencies]
 prometheus-client = ">=0.7"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-redis"
 version = "5.0.0"
@@ -1390,11 +995,6 @@ python-versions = ">=3.6"
 Django = ">=2.2"
 redis = ">=3.0.0"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-render-block"
 version = "0.8.1"
@@ -1406,11 +1006,6 @@ python-versions = ">=3.5"
 [package.dependencies]
 django = ">=2.2"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-reversion"
 version = "4.0.0"
@@ -1422,11 +1017,6 @@ python-versions = ">=3.6"
 [package.dependencies]
 django = ">=2.0"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-sass-processor"
 version = "1.0.0"
@@ -1438,11 +1028,6 @@ python-versions = "*"
 [package.extras]
 management_command = ["django-compressor (>=2.4)"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-select2"
 version = "7.7.3"
@@ -1458,11 +1043,6 @@ django-appconf = ">=0.6.0"
 [package.extras]
 test = ["pytest", "pytest-cov", "pytest-django", "selenium"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-storages"
 version = "1.12.2"
@@ -1482,11 +1062,6 @@ google = ["google-cloud-storage (>=1.27.0)"]
 libcloud = ["apache-libcloud"]
 sftp = ["paramiko"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-stubs"
 version = "1.9.0"
@@ -1504,11 +1079,6 @@ types-pytz = "*"
 types-PyYAML = "*"
 typing-extensions = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-stubs-ext"
 version = "0.3.1"
@@ -1521,11 +1091,6 @@ python-versions = ">=3.6"
 django = "*"
 typing-extensions = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-tables2"
 version = "2.4.1"
@@ -1540,11 +1105,6 @@ Django = ">=1.11"
 [package.extras]
 tablib = ["tablib"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-templated-email"
 version = "3.0.0"
@@ -1556,11 +1116,6 @@ python-versions = "*"
 [package.dependencies]
 django-render-block = ">=0.5"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-timezone-field"
 version = "4.2.1"
@@ -1576,11 +1131,6 @@ pytz = "*"
 [package.extras]
 rest_framework = ["djangorestframework (>=3.0.0)"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-titofisto"
 version = "0.1.2.post1"
@@ -1592,11 +1142,6 @@ python-versions = ">=3.9,<4.0"
 [package.dependencies]
 Django = ">2.2,<4.0"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-two-factor-auth"
 version = "1.13.1"
@@ -1622,11 +1167,6 @@ phonenumberslite = ["phonenumberslite (>=7.0.9,<8.99)"]
 sms = ["twilio (>=6.0)"]
 yubikey = ["django-otp-yubikey"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-uwsgi-ng"
 version = "1.1.2"
@@ -1638,11 +1178,6 @@ python-versions = "*"
 [package.extras]
 uwsgi = ["uwsgi"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-widget-tweaks"
 version = "1.4.9"
@@ -1651,11 +1186,6 @@ category = "main"
 optional = false
 python-versions = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "django-yarnpkg"
 version = "6.0.1"
@@ -1668,11 +1198,6 @@ python-versions = "*"
 django = "*"
 six = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "djangorestframework"
 version = "3.12.4"
@@ -1684,11 +1209,6 @@ python-versions = ">=3.5"
 [package.dependencies]
 django = ">=2.2"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "docutils"
 version = "0.16"
@@ -1697,11 +1217,6 @@ category = "dev"
 optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "dparse"
 version = "0.5.1"
@@ -1718,11 +1233,6 @@ toml = "*"
 [package.extras]
 pipenv = ["pipenv"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "dynaconf"
 version = "3.1.7"
@@ -1745,11 +1255,6 @@ toml = ["toml"]
 vault = ["hvac"]
 yaml = ["ruamel.yaml"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "flake8"
 version = "3.9.2"
@@ -1763,11 +1268,6 @@ mccabe = ">=0.6.0,<0.7.0"
 pycodestyle = ">=2.7.0,<2.8.0"
 pyflakes = ">=2.3.0,<2.4.0"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "flake8-bandit"
 version = "2.1.2"
@@ -1782,11 +1282,6 @@ flake8 = "*"
 flake8-polyfill = "*"
 pycodestyle = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "flake8-black"
 version = "0.2.3"
@@ -1800,11 +1295,6 @@ black = "*"
 flake8 = ">=3.0.0"
 toml = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "flake8-builtins"
 version = "1.5.3"
@@ -1819,11 +1309,6 @@ flake8 = "*"
 [package.extras]
 test = ["coverage", "coveralls", "mock", "pytest", "pytest-cov"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "flake8-django"
 version = "1.1.2"
@@ -1835,11 +1320,6 @@ python-versions = ">=3.6,<4.0"
 [package.dependencies]
 flake8 = ">=3.8.4,<4.0.0"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "flake8-docstrings"
 version = "1.6.0"
@@ -1852,11 +1332,6 @@ python-versions = "*"
 flake8 = ">=3"
 pydocstyle = ">=2.1"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "flake8-fixme"
 version = "1.1.1"
@@ -1865,11 +1340,6 @@ category = "dev"
 optional = false
 python-versions = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "flake8-isort"
 version = "4.1.1"
@@ -1886,11 +1356,6 @@ testfixtures = ">=6.8.0,<7"
 [package.extras]
 test = ["pytest-cov"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "flake8-mypy"
 version = "17.8.0"
@@ -1904,11 +1369,6 @@ attrs = "*"
 flake8 = ">=3.0.0"
 mypy = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "flake8-polyfill"
 version = "1.0.2"
@@ -1920,11 +1380,6 @@ python-versions = "*"
 [package.dependencies]
 flake8 = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "flake8-rst-docstrings"
 version = "0.2.3"
@@ -1938,11 +1393,6 @@ flake8 = ">=3.0.0"
 pygments = "*"
 restructuredtext-lint = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "freezegun"
 version = "1.1.0"
@@ -1954,14 +1404,9 @@ python-versions = ">=3.5"
 [package.dependencies]
 python-dateutil = ">=2.7"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "gitdb"
-version = "4.0.8"
+version = "4.0.9"
 description = "Git Object Database"
 category = "dev"
 optional = false
@@ -1970,11 +1415,6 @@ python-versions = ">=3.6"
 [package.dependencies]
 smmap = ">=3.0.1,<6"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "gitpython"
 version = "3.1.24"
@@ -1987,11 +1427,6 @@ python-versions = ">=3.7"
 gitdb = ">=4.0.1,<5"
 typing-extensions = {version = ">=3.7.4.3", markers = "python_version < \"3.10\""}
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "haystack-redis"
 version = "0.0.1"
@@ -2005,11 +1440,6 @@ django-haystack = "*"
 redis = "*"
 whoosh = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "html2text"
 version = "2020.1.16"
@@ -2018,11 +1448,6 @@ category = "main"
 optional = false
 python-versions = ">=3.5"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "idna"
 version = "3.3"
@@ -2031,11 +1456,6 @@ category = "main"
 optional = false
 python-versions = ">=3.5"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "imagesize"
 version = "1.2.0"
@@ -2044,11 +1464,6 @@ category = "dev"
 optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "iniconfig"
 version = "1.1.1"
@@ -2057,11 +1472,6 @@ category = "dev"
 optional = false
 python-versions = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "ipython"
 version = "7.28.0"
@@ -2094,11 +1504,6 @@ parallel = ["ipyparallel"]
 qtconsole = ["qtconsole"]
 test = ["nose (>=0.10.1)", "requests", "testpath", "pygments", "nbformat", "ipykernel", "numpy (>=1.17)"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "isort"
 version = "5.9.3"
@@ -2108,16 +1513,11 @@ optional = false
 python-versions = ">=3.6.1,<4.0"
 
 [package.extras]
-colors = ["colorama (>=0.4.3,<0.5.0)"]
-requirements_deprecated_finder = ["pip-api", "pipreqs"]
 pipfile_deprecated_finder = ["pipreqs", "requirementslib"]
+requirements_deprecated_finder = ["pipreqs", "pip-api"]
+colors = ["colorama (>=0.4.3,<0.5.0)"]
 plugins = ["setuptools"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "jedi"
 version = "0.18.0"
@@ -2133,11 +1533,6 @@ parso = ">=0.8.0,<0.9.0"
 qa = ["flake8 (==3.8.3)", "mypy (==0.782)"]
 testing = ["Django (<3.1)", "colorama", "docopt", "pytest (<6.0.0)"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "jinja2"
 version = "3.0.2"
@@ -2152,11 +1547,6 @@ MarkupSafe = ">=2.0"
 [package.extras]
 i18n = ["Babel (>=2.7)"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "jmespath"
 version = "0.10.0"
@@ -2165,11 +1555,6 @@ category = "main"
 optional = true
 python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "jwcrypto"
 version = "1.0"
@@ -2182,11 +1567,6 @@ python-versions = "*"
 cryptography = ">=2.3"
 deprecated = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "kombu"
 version = "5.1.0"
@@ -2215,11 +1595,6 @@ sqs = ["boto3 (>=1.4.4)", "pycurl (==7.43.0.2)", "urllib3 (<1.26)"]
 yaml = ["PyYAML (>=3.10)"]
 zookeeper = ["kazoo (>=1.3.1)"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "libsass"
 version = "0.21.0"
@@ -2231,11 +1606,6 @@ python-versions = "*"
 [package.dependencies]
 six = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "license-expression"
 version = "1.2"
@@ -2247,11 +1617,6 @@ python-versions = "*"
 [package.dependencies]
 "boolean.py" = ">=3.6,<4.0.0"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "markupsafe"
 version = "2.0.1"
@@ -2260,11 +1625,6 @@ category = "dev"
 optional = false
 python-versions = ">=3.6"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "matplotlib-inline"
 version = "0.1.3"
@@ -2276,11 +1636,6 @@ python-versions = ">=3.5"
 [package.dependencies]
 traitlets = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "mccabe"
 version = "0.6.1"
@@ -2289,11 +1644,6 @@ category = "dev"
 optional = false
 python-versions = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "mypy"
 version = "0.910"
@@ -2311,11 +1661,6 @@ typing-extensions = ">=3.7.4"
 dmypy = ["psutil (>=4.0)"]
 python2 = ["typed-ast (>=1.4.0,<1.5.0)"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "mypy-extensions"
 version = "0.4.3"
@@ -2324,11 +1669,6 @@ category = "dev"
 optional = false
 python-versions = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "oauthlib"
 version = "3.1.1"
@@ -2342,11 +1682,6 @@ rsa = ["cryptography (>=3.0.0,<4)"]
 signals = ["blinker (>=1.4.0)"]
 signedtoken = ["cryptography (>=3.0.0,<4)", "pyjwt (>=2.0.0,<3)"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "packaging"
 version = "21.0"
@@ -2358,11 +1693,6 @@ python-versions = ">=3.6"
 [package.dependencies]
 pyparsing = ">=2.0.2"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "parso"
 version = "0.8.2"
@@ -2375,11 +1705,6 @@ python-versions = ">=3.6"
 qa = ["flake8 (==3.8.3)", "mypy (==0.782)"]
 testing = ["docopt", "pytest (<6.0.0)"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "parsy"
 version = "1.1.0"
@@ -2388,11 +1713,6 @@ category = "dev"
 optional = false
 python-versions = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "pathspec"
 version = "0.9.0"
@@ -2401,11 +1721,6 @@ category = "dev"
 optional = false
 python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "pbr"
 version = "5.6.0"
@@ -2414,11 +1729,6 @@ category = "dev"
 optional = false
 python-versions = ">=2.6"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "persisting-theory"
 version = "0.2.1"
@@ -2427,11 +1737,6 @@ category = "main"
 optional = false
 python-versions = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "pexpect"
 version = "4.8.0"
@@ -2443,11 +1748,6 @@ python-versions = "*"
 [package.dependencies]
 ptyprocess = ">=0.5"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "pg8000"
 version = "1.22.0"
@@ -2459,11 +1759,6 @@ python-versions = ">=3.6"
 [package.dependencies]
 scramp = ">=1.4.1"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "phonenumbers"
 version = "8.12.35"
@@ -2472,11 +1767,6 @@ category = "main"
 optional = false
 python-versions = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "pickleshare"
 version = "0.7.5"
@@ -2485,11 +1775,6 @@ category = "main"
 optional = false
 python-versions = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "pillow"
 version = "8.4.0"
@@ -2498,11 +1783,6 @@ category = "main"
 optional = false
 python-versions = ">=3.6"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "pluggy"
 version = "1.0.0"
@@ -2515,11 +1795,6 @@ python-versions = ">=3.6"
 dev = ["pre-commit", "tox"]
 testing = ["pytest", "pytest-benchmark"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "prometheus-client"
 version = "0.11.0"
@@ -2531,11 +1806,6 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
 [package.extras]
 twisted = ["twisted"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "prompt-toolkit"
 version = "3.0.21"
@@ -2547,11 +1817,6 @@ python-versions = ">=3.6.2"
 [package.dependencies]
 wcwidth = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "psutil"
 version = "5.8.0"
@@ -2563,11 +1828,6 @@ python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
 [package.extras]
 test = ["ipaddress", "mock", "unittest2", "enum34", "pywin32", "wmi"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "psycopg2"
 version = "2.9.1"
@@ -2576,11 +1836,6 @@ category = "main"
 optional = false
 python-versions = ">=3.6"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "ptyprocess"
 version = "0.7.0"
@@ -2589,11 +1844,6 @@ category = "main"
 optional = false
 python-versions = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "py"
 version = "1.10.0"
@@ -2602,11 +1852,6 @@ category = "dev"
 optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "pyasn1"
 version = "0.4.8"
@@ -2615,11 +1860,6 @@ category = "main"
 optional = true
 python-versions = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "pyasn1-modules"
 version = "0.2.8"
@@ -2631,11 +1871,6 @@ python-versions = "*"
 [package.dependencies]
 pyasn1 = ">=0.4.6,<0.5.0"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "pycodestyle"
 version = "2.7.0"
@@ -2644,11 +1879,6 @@ category = "dev"
 optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "pycparser"
 version = "2.20"
@@ -2657,11 +1887,6 @@ category = "main"
 optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "pycryptodome"
 version = "3.11.0"
@@ -2670,11 +1895,6 @@ category = "main"
 optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "pydocstyle"
 version = "6.1.1"
@@ -2689,11 +1909,6 @@ snowballstemmer = "*"
 [package.extras]
 toml = ["toml"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "pyflakes"
 version = "2.3.1"
@@ -2702,11 +1917,6 @@ category = "dev"
 optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "pygments"
 version = "2.10.0"
@@ -2715,11 +1925,6 @@ category = "main"
 optional = false
 python-versions = ">=3.5"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "pyjwt"
 version = "2.3.0"
@@ -2737,23 +1942,16 @@ dev = ["sphinx", "sphinx-rtd-theme", "zope.interface", "cryptography (>=3.3.1)",
 docs = ["sphinx", "sphinx-rtd-theme", "zope.interface"]
 tests = ["pytest (>=6.0.0,<7.0.0)", "coverage[toml] (==5.0.4)"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "pyparsing"
-version = "2.4.7"
+version = "3.0.1"
 description = "Python parsing module"
 category = "main"
 optional = false
-python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
+python-versions = ">=3.6"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
+[package.extras]
+diagrams = ["jinja2", "railroad-diagrams"]
 
 [[package]]
 name = "pytest"
@@ -2776,11 +1974,6 @@ toml = "*"
 [package.extras]
 testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xmlschema"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "pytest-cov"
 version = "2.12.1"
@@ -2797,11 +1990,6 @@ toml = "*"
 [package.extras]
 testing = ["fields", "hunter", "process-tests", "six", "pytest-xdist", "virtualenv"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "pytest-django"
 version = "4.4.0"
@@ -2817,11 +2005,6 @@ pytest = ">=5.4.0"
 docs = ["sphinx", "sphinx-rtd-theme"]
 testing = ["django", "django-configurations (>=2.0)"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "pytest-django-testing-postgresql"
 version = "0.1.post0"
@@ -2834,11 +2017,6 @@ python-versions = "*"
 dj-database-url = "*"
 "testing.postgresql" = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "pytest-sugar"
 version = "0.9.4"
@@ -2852,11 +2030,6 @@ packaging = ">=14.1"
 pytest = ">=2.9"
 termcolor = ">=1.1.0"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "python-crontab"
 version = "2.6.0"
@@ -2872,11 +2045,6 @@ python-dateutil = "*"
 cron-description = ["cron-descriptor"]
 cron-schedule = ["croniter"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "python-dateutil"
 version = "2.8.2"
@@ -2888,11 +2056,6 @@ python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7"
 [package.dependencies]
 six = ">=1.5"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "python-gnupg"
 version = "0.4.7"
@@ -2901,11 +2064,6 @@ category = "main"
 optional = false
 python-versions = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "python-ldap"
 version = "3.3.1"
@@ -2918,11 +2076,6 @@ python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*"
 pyasn1 = ">=0.3.7"
 pyasn1_modules = ">=0.1.5"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "python3-openid"
 version = "3.2.0"
@@ -2938,11 +2091,6 @@ defusedxml = "*"
 mysql = ["mysql-connector-python"]
 postgresql = ["psycopg2"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "pytz"
 version = "2021.3"
@@ -2951,11 +2099,6 @@ category = "main"
 optional = false
 python-versions = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "pyyaml"
 version = "6.0"
@@ -2964,11 +2107,6 @@ category = "dev"
 optional = false
 python-versions = ">=3.6"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "qrcode"
 version = "6.1"
@@ -2987,11 +2125,6 @@ maintainer = ["zest.releaser"]
 pil = ["pillow"]
 test = ["pytest", "pytest-cov", "mock"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "redis"
 version = "3.5.3"
@@ -3003,11 +2136,6 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
 [package.extras]
 hiredis = ["hiredis (>=0.1.3)"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "regex"
 version = "2021.10.23"
@@ -3016,11 +2144,6 @@ category = "dev"
 optional = false
 python-versions = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "requests"
 version = "2.26.0"
@@ -3039,11 +2162,6 @@ urllib3 = ">=1.21.1,<1.27"
 socks = ["PySocks (>=1.5.6,!=1.5.7)", "win-inet-pton"]
 use_chardet_on_py3 = ["chardet (>=3.0.2,<5)"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "requests-oauthlib"
 version = "1.3.0"
@@ -3059,11 +2177,6 @@ requests = ">=2.0.0"
 [package.extras]
 rsa = ["oauthlib[signedtoken] (>=3.0.0)"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "restructuredtext-lint"
 version = "1.3.2"
@@ -3075,11 +2188,6 @@ python-versions = "*"
 [package.dependencies]
 docutils = ">=0.11,<1.0"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "ruamel.yaml"
 version = "0.17.16"
@@ -3095,11 +2203,6 @@ python-versions = ">=3"
 docs = ["ryd"]
 jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "ruamel.yaml.clib"
 version = "0.2.6"
@@ -3108,11 +2211,6 @@ category = "main"
 optional = false
 python-versions = ">=3.5"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "rules"
 version = "2.2"
@@ -3121,11 +2219,6 @@ category = "main"
 optional = false
 python-versions = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "s3transfer"
 version = "0.5.0"
@@ -3140,11 +2233,6 @@ botocore = ">=1.12.36,<2.0a.0"
 [package.extras]
 crt = ["botocore[crt] (>=1.20.29,<2.0a.0)"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "safety"
 version = "1.10.3"
@@ -3159,11 +2247,6 @@ dparse = ">=0.5.1"
 packaging = "*"
 requests = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "scramp"
 version = "1.4.1"
@@ -3175,11 +2258,6 @@ python-versions = ">=3.6"
 [package.dependencies]
 asn1crypto = ">=1.4.0"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "selenium"
 version = "3.141.0"
@@ -3191,11 +2269,6 @@ python-versions = "*"
 [package.dependencies]
 urllib3 = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "sentry-sdk"
 version = "1.4.3"
@@ -3238,11 +2311,6 @@ category = "main"
 optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "smmap"
 version = "5.0.0"
@@ -3251,11 +2319,6 @@ category = "dev"
 optional = false
 python-versions = ">=3.6"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "snowballstemmer"
 version = "2.1.0"
@@ -3264,11 +2327,6 @@ category = "dev"
 optional = false
 python-versions = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "soupsieve"
 version = "2.2.1"
@@ -3277,11 +2335,6 @@ category = "main"
 optional = false
 python-versions = ">=3.6"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "spdx-license-list"
 version = "0.5.2"
@@ -3290,11 +2343,6 @@ category = "main"
 optional = false
 python-versions = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "sphinx"
 version = "3.5.4"
@@ -3326,11 +2374,6 @@ docs = ["sphinxcontrib-websupport"]
 lint = ["flake8 (>=3.5.0)", "isort", "mypy (>=0.800)", "docutils-stubs"]
 test = ["pytest", "pytest-cov", "html5lib", "cython", "typed-ast"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "sphinx-autodoc-typehints"
 version = "1.12.0"
@@ -3346,11 +2389,6 @@ Sphinx = ">=3.0"
 test = ["pytest (>=3.1.0)", "typing-extensions (>=3.5)", "sphobjinv (>=2.0)", "Sphinx (>=3.2.0)", "dataclasses"]
 type_comments = ["typed-ast (>=1.4.0)"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "sphinx-materialdesign-theme"
 version = "0.1.11"
@@ -3359,11 +2397,6 @@ category = "dev"
 optional = false
 python-versions = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "sphinxcontrib-applehelp"
 version = "1.0.2"
@@ -3376,11 +2409,6 @@ python-versions = ">=3.5"
 lint = ["flake8", "mypy", "docutils-stubs"]
 test = ["pytest"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "sphinxcontrib-devhelp"
 version = "1.0.2"
@@ -3393,11 +2421,6 @@ python-versions = ">=3.5"
 lint = ["flake8", "mypy", "docutils-stubs"]
 test = ["pytest"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "sphinxcontrib-django"
 version = "0.5.1"
@@ -3406,11 +2429,6 @@ category = "dev"
 optional = false
 python-versions = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "sphinxcontrib-htmlhelp"
 version = "2.0.0"
@@ -3423,11 +2441,6 @@ python-versions = ">=3.6"
 lint = ["flake8", "mypy", "docutils-stubs"]
 test = ["pytest", "html5lib"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "sphinxcontrib-jsmath"
 version = "1.0.1"
@@ -3439,11 +2452,6 @@ python-versions = ">=3.5"
 [package.extras]
 test = ["pytest", "flake8", "mypy"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "sphinxcontrib-qthelp"
 version = "1.0.3"
@@ -3456,11 +2464,6 @@ python-versions = ">=3.5"
 lint = ["flake8", "mypy", "docutils-stubs"]
 test = ["pytest"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "sphinxcontrib-serializinghtml"
 version = "1.1.5"
@@ -3473,11 +2476,6 @@ python-versions = ">=3.5"
 lint = ["flake8", "mypy", "docutils-stubs"]
 test = ["pytest"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "sqlparse"
 version = "0.4.2"
@@ -3486,11 +2484,6 @@ category = "main"
 optional = false
 python-versions = ">=3.5"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "stevedore"
 version = "3.5.0"
@@ -3502,11 +2495,6 @@ python-versions = ">=3.6"
 [package.dependencies]
 pbr = ">=2.0.0,<2.1.0 || >2.1.0"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "termcolor"
 version = "1.1.0"
@@ -3515,11 +2503,6 @@ category = "dev"
 optional = false
 python-versions = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "testfixtures"
 version = "6.18.3"
@@ -3533,11 +2516,6 @@ build = ["setuptools-git", "wheel", "twine"]
 docs = ["sphinx", "zope.component", "sybil", "twisted", "mock", "django (<2)", "django"]
 test = ["pytest (>=3.6)", "pytest-cov", "pytest-django", "zope.component", "sybil", "twisted", "mock", "django (<2)", "django"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "testing.common.database"
 version = "2.0.3"
@@ -3549,11 +2527,6 @@ python-versions = "*"
 [package.extras]
 testing = ["nose"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "testing.postgresql"
 version = "1.3.0"
@@ -3569,11 +2542,6 @@ pg8000 = ">=1.10"
 [package.extras]
 testing = ["sqlalchemy", "nose", "psycopg2"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "toml"
 version = "0.10.2"
@@ -3582,14 +2550,9 @@ category = "main"
 optional = false
 python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "traitlets"
-version = "5.1.0"
+version = "5.1.1"
 description = "Traitlets Python configuration system"
 category = "main"
 optional = false
@@ -3598,11 +2561,6 @@ python-versions = ">=3.7"
 [package.extras]
 test = ["pytest"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "twilio"
 version = "7.2.0"
@@ -3616,11 +2574,6 @@ PyJWT = ">=2.0.0,<3.0.0"
 pytz = "*"
 requests = ">=2.0.0"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "typed-ast"
 version = "1.4.3"
@@ -3629,11 +2582,6 @@ category = "dev"
 optional = false
 python-versions = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "types-pytz"
 version = "2021.3.0"
@@ -3642,11 +2590,6 @@ category = "dev"
 optional = false
 python-versions = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "types-pyyaml"
 version = "6.0.0"
@@ -3655,11 +2598,6 @@ category = "dev"
 optional = false
 python-versions = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "typing-extensions"
 version = "3.10.0.2"
@@ -3668,11 +2606,6 @@ category = "dev"
 optional = false
 python-versions = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "urllib3"
 version = "1.26.7"
@@ -3686,11 +2619,6 @@ brotli = ["brotlipy (>=0.6.0)"]
 secure = ["pyOpenSSL (>=0.14)", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "certifi", "ipaddress"]
 socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"]
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "uwsgi"
 version = "2.0.20"
@@ -3699,11 +2627,6 @@ category = "dev"
 optional = false
 python-versions = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "vine"
 version = "5.0.0"
@@ -3712,11 +2635,6 @@ category = "main"
 optional = false
 python-versions = ">=3.6"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "wcwidth"
 version = "0.2.5"
@@ -3725,11 +2643,6 @@ category = "main"
 optional = false
 python-versions = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "webencodings"
 version = "0.5.1"
@@ -3738,11 +2651,6 @@ category = "main"
 optional = false
 python-versions = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "whoosh"
 version = "2.7.4"
@@ -3751,11 +2659,6 @@ category = "main"
 optional = false
 python-versions = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "wrapt"
 version = "1.13.2"
@@ -3764,11 +2667,6 @@ category = "main"
 optional = false
 python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [[package]]
 name = "yubiotp"
 version = "1.0.0.post1"
@@ -3780,11 +2678,6 @@ python-versions = "*"
 [package.dependencies]
 pycryptodome = "*"
 
-[package.source]
-type = "legacy"
-url = "https://edugit.org/api/v4/projects/461/packages/pypi/simple"
-reference = "gitlab"
-
 [extras]
 ldap = ["django-auth-ldap"]
 s3 = ["boto3", "django-storages"]
@@ -3802,6 +2695,7 @@ alabaster = [
 ]
 aleksis-builddeps = [
     {file = "AlekSIS-Builddeps-4.tar.gz", hash = "sha256:aaaa22965228b9b9b7de812e3e7fa9cbfdbf8635bb22d6f3a201dc0cc6d8d307"},
+    {file = "AlekSIS_Builddeps-4-py3-none-any.whl", hash = "sha256:02a93e503f5810e6c93a8bc829bc8cbda735ccbf78b91954d2f6507dfea3d01f"},
 ]
 amqp = [
     {file = "amqp-5.0.6-py3-none-any.whl", hash = "sha256:493a2ac6788ce270a2f6a765b017299f60c1998f5a8617908ee9be082f7300fb"},
@@ -3864,12 +2758,12 @@ bleach = [
     {file = "boolean.py-3.8.tar.gz", hash = "sha256:cc24e20f985d60cd4a3a5a1c0956dd12611159d32a75081dabd0c9ab981acaa4"},
 ]
 boto3 = [
-    {file = "boto3-1.19.2-py3-none-any.whl", hash = "sha256:1b8fac5f11ee1d185770d7619f2212e67e636ce190512770d0d36fd162739628"},
-    {file = "boto3-1.19.2.tar.gz", hash = "sha256:11a6035060230e92327d4f10fef6bc44188b2cd68504012bc25ed62ac31d670b"},
+    {file = "boto3-1.19.3-py3-none-any.whl", hash = "sha256:2dfc8cf34d6dfbdfca4c88e8fddf9fe95cde489fb83144fe35f989ec6790e325"},
+    {file = "boto3-1.19.3.tar.gz", hash = "sha256:e36ffaf9969648e2f435aa1f0029956fea3aac52466eef3bcb43bde498a182dd"},
 ]
 botocore = [
-    {file = "botocore-1.22.2-py3-none-any.whl", hash = "sha256:681d0d854d08beb9a5727152e95a884439b76cf19fb38d69ca2f17f1404d48ae"},
-    {file = "botocore-1.22.2.tar.gz", hash = "sha256:011360e79a4b843aa6591573cfa61e8eddc99b91adab1dfdb9a2b7f2c8511193"},
+    {file = "botocore-1.22.3-py3-none-any.whl", hash = "sha256:aacdb9b8e09e356515966251d1e08d9929575a76af504992bfb941553dee59c2"},
+    {file = "botocore-1.22.3.tar.gz", hash = "sha256:53ca22aeac9b53fe5ec1f40b8ca9620ffe8b054458abfeb9ab74bbe9e0b0ecfa"},
 ]
 bs4 = [
     {file = "bs4-0.0.1.tar.gz", hash = "sha256:36ecea1fd7cc5c0c6e4a1ff075df26d50da647b75376626cc186e2212886dd3a"},
@@ -4331,8 +3225,8 @@ freezegun = [
     {file = "freezegun-1.1.0.tar.gz", hash = "sha256:177f9dd59861d871e27a484c3332f35a6e3f5d14626f2bf91be37891f18927f3"},
 ]
 gitdb = [
-    {file = "gitdb-4.0.8-py3-none-any.whl", hash = "sha256:6875cbaed01f1b750394f372607803768fc7dad7c58c7ceb5f5917e980d779b2"},
-    {file = "gitdb-4.0.8.tar.gz", hash = "sha256:858966a9310649cb24a387c101429bb5a1110068a312517722b0281077e78bc6"},
+    {file = "gitdb-4.0.9-py3-none-any.whl", hash = "sha256:8033ad4e853066ba6ca92050b9df2f89301b8fc8bf7e9324d412a63f8bf1a8fd"},
+    {file = "gitdb-4.0.9.tar.gz", hash = "sha256:bac2fd45c0a1c9cf619e63a90d62bdc63892ef92387424b855792a6cabe789aa"},
 ]
 gitpython = [
     {file = "GitPython-3.1.24-py3-none-any.whl", hash = "sha256:dc0a7f2f697657acc8d7f89033e8b1ea94dd90356b2983bca89dc8d2ab3cc647"},
@@ -4642,12 +3536,34 @@ py = [
     {file = "py-1.10.0.tar.gz", hash = "sha256:21b81bda15b66ef5e1a777a21c4dcd9c20ad3efd0b3f817e7a809035269e1bd3"},
 ]
 pyasn1 = [
+    {file = "pyasn1-0.4.8-py2.4.egg", hash = "sha256:fec3e9d8e36808a28efb59b489e4528c10ad0f480e57dcc32b4de5c9d8c9fdf3"},
+    {file = "pyasn1-0.4.8-py2.5.egg", hash = "sha256:0458773cfe65b153891ac249bcf1b5f8f320b7c2ce462151f8fa74de8934becf"},
+    {file = "pyasn1-0.4.8-py2.6.egg", hash = "sha256:5c9414dcfede6e441f7e8f81b43b34e834731003427e5b09e4e00e3172a10f00"},
+    {file = "pyasn1-0.4.8-py2.7.egg", hash = "sha256:6e7545f1a61025a4e58bb336952c5061697da694db1cae97b116e9c46abcf7c8"},
     {file = "pyasn1-0.4.8-py2.py3-none-any.whl", hash = "sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d"},
+    {file = "pyasn1-0.4.8-py3.1.egg", hash = "sha256:78fa6da68ed2727915c4767bb386ab32cdba863caa7dbe473eaae45f9959da86"},
+    {file = "pyasn1-0.4.8-py3.2.egg", hash = "sha256:08c3c53b75eaa48d71cf8c710312316392ed40899cb34710d092e96745a358b7"},
+    {file = "pyasn1-0.4.8-py3.3.egg", hash = "sha256:03840c999ba71680a131cfaee6fab142e1ed9bbd9c693e285cc6aca0d555e576"},
+    {file = "pyasn1-0.4.8-py3.4.egg", hash = "sha256:7ab8a544af125fb704feadb008c99a88805126fb525280b2270bb25cc1d78a12"},
+    {file = "pyasn1-0.4.8-py3.5.egg", hash = "sha256:e89bf84b5437b532b0803ba5c9a5e054d21fec423a89952a74f87fa2c9b7bce2"},
+    {file = "pyasn1-0.4.8-py3.6.egg", hash = "sha256:014c0e9976956a08139dc0712ae195324a75e142284d5f87f1a87ee1b068a359"},
+    {file = "pyasn1-0.4.8-py3.7.egg", hash = "sha256:99fcc3c8d804d1bc6d9a099921e39d827026409a58f2a720dcdb89374ea0c776"},
     {file = "pyasn1-0.4.8.tar.gz", hash = "sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba"},
 ]
 pyasn1-modules = [
     {file = "pyasn1-modules-0.2.8.tar.gz", hash = "sha256:905f84c712230b2c592c19470d3ca8d552de726050d1d1716282a1f6146be65e"},
+    {file = "pyasn1_modules-0.2.8-py2.4.egg", hash = "sha256:0fe1b68d1e486a1ed5473f1302bd991c1611d319bba158e98b106ff86e1d7199"},
+    {file = "pyasn1_modules-0.2.8-py2.5.egg", hash = "sha256:fe0644d9ab041506b62782e92b06b8c68cca799e1a9636ec398675459e031405"},
+    {file = "pyasn1_modules-0.2.8-py2.6.egg", hash = "sha256:a99324196732f53093a84c4369c996713eb8c89d360a496b599fb1a9c47fc3eb"},
+    {file = "pyasn1_modules-0.2.8-py2.7.egg", hash = "sha256:0845a5582f6a02bb3e1bde9ecfc4bfcae6ec3210dd270522fee602365430c3f8"},
     {file = "pyasn1_modules-0.2.8-py2.py3-none-any.whl", hash = "sha256:a50b808ffeb97cb3601dd25981f6b016cbb3d31fbf57a8b8a87428e6158d0c74"},
+    {file = "pyasn1_modules-0.2.8-py3.1.egg", hash = "sha256:f39edd8c4ecaa4556e989147ebf219227e2cd2e8a43c7e7fcb1f1c18c5fd6a3d"},
+    {file = "pyasn1_modules-0.2.8-py3.2.egg", hash = "sha256:b80486a6c77252ea3a3e9b1e360bc9cf28eaac41263d173c032581ad2f20fe45"},
+    {file = "pyasn1_modules-0.2.8-py3.3.egg", hash = "sha256:65cebbaffc913f4fe9e4808735c95ea22d7a7775646ab690518c056784bc21b4"},
+    {file = "pyasn1_modules-0.2.8-py3.4.egg", hash = "sha256:15b7c67fabc7fc240d87fb9aabf999cf82311a6d6fb2c70d00d3d0604878c811"},
+    {file = "pyasn1_modules-0.2.8-py3.5.egg", hash = "sha256:426edb7a5e8879f1ec54a1864f16b882c2837bfd06eee62f2c982315ee2473ed"},
+    {file = "pyasn1_modules-0.2.8-py3.6.egg", hash = "sha256:cbac4bc38d117f2a49aeedec4407d23e8866ea4ac27ff2cf7fb3e5b570df19e0"},
+    {file = "pyasn1_modules-0.2.8-py3.7.egg", hash = "sha256:c29a5e5cc7a3f05926aff34e097e84f8589cd790ce0ed41b67aed6857b26aafd"},
 ]
 pycodestyle = [
     {file = "pycodestyle-2.7.0-py2.py3-none-any.whl", hash = "sha256:514f76d918fcc0b55c6680472f0a37970994e07bbb80725808c17089be302068"},
@@ -4706,8 +3622,8 @@ pyjwt = [
     {file = "PyJWT-2.3.0.tar.gz", hash = "sha256:b888b4d56f06f6dcd777210c334e69c737be74755d3e5e9ee3fe67dc18a0ee41"},
 ]
 pyparsing = [
-    {file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"},
-    {file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"},
+    {file = "pyparsing-3.0.1-py3-none-any.whl", hash = "sha256:fd93fc45c47893c300bd98f5dd1b41c0e783eaeb727e7cea210dcc09d64ce7c3"},
+    {file = "pyparsing-3.0.1.tar.gz", hash = "sha256:84196357aa3566d64ad123d7a3c67b0e597a115c4934b097580e5ce220b91531"},
 ]
 pytest = [
     {file = "pytest-6.2.5-py3-none-any.whl", hash = "sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134"},
@@ -4838,6 +3754,7 @@ requests = [
 requests-oauthlib = [
     {file = "requests-oauthlib-1.3.0.tar.gz", hash = "sha256:b4261601a71fd721a8bd6d7aa1cc1d6a8a93b4a9f5e96626f8e4d91e8beeaa6a"},
     {file = "requests_oauthlib-1.3.0-py2.py3-none-any.whl", hash = "sha256:7f71572defaecd16372f9006f33c2ec8c077c3cfa6f5911a9a90202beb513f3d"},
+    {file = "requests_oauthlib-1.3.0-py3.7.egg", hash = "sha256:fa6c47b933f01060936d87ae9327fead68768b69c6c9ea2109c48be30f2d4dbc"},
 ]
 restructuredtext-lint = [
     {file = "restructuredtext_lint-1.3.2.tar.gz", hash = "sha256:d3b10a1fe2ecac537e51ae6d151b223b78de9fafdd50e5eb6b08c243df173c80"},
@@ -4979,8 +3896,8 @@ toml = [
     {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
 ]
 traitlets = [
-    {file = "traitlets-5.1.0-py3-none-any.whl", hash = "sha256:03f172516916220b58c9f19d7f854734136dd9528103d04e9bf139a92c9f54c4"},
-    {file = "traitlets-5.1.0.tar.gz", hash = "sha256:bd382d7ea181fbbcce157c133db9a829ce06edffe097bcf3ab945b435452b46d"},
+    {file = "traitlets-5.1.1-py3-none-any.whl", hash = "sha256:2d313cc50a42cd6c277e7d7dc8d4d7fedd06a2c215f78766ae7b1a66277e0033"},
+    {file = "traitlets-5.1.1.tar.gz", hash = "sha256:059f456c5a7c1c82b98c2e8c799f39c9b8128f6d0d46941ee118daace9eb70c7"},
 ]
 twilio = [
     {file = "twilio-7.2.0.tar.gz", hash = "sha256:f99643641c193fcd09b58f20ef65a78937e5c426319530a42c325b3abd80e739"},
diff --git a/tox.ini b/tox.ini
index 2aed3362cf7e62c15839c37ec5fb191dcd1a2f4d..6ba5d926ea520a574125f4a9717b93ba0020a2c3 100644
--- a/tox.ini
+++ b/tox.ini
@@ -47,6 +47,11 @@ commands =
     poetry run isort aleksis/
     poetry run black aleksis/
 
+[testenv:makemessages]
+commands =
+    poetry run aleksis-admin makemessages --no-wrap -e html,txt,py,email -i static -l ar -l de_DE -l fr -l nb_NO -l tr_TR -l la
+    poetry run aleksis-admin makemessages --no-wrap -d djangojs -i **/node_modules -l ar -l de_DE -l fr -l nb_NO -l tr_TR -l la
+
 [flake8]
 max_line_length = 100
 exclude = migrations,tests