diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 955750958d170e723e9714295750d0e1204e878f..b2516b9ec034623bc679680e228e6b96bbc0ef91 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -2,8 +2,14 @@ include:
     - project: "AlekSIS/official/AlekSIS"
       file: /ci/general.yml
     - project: "AlekSIS/official/AlekSIS"
-      file: /ci/test.yml
+      file: /ci/test/test.yml
     - project: "AlekSIS/official/AlekSIS"
-      file: /ci/build_dist.yml
+      file: /ci/test/lint.yml
     - project: "AlekSIS/official/AlekSIS"
-      file: /ci/deploy_pypi.yml
+      file: /ci/test/security.yml
+    - project: "AlekSIS/official/AlekSIS"
+      file: /ci/build/dist.yml
+    - project: "AlekSIS/official/AlekSIS"
+      file: /ci/deploy/pages.yml
+    - project: "AlekSIS/official/AlekSIS"
+      file: /ci/deploy/pypi.yml
diff --git a/aleksis/core/admin.py b/aleksis/core/admin.py
index e35910f597983ea8cfaa957cd475e607c490dfa0..ae51f4bcfddec26f5b31af1fb79628ac6812476f 100644
--- a/aleksis/core/admin.py
+++ b/aleksis/core/admin.py
@@ -10,6 +10,7 @@ from .models import (
     Announcement,
     AnnouncementRecipient,
     CustomMenuItem,
+    DataCheckResult,
     Group,
     Notification,
     Person,
@@ -33,3 +34,4 @@ class AnnouncementAdmin(BaseModelAdmin, VersionAdmin):
 
 
 admin.site.register(Announcement, AnnouncementAdmin)
+admin.site.register(DataCheckResult)
diff --git a/aleksis/core/apps.py b/aleksis/core/apps.py
index e88d812bde928fcdc2f38027b8323aa8f09ad07b..75feb14c3ed9e6d717d1bbd89bf0ef87070d34b3 100644
--- a/aleksis/core/apps.py
+++ b/aleksis/core/apps.py
@@ -1,12 +1,14 @@
 from typing import Any, List, Optional, Tuple
 
 import django.apps
+from django.apps import apps
 from django.conf import settings
 from django.db import OperationalError, ProgrammingError
 from django.http import HttpRequest
 from django.utils.module_loading import autodiscover_modules
 
 from dynamic_preferences.registries import preference_models
+from health_check.plugins import plugin_dir
 
 from .registries import (
     group_preferences_registry,
@@ -52,6 +54,22 @@ class CoreConfig(AppConfig):
 
         self._refresh_authentication_backends()
 
+        self._load_data_checks()
+
+        from .health_checks import DataChecksHealthCheckBackend
+
+        plugin_dir.register(DataChecksHealthCheckBackend)
+
+    @classmethod
+    def _load_data_checks(cls):
+        """Get all data checks from all loaded models."""
+        from aleksis.core.data_checks import DataCheckRegistry
+
+        data_checks = []
+        for model in apps.get_models():
+            data_checks += getattr(model, "data_checks", [])
+        DataCheckRegistry.data_checks = data_checks
+
     @classmethod
     def _refresh_authentication_backends(cls):
         """Refresh config list of enabled authentication backends."""
diff --git a/aleksis/core/data_checks.py b/aleksis/core/data_checks.py
new file mode 100644
index 0000000000000000000000000000000000000000..1279822f8d1f28bb40e040d9eaf0bb8126540940
--- /dev/null
+++ b/aleksis/core/data_checks.py
@@ -0,0 +1,257 @@
+import logging
+
+from django.contrib.contenttypes.models import ContentType
+from django.db.models.aggregates import Count
+from django.utils.functional import classproperty
+from django.utils.translation import gettext as _
+
+import reversion
+from reversion import set_comment
+from templated_email import send_templated_mail
+
+from .util.core_helpers import celery_optional, get_site_preferences
+
+
+class SolveOption:
+    """Define a solve option for one or more data checks.
+
+    Solve options are used in order to give the data admin typical
+    solutions to a data issue detected by a data check.
+
+    Example definition
+
+    .. code-block:: python
+
+        from aleksis.core.data_checks import SolveOption
+        from django.utils.translation import gettext as _
+
+        class DeleteSolveOption(SolveOption):
+            name = "delete" # has to be unqiue
+            verbose_name = _("Delete") # should make use of i18n
+
+            @classmethod
+            def solve(cls, check_result: "DataCheckResult"):
+                check_result.related_object.delete()
+                check_result.delete()
+
+    After the solve option has been successfully executed,
+    the corresponding data check result has to be deleted.
+    """
+
+    name: str = "default"
+    verbose_name: str = ""
+
+    @classmethod
+    def solve(cls, check_result: "DataCheckResult"):
+        pass
+
+
+class IgnoreSolveOption(SolveOption):
+    """Mark the object with data issues as solved."""
+
+    name = "ignore"
+    verbose_name = _("Ignore problem")
+
+    @classmethod
+    def solve(cls, check_result: "DataCheckResult"):
+        """Mark the object as solved without doing anything more."""
+        check_result.solved = True
+        check_result.save()
+
+
+class DataCheck:
+    """Define a data check.
+
+    Data checks should be used to search objects of
+    any type which are broken or need some extra action.
+
+    Defining data checks
+    --------------------
+    Data checks are defined by inheriting from the class DataCheck
+    and registering the inherited class in the data check registry.
+
+    Example:
+
+    ``data_checks.py``
+    ******************
+
+    .. code-block:: python
+
+        from aleksis.core.data_checks import DataCheck, DATA_CHECK_REGISTRY
+        from django.utils.translation import gettext as _
+
+        class ExampleDataCheck(DataCheck):
+            name = "example" # has to be unique
+            verbose_name = _("Ensure that there are no examples.")
+            problem_name = _("There is an example.") # should both make use of i18n
+
+            solve_options = {
+                IgnoreSolveOption.name: IgnoreSolveOption
+            }
+
+            @classmethod
+            def check_data(cls):
+                from example_app.models import ExampleModel
+
+                wrong_examples = ExampleModel.objects.filter(wrong_value=True)
+
+                for example in wrong_examples:
+                    cls.register_result(example)
+
+    ``models.py``
+    *************
+
+    .. code-block:: python
+
+        from .data_checks import ExampleDataCheck
+
+        # ...
+
+        class ExampleModel(Model):
+            data_checks = [ExampleDataCheck]
+
+
+    Solve options are used in order to give the data admin typical solutions to this specific issue.
+    They are defined by inheriting from SolveOption.
+    More information about defining solve options can be find there.
+
+    The dictionary ``solve_options`` should include at least the IgnoreSolveOption,
+    but preferably also own solve options. The keys in this dictionary
+    have to be ``<YourOption>SolveOption.name``
+    and the values must be the corresponding solve option classes.
+
+    The class method ``check_data`` does the actual work. In this method
+    your code should find all objects with issues and should register
+    them in the result database using the class method ``register_result``.
+
+    Data checks have to be registered in their corresponding model.
+    This can be done by adding a list ``data_checks``
+    containing the data check classes.
+
+    Executing data checks
+    ---------------------
+    The data checks can be executed by using the
+    celery task named ``aleksis.core.data_checks.check_data``.
+    We recommend to create a periodic task in the backend
+    which executes ``check_data`` on a regular base (e. g. every day).
+
+    .. warning::
+        To use the option described above, you must have setup celery properly.
+
+    Notifications about results
+    ---------------------------
+    The data check tasks can notify persons via email
+    if there are new data issues. You can set these persons
+    by adding them to the preference
+    ``Email recipients for data checks problem emails`` in the site configuration.
+
+    To enable this feature, you also have to activate
+    the preference ``Send emails if data checks detect problems``.
+    """  # noqa: D412
+
+    name: str = ""
+    verbose_name: str = ""
+    problem_name: str = ""
+
+    solve_options = {IgnoreSolveOption.name: IgnoreSolveOption}
+
+    @classmethod
+    def check_data(cls):
+        """Find all objects with data issues and register them."""
+        pass
+
+    @classmethod
+    def solve(cls, check_result: "DataCheckResult", solve_option: str):
+        """Execute a solve option for an object detected by this check.
+
+        :param check_result: The result item from database
+        :param solve_option: The name of the solve option that should be executed
+        """
+        with reversion.create_revision():
+            solve_option_obj = cls.solve_options[solve_option]
+            set_comment(
+                _(
+                    f"Solve option '{solve_option_obj.verbose_name}' "
+                    f"for data check '{cls.verbose_name}'"
+                )
+            )
+            solve_option_obj.solve(check_result)
+
+    @classmethod
+    def register_result(cls, instance) -> "DataCheckResult":
+        """Register an object with data issues in the result database.
+
+        :param instance: The affected object
+        :return: The database entry
+        """
+        from aleksis.core.models import DataCheckResult
+
+        ct = ContentType.objects.get_for_model(instance)
+        result = DataCheckResult.objects.get_or_create(
+            check=cls.name, content_type=ct, object_id=instance.id
+        )
+        return result
+
+
+class DataCheckRegistry:
+    """Create central registry for all data checks in AlekSIS."""
+
+    data_checks = []
+
+    @classproperty
+    def data_checks_by_name(cls):
+        return {check.name: check for check in cls.data_checks}
+
+    @classproperty
+    def data_checks_choices(cls):
+        return [(check.name, check.verbose_name) for check in cls.data_checks]
+
+
+@celery_optional
+def check_data():
+    """Execute all registered data checks and send email if activated."""
+    for check in DataCheckRegistry.data_checks:
+        logging.info(f"Run check: {check.verbose_name}")
+        check.check_data()
+
+    if get_site_preferences()["general__data_checks_send_emails"]:
+        send_emails_for_data_checks()
+
+
+def send_emails_for_data_checks():
+    """Notify one or more recipients about new problems with data.
+
+    Recipients can be set in dynamic preferences.
+    """
+    from .models import DataCheckResult  # noqa
+
+    results = DataCheckResult.objects.filter(solved=False, sent=False)
+
+    if results.exists():
+        results_by_check = results.values("check").annotate(count=Count("check"))
+
+        results_with_checks = []
+        for result in results_by_check:
+            results_with_checks.append(
+                (DataCheckRegistry.data_checks_by_name[result["check"]], result["count"])
+            )
+
+        recipient_list = [
+            p.mail_sender
+            for p in get_site_preferences()["general__data_checks_recipients"]
+            if p.email
+        ]
+
+        for group in get_site_preferences()["general__data_checks_recipient_groups"]:
+            recipient_list += [p.mail_sender for p in group.announcement_recipients if p.email]
+
+        send_templated_mail(
+            template_name="data_checks",
+            from_email=get_site_preferences()["mail__address"],
+            recipient_list=recipient_list,
+            context={"results": results_with_checks},
+        )
+
+        logging.info("Sent notification email because of unsent data checks")
+
+        results.update(sent=True)
diff --git a/aleksis/core/health_checks.py b/aleksis/core/health_checks.py
new file mode 100644
index 0000000000000000000000000000000000000000..e3239087a17e5fed6c59441e9c6a219e86deb006
--- /dev/null
+++ b/aleksis/core/health_checks.py
@@ -0,0 +1,18 @@
+from django.utils.translation import gettext as _
+
+from health_check.backends import BaseHealthCheckBackend
+
+from aleksis.core.models import DataCheckResult
+
+
+class DataChecksHealthCheckBackend(BaseHealthCheckBackend):
+    """Checks whether there are unresolved data problems."""
+
+    critical_service = False
+
+    def check_status(self):
+        if DataCheckResult.objects.filter(solved=False).exists():
+            self.add_error(_("There are unresolved data problems."))
+
+    def identifier(self):
+        return self.__class__.__name__
diff --git a/aleksis/core/locale/ar/LC_MESSAGES/django.po b/aleksis/core/locale/ar/LC_MESSAGES/django.po
index a3e781c6b389c7e3c6814fe9491358e6810b1b41..26513bbf79d22e23b2c3f8f90b93b5474034a972 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: 2020-08-02 16:29+0200\n"
+"POT-Creation-Date: 2021-01-11 21:30+0100\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -18,6 +18,15 @@ 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"
 
+#: data_checks.py:53
+msgid "Ignore problem"
+msgstr ""
+
+#: data_checks.py:174
+#, python-brace-format
+msgid "Solve option '{solve_option_obj.verbose_name}' "
+msgstr ""
+
 #: filters.py:37 templates/core/base.html:77 templates/core/group/list.html:20
 #: templates/core/person/list.html:24 templates/search/search.html:7
 #: templates/search/search.html:22
@@ -32,92 +41,96 @@ msgstr ""
 msgid "Search by contact details"
 msgstr ""
 
-#: forms.py:46
+#: forms.py:54
 msgid "You cannot set a new username when also selecting an existing user."
 msgstr ""
 
-#: forms.py:50
+#: forms.py:58
 msgid "This username is already in use."
 msgstr ""
 
-#: forms.py:74
+#: forms.py:82
 msgid "Base data"
 msgstr ""
 
-#: forms.py:80
+#: forms.py:88
 msgid "Address"
 msgstr ""
 
-#: forms.py:81
+#: forms.py:89
 msgid "Contact data"
 msgstr ""
 
-#: forms.py:83
+#: forms.py:91
 msgid "Advanced personal data"
 msgstr ""
 
-#: forms.py:114
+#: forms.py:134
 msgid "New user"
 msgstr ""
 
-#: forms.py:114
+#: forms.py:134
 msgid "Create a new account"
 msgstr ""
 
-#: forms.py:126 models.py:91
+#: forms.py:146 models.py:102
 msgid "School term"
 msgstr ""
 
-#: forms.py:127
+#: forms.py:147
 msgid "Common data"
 msgstr ""
 
-#: forms.py:128 forms.py:170 menus.py:152 models.py:105
+#: forms.py:148 forms.py:197 menus.py:169 models.py:116
 #: templates/core/person/list.html:8 templates/core/person/list.html:9
 msgid "Persons"
 msgstr ""
 
-#: forms.py:129
+#: forms.py:149
 msgid "Additional data"
 msgstr ""
 
-#: forms.py:163 forms.py:166 models.py:35
+#: forms.py:189 forms.py:192 models.py:45
 msgid "Date"
 msgstr ""
 
-#: forms.py:164 forms.py:167 models.py:43
+#: forms.py:190 forms.py:193 models.py:53
 msgid "Time"
 msgstr ""
 
-#: forms.py:172 menus.py:160 models.py:319 templates/core/group/list.html:8
-#: templates/core/group/list.html:9 templates/core/person/full.html:136
+#: forms.py:210 menus.py:177 models.py:338 templates/core/group/list.html:8
+#: templates/core/group/list.html:9 templates/core/person/full.html:144
 msgid "Groups"
 msgstr ""
 
-#: forms.py:176
+#: forms.py:220
 msgid "From when until when should the announcement be displayed?"
 msgstr ""
 
-#: forms.py:179
+#: forms.py:223
 msgid "Who should see the announcement?"
 msgstr ""
 
-#: forms.py:180
+#: forms.py:224
 msgid "Write your announcement:"
 msgstr ""
 
-#: forms.py:219
+#: forms.py:263
 msgid "You are not allowed to create announcements which are only valid in the past."
 msgstr ""
 
-#: forms.py:223
+#: forms.py:267
 msgid "The from date and time must be earlier then the until date and time."
 msgstr ""
 
-#: forms.py:232
+#: forms.py:276
 msgid "You need at least one recipient."
 msgstr ""
 
+#: health_checks.py:15
+msgid "There are unresolved data problems."
+msgstr ""
+
 #: menus.py:7 templates/two_factor/core/login.html:6
 #: templates/two_factor/core/login.html:10
 #: templates/two_factor/core/login.html:86
@@ -156,539 +169,657 @@ msgstr ""
 msgid "Admin"
 msgstr ""
 
-#: menus.py:75 models.py:564 templates/core/announcement/list.html:7
+#: menus.py:75 models.py:602 templates/core/announcement/list.html:7
 #: templates/core/announcement/list.html:8
 msgid "Announcements"
 msgstr ""
 
-#: menus.py:86 models.py:92 templates/core/school_term/list.html:8
+#: menus.py:86 models.py:103 templates/core/school_term/list.html:8
 #: templates/core/school_term/list.html:9
 msgid "School terms"
 msgstr ""
 
-#: menus.py:97 templates/core/management/data_management.html:6
+#: menus.py:97 templates/core/dashboard_widget/list.html:8
+#: templates/core/dashboard_widget/list.html:9
+msgid "Dashboard widgets"
+msgstr ""
+
+#: menus.py:108 templates/core/management/data_management.html:6
 #: templates/core/management/data_management.html:7
 msgid "Data management"
 msgstr ""
 
-#: menus.py:105 templates/core/pages/system_status.html:5
+#: menus.py:116 templates/core/pages/system_status.html:5
 #: templates/core/pages/system_status.html:7
 msgid "System status"
 msgstr ""
 
-#: menus.py:116
+#: menus.py:127
 msgid "Impersonation"
 msgstr ""
 
-#: menus.py:124
+#: menus.py:135
 msgid "Configuration"
 msgstr ""
 
-#: menus.py:135
+#: menus.py:146 templates/core/data_check/list.html:9
+#: templates/core/data_check/list.html:10
+msgid "Data checks"
+msgstr ""
+
+#: menus.py:152
 msgid "Backend Admin"
 msgstr ""
 
-#: menus.py:143
+#: menus.py:160
 msgid "People"
 msgstr ""
 
-#: menus.py:168 models.py:727 templates/core/group_type/list.html:8
+#: menus.py:185 models.py:812 templates/core/group_type/list.html:8
 #: templates/core/group_type/list.html:9
 msgid "Group types"
 msgstr ""
 
-#: menus.py:179
+#: menus.py:196
 msgid "Persons and accounts"
 msgstr ""
 
-#: menus.py:190
+#: menus.py:207
 msgid "Groups and child groups"
 msgstr ""
 
-#: menus.py:201 models.py:363 templates/core/additional_field/list.html:8
+#: menus.py:218 models.py:385 templates/core/additional_field/list.html:8
 #: templates/core/additional_field/list.html:9
 msgid "Additional fields"
 msgstr ""
 
-#: menus.py:216 templates/core/group/child_groups.html:7
+#: menus.py:233 templates/core/group/child_groups.html:7
 #: templates/core/group/child_groups.html:9
 msgid "Assign child groups to groups"
 msgstr ""
 
-#: mixins.py:406
+#: mixins.py:384
 msgid "Linked school term"
 msgstr ""
 
-#: models.py:33
+#: models.py:43
 msgid "Boolean (Yes/No)"
 msgstr ""
 
-#: models.py:34
+#: models.py:44
 msgid "Text (one line)"
 msgstr ""
 
-#: models.py:36
+#: models.py:46
 msgid "Date and time"
 msgstr ""
 
-#: models.py:37
+#: models.py:47
 msgid "Decimal number"
 msgstr ""
 
-#: models.py:38 models.py:146
+#: models.py:48 models.py:157
 msgid "E-mail address"
 msgstr ""
 
-#: models.py:39
+#: models.py:49
 msgid "Integer"
 msgstr ""
 
-#: models.py:40
+#: models.py:50
 msgid "IP address"
 msgstr ""
 
-#: models.py:41
+#: models.py:51
 msgid "Boolean or empty (Yes/No/Neither)"
 msgstr ""
 
-#: models.py:42
+#: models.py:52
 msgid "Text (multi-line)"
 msgstr ""
 
-#: models.py:44
+#: models.py:54
 msgid "URL / Link"
 msgstr ""
 
-#: models.py:56 models.py:700
+#: models.py:66 models.py:785
 msgid "Name"
 msgstr ""
 
-#: models.py:58
+#: models.py:68
 msgid "Start date"
 msgstr ""
 
-#: models.py:59
+#: models.py:69
 msgid "End date"
 msgstr ""
 
-#: models.py:77
+#: models.py:88
 msgid "The start date must be earlier than the end date."
 msgstr ""
 
-#: models.py:84
+#: models.py:95
 msgid "There is already a school term for this time or a part of this time."
 msgstr ""
 
-#: models.py:104 templates/core/person/accounts.html:36
+#: models.py:115 models.py:744 templates/core/person/accounts.html:41
 msgid "Person"
 msgstr ""
 
-#: models.py:107
+#: models.py:118
 msgid "Can view address"
 msgstr ""
 
-#: models.py:108
+#: models.py:119
 msgid "Can view contact details"
 msgstr ""
 
-#: models.py:109
+#: models.py:120
 msgid "Can view photo"
 msgstr ""
 
-#: models.py:110
+#: models.py:121
 msgid "Can view persons groups"
 msgstr ""
 
-#: models.py:111
+#: models.py:122
 msgid "Can view personal details"
 msgstr ""
 
-#: models.py:116
+#: models.py:127
 msgid "female"
 msgstr ""
 
-#: models.py:116
+#: models.py:127
 msgid "male"
 msgstr ""
 
-#: models.py:124
+#: models.py:135
 msgid "Linked user"
 msgstr ""
 
-#: models.py:126
+#: models.py:137
 msgid "Is person active?"
 msgstr ""
 
-#: models.py:128
+#: models.py:139
 msgid "First name"
 msgstr ""
 
-#: models.py:129
+#: models.py:140
 msgid "Last name"
 msgstr ""
 
-#: models.py:131
+#: models.py:142
 msgid "Additional name(s)"
 msgstr ""
 
-#: models.py:135 models.py:332
+#: models.py:146 models.py:354
 msgid "Short name"
 msgstr ""
 
-#: models.py:138
+#: models.py:149
 msgid "Street"
 msgstr ""
 
-#: models.py:139
+#: models.py:150
 msgid "Street number"
 msgstr ""
 
-#: models.py:140
+#: models.py:151
 msgid "Postal code"
 msgstr ""
 
-#: models.py:141
+#: models.py:152
 msgid "Place"
 msgstr ""
 
-#: models.py:143
+#: models.py:154
 msgid "Home phone"
 msgstr ""
 
-#: models.py:144
+#: models.py:155
 msgid "Mobile phone"
 msgstr ""
 
-#: models.py:148
+#: models.py:159
 msgid "Date of birth"
 msgstr ""
 
-#: models.py:149
+#: models.py:160
 msgid "Sex"
 msgstr ""
 
-#: models.py:151
+#: models.py:162
 msgid "Photo"
 msgstr ""
 
-#: models.py:155 templates/core/person/full.html:129
+#: models.py:166 templates/core/person/full.html:137
 msgid "Guardians / Parents"
 msgstr ""
 
-#: models.py:162
+#: models.py:173
 msgid "Primary group"
 msgstr ""
 
-#: models.py:165 models.py:423 models.py:447 models.py:532 models.py:720
-#: templates/core/person/full.html:112
+#: models.py:176 models.py:461 models.py:485 models.py:570 models.py:805
+#: templates/core/person/full.html:120
 msgid "Description"
 msgstr ""
 
-#: models.py:296
+#: models.py:313
 msgid "Title of field"
 msgstr ""
 
-#: models.py:298
+#: models.py:315
 msgid "Type of field"
 msgstr ""
 
-#: models.py:305
+#: models.py:322
 msgid "Addtitional field for groups"
 msgstr ""
 
-#: models.py:306
+#: models.py:323
 msgid "Addtitional fields for groups"
 msgstr ""
 
-#: models.py:318
+#: models.py:337
 msgid "Group"
 msgstr ""
 
-#: models.py:320
+#: models.py:340
 msgid "Can assign child groups to groups"
 msgstr ""
 
-#: models.py:330
+#: models.py:341
+msgid "Can view statistics about group."
+msgstr ""
+
+#: models.py:352
 msgid "Long name"
 msgstr ""
 
-#: models.py:340 templates/core/group/full.html:65
+#: models.py:362 templates/core/group/full.html:85
 msgid "Members"
 msgstr ""
 
-#: models.py:343 templates/core/group/full.html:62
+#: models.py:365 templates/core/group/full.html:82
 msgid "Owners"
 msgstr ""
 
-#: models.py:350 templates/core/group/full.html:54
+#: models.py:372 templates/core/group/full.html:55
 msgid "Parent groups"
 msgstr ""
 
-#: models.py:358
+#: models.py:380
 msgid "Type of group"
 msgstr ""
 
-#: models.py:419
+#: models.py:457
 msgid "User"
 msgstr ""
 
-#: models.py:422 models.py:446 models.py:531
+#: models.py:460 models.py:484 models.py:569
 #: templates/core/announcement/list.html:18
 msgid "Title"
 msgstr ""
 
-#: models.py:425
+#: models.py:463
 msgid "Application"
 msgstr ""
 
-#: models.py:431
+#: models.py:469
 msgid "Activity"
 msgstr ""
 
-#: models.py:432
+#: models.py:470
 msgid "Activities"
 msgstr ""
 
-#: models.py:438
+#: models.py:476
 msgid "Sender"
 msgstr ""
 
-#: models.py:443
+#: models.py:481
 msgid "Recipient"
 msgstr ""
 
-#: models.py:448 models.py:701
+#: models.py:486 models.py:786
 msgid "Link"
 msgstr ""
 
-#: models.py:450
+#: models.py:488
 msgid "Read"
 msgstr ""
 
-#: models.py:451
+#: models.py:489
 msgid "Sent"
 msgstr ""
 
-#: models.py:464
+#: models.py:502
 msgid "Notification"
 msgstr ""
 
-#: models.py:465
+#: models.py:503
 msgid "Notifications"
 msgstr ""
 
-#: models.py:533
+#: models.py:571
 msgid "Link to detailed view"
 msgstr ""
 
-#: models.py:536
+#: models.py:574
 msgid "Date and time from when to show"
 msgstr ""
 
-#: models.py:539
+#: models.py:577
 msgid "Date and time until when to show"
 msgstr ""
 
-#: models.py:563
+#: models.py:601
 msgid "Announcement"
 msgstr ""
 
-#: models.py:601
+#: models.py:639
 msgid "Announcement recipient"
 msgstr ""
 
-#: models.py:602
+#: models.py:640
 msgid "Announcement recipients"
 msgstr ""
 
-#: models.py:652
+#: models.py:690
 msgid "Widget Title"
 msgstr ""
 
-#: models.py:653
+#: models.py:691
 msgid "Activate Widget"
 msgstr ""
 
-#: models.py:671
+#: models.py:694
+msgid "Size on mobile devices"
+msgstr ""
+
+#: models.py:695
+msgid "<= 600 px, 12 columns"
+msgstr ""
+
+#: models.py:700
+msgid "Size on tablet devices"
+msgstr ""
+
+#: models.py:701
+msgid "> 600 px, 12 columns"
+msgstr ""
+
+#: models.py:706
+msgid "Size on desktop devices"
+msgstr ""
+
+#: models.py:707
+msgid "> 992 px, 12 columns"
+msgstr ""
+
+#: models.py:712
+msgid "Size on large desktop devices"
+msgstr ""
+
+#: models.py:713
+msgid "> 1200 px>, 12 columns"
+msgstr ""
+
+#: models.py:734
+msgid "Can edit default dashboard"
+msgstr ""
+
+#: models.py:735
 msgid "Dashboard Widget"
 msgstr ""
 
-#: models.py:672
+#: models.py:736
 msgid "Dashboard Widgets"
 msgstr ""
 
-#: models.py:678
+#: models.py:741
+msgid "Dashboard widget"
+msgstr ""
+
+#: models.py:746
+msgid "Order"
+msgstr ""
+
+#: models.py:747
+msgid "Part of the default dashboard"
+msgstr ""
+
+#: models.py:755
+msgid "Dashboard widget order"
+msgstr ""
+
+#: models.py:756
+msgid "Dashboard widget orders"
+msgstr ""
+
+#: models.py:762
 msgid "Menu ID"
 msgstr ""
 
-#: models.py:690
+#: models.py:775
 msgid "Custom menu"
 msgstr ""
 
-#: models.py:691
+#: models.py:776
 msgid "Custom menus"
 msgstr ""
 
-#: models.py:698
+#: models.py:783
 msgid "Menu"
 msgstr ""
 
-#: models.py:702
+#: models.py:787
 msgid "Icon"
 msgstr ""
 
-#: models.py:708
+#: models.py:793
 msgid "Custom menu item"
 msgstr ""
 
-#: models.py:709
+#: models.py:794
 msgid "Custom menu items"
 msgstr ""
 
-#: models.py:719
+#: models.py:804
 msgid "Title of type"
 msgstr ""
 
-#: models.py:726 templates/core/group/full.html:46
+#: models.py:811 templates/core/group/full.html:47
 msgid "Group type"
 msgstr ""
 
-#: models.py:736
+#: models.py:821
 msgid "Can view system status"
 msgstr ""
 
-#: models.py:737
+#: models.py:822
 msgid "Can link persons to accounts"
 msgstr ""
 
-#: models.py:738
+#: models.py:823
 msgid "Can manage data"
 msgstr ""
 
-#: models.py:739
+#: models.py:824
 msgid "Can impersonate"
 msgstr ""
 
-#: models.py:740
+#: models.py:825
 msgid "Can use search"
 msgstr ""
 
-#: models.py:741
+#: models.py:826
 msgid "Can change site preferences"
 msgstr ""
 
-#: models.py:742
+#: models.py:827
 msgid "Can change person preferences"
 msgstr ""
 
-#: models.py:743
+#: models.py:828
 msgid "Can change group preferences"
 msgstr ""
 
-#: preferences.py:24
+#: models.py:864
+msgid "Related data check task"
+msgstr ""
+
+#: models.py:872
+msgid "Issue solved"
+msgstr ""
+
+#: models.py:873
+msgid "Notification sent"
+msgstr ""
+
+#: models.py:886
+msgid "Data check result"
+msgstr ""
+
+#: models.py:887
+msgid "Data check results"
+msgstr ""
+
+#: models.py:889
+msgid "Can run data checks"
+msgstr ""
+
+#: models.py:890
+msgid "Can solve data check problems"
+msgstr ""
+
+#: preferences.py:27
 msgid "Authentication"
 msgstr ""
 
-#: preferences.py:33
+#: preferences.py:28
+msgid "Internationalisation"
+msgstr ""
+
+#: preferences.py:37
 msgid "Site title"
 msgstr ""
 
-#: preferences.py:42
+#: preferences.py:46
 msgid "Site description"
 msgstr ""
 
-#: preferences.py:51
+#: preferences.py:55
 msgid "Primary colour"
 msgstr ""
 
-#: preferences.py:60
+#: preferences.py:64
 msgid "Secondary colour"
 msgstr ""
 
-#: preferences.py:68
+#: preferences.py:72
 msgid "Logo"
 msgstr ""
 
-#: preferences.py:76
+#: preferences.py:80
 msgid "Favicon"
 msgstr ""
 
-#: preferences.py:84
+#: preferences.py:88
 msgid "PWA-Icon"
 msgstr ""
 
-#: preferences.py:93
+#: preferences.py:97
 msgid "Mail out name"
 msgstr ""
 
-#: preferences.py:102
+#: preferences.py:106
 msgid "Mail out address"
 msgstr ""
 
-#: preferences.py:112
+#: preferences.py:116
 msgid "Link to privacy policy"
 msgstr ""
 
-#: preferences.py:122
+#: preferences.py:126
 msgid "Link to imprint"
 msgstr ""
 
-#: preferences.py:132
+#: preferences.py:136
 msgid "Name format for addressing"
 msgstr ""
 
-#: preferences.py:146
+#: preferences.py:150
 msgid "Channels to use for notifications"
 msgstr ""
 
-#: preferences.py:156
+#: preferences.py:160
 msgid "Regular expression to match primary group, e.g. '^Class .*'"
 msgstr ""
 
-#: preferences.py:165
+#: preferences.py:169
 msgid "Field on person to match primary group against"
 msgstr ""
 
-#: preferences.py:177
+#: preferences.py:181
 msgid "Display name of the school"
 msgstr ""
 
-#: preferences.py:186
+#: preferences.py:190
 msgid "Official name of the school, e.g. as given by supervisory authority"
 msgstr ""
 
-#: preferences.py:194
+#: preferences.py:198
 msgid "Enabled custom authentication backends"
 msgstr ""
 
-#: settings.py:300
+#: preferences.py:211
+msgid "Available languages"
+msgstr ""
+
+#: preferences.py:223
+msgid "Send emails if data checks detect problems"
+msgstr ""
+
+#: preferences.py:234
+msgid "Email recipients for data checks problem emails"
+msgstr ""
+
+#: preferences.py:245
+msgid "Email recipient groups for data checks problem emails"
+msgstr ""
+
+#: settings.py:322
 msgid "English"
 msgstr ""
 
-#: settings.py:301
+#: settings.py:323
 msgid "German"
 msgstr ""
 
-#: settings.py:302
+#: settings.py:324
 msgid "French"
 msgstr ""
 
-#: settings.py:303
+#: settings.py:325
 msgid "Norwegian (bokmål)"
 msgstr ""
 
 #: tables.py:19 templates/core/announcement/list.html:36
-#: templates/core/group/full.html:23 templates/core/person/full.html:22
+#: templates/core/group/full.html:24 templates/core/person/full.html:23
 msgid "Edit"
 msgstr ""
 
-#: tables.py:21 templates/core/announcement/list.html:22
+#: tables.py:21 tables.py:89 templates/core/announcement/list.html:22
 msgid "Actions"
 msgstr ""
 
-#: tables.py:56 tables.py:57 tables.py:71
-#: templates/core/announcement/list.html:42 templates/core/group/full.html:30
-#: templates/core/pages/delete.html:22 templates/core/person/full.html:29
+#: tables.py:56 tables.py:57 tables.py:71 tables.py:87
+#: templates/core/announcement/list.html:42 templates/core/group/full.html:31
+#: templates/core/pages/delete.html:22 templates/core/person/full.html:30
 msgid "Delete"
 msgstr ""
 
@@ -760,21 +891,21 @@ msgstr ""
 msgid "Create additional field"
 msgstr ""
 
-#: templates/core/announcement/form.html:10
-#: templates/core/announcement/form.html:17
+#: templates/core/announcement/form.html:14
+#: templates/core/announcement/form.html:21
 msgid "Edit announcement"
 msgstr ""
 
-#: templates/core/announcement/form.html:12
+#: templates/core/announcement/form.html:16
 msgid "Publish announcement"
 msgstr ""
 
-#: templates/core/announcement/form.html:19
+#: templates/core/announcement/form.html:23
 #: templates/core/announcement/list.html:13
 msgid "Publish new announcement"
 msgstr ""
 
-#: templates/core/announcement/form.html:30
+#: templates/core/announcement/form.html:34
 msgid "Save und publish announcement"
 msgstr ""
 
@@ -814,6 +945,120 @@ msgstr ""
 msgid "Powered by AlekSIS"
 msgstr ""
 
+#: templates/core/dashboard_widget/create.html:8
+#: templates/core/dashboard_widget/create.html:12
+#, python-format
+msgid "Create %(widget)s"
+msgstr ""
+
+#: templates/core/dashboard_widget/edit.html:8
+#: templates/core/dashboard_widget/edit.html:12
+#, python-format
+msgid "Edit %(widget)s"
+msgstr ""
+
+#: templates/core/dashboard_widget/list.html:17
+#, python-format
+msgid "Create %(name)s"
+msgstr ""
+
+#: templates/core/dashboard_widget/list.html:25
+#: templates/core/edit_dashboard.html:8 templates/core/edit_dashboard.html:15
+msgid "Edit default dashboard"
+msgstr ""
+
+#: templates/core/data_check/list.html:15
+msgid "Check data again"
+msgstr ""
+
+#: templates/core/data_check/list.html:22
+msgid "The system detected some problems with your data."
+msgstr ""
+
+#: templates/core/data_check/list.html:23
+msgid ""
+"Please go through all data and check whether some extra action is\n"
+"          needed."
+msgstr ""
+
+#: templates/core/data_check/list.html:31
+msgid "Everything is fine."
+msgstr ""
+
+#: templates/core/data_check/list.html:32
+msgid "The system hasn't detected any problems with your data."
+msgstr ""
+
+#: templates/core/data_check/list.html:40
+msgid "Detected problems"
+msgstr ""
+
+#: templates/core/data_check/list.html:45
+msgid "Affected object"
+msgstr ""
+
+#: templates/core/data_check/list.html:46
+msgid "Detected problem"
+msgstr ""
+
+#: templates/core/data_check/list.html:47
+msgid "Show details"
+msgstr ""
+
+#: templates/core/data_check/list.html:48
+msgid "Options to solve the problem"
+msgstr ""
+
+#: templates/core/data_check/list.html:62
+msgid "Show object"
+msgstr ""
+
+#: templates/core/data_check/list.html:84
+msgid "Registered checks"
+msgstr ""
+
+#: templates/core/data_check/list.html:88
+msgid ""
+"\n"
+"            The system will check for the following problems:\n"
+"          "
+msgstr ""
+
+#: templates/core/edit_dashboard.html:6 templates/core/edit_dashboard.html:13
+#: templates/core/index.html:14
+msgid "Edit dashboard"
+msgstr ""
+
+#: templates/core/edit_dashboard.html:24
+msgid ""
+"\n"
+"          On this page you can arrange your personal dashboard. You can drag any items from \"Available widgets\" to \"Your\n"
+"          Dashboard\" or change the order by moving the widgets. After you have finished, please don't forget to click on\n"
+"          \"Save\".\n"
+"        "
+msgstr ""
+
+#: templates/core/edit_dashboard.html:30
+msgid ""
+"\n"
+"          On this page you can arrange the default dashboard which is shown when a user doesn't arrange his own\n"
+"          dashboard. You can drag any items from \"Available widgets\" to \"Default Dashboard\" or change the order\n"
+"          by moving the widgets. After you have finished, please don't forget to click on \"Save\".\n"
+"        "
+msgstr ""
+
+#: templates/core/edit_dashboard.html:48
+msgid "Available widgets"
+msgstr ""
+
+#: templates/core/edit_dashboard.html:57
+msgid "Your dashboard"
+msgstr ""
+
+#: templates/core/edit_dashboard.html:59
+msgid "Default dashboard"
+msgstr ""
+
 #: templates/core/group/child_groups.html:18
 msgid ""
 "\n"
@@ -886,14 +1131,38 @@ msgstr ""
 msgid "Save and next"
 msgstr ""
 
-#: templates/core/group/edit.html:6 templates/core/group/edit.html:7
+#: templates/core/group/edit.html:11 templates/core/group/edit.html:12
 msgid "Edit group"
 msgstr ""
 
-#: templates/core/group/full.html:37 templates/core/person/full.html:36
+#: templates/core/group/full.html:38 templates/core/person/full.html:37
 msgid "Change preferences"
 msgstr ""
 
+#: templates/core/group/full.html:64
+msgid "Statistics"
+msgstr ""
+
+#: templates/core/group/full.html:67
+msgid "Count of members"
+msgstr ""
+
+#: templates/core/group/full.html:71
+msgid "Average age"
+msgstr ""
+
+#: templates/core/group/full.html:76
+msgid "Age range"
+msgstr ""
+
+#: templates/core/group/full.html:76
+msgid "years to"
+msgstr ""
+
+#: templates/core/group/full.html:76
+msgid "years "
+msgstr ""
+
 #: templates/core/group/list.html:14
 msgid "Create group"
 msgstr ""
@@ -922,23 +1191,31 @@ msgstr ""
 msgid "Home"
 msgstr ""
 
-#: templates/core/index.html:42
+#: templates/core/index.html:50
+msgid ""
+"\n"
+"          You didn't customise your dashboard so that you see the system default. Please click on \"Edit dashboard\" to\n"
+"          customise your personal dashboard.\n"
+"        "
+msgstr ""
+
+#: templates/core/index.html:59
 msgid "Last activities"
 msgstr ""
 
-#: templates/core/index.html:60
+#: templates/core/index.html:77
 msgid "No activities available yet."
 msgstr ""
 
-#: templates/core/index.html:65
+#: templates/core/index.html:82
 msgid "Recent notifications"
 msgstr ""
 
-#: templates/core/index.html:81
+#: templates/core/index.html:98
 msgid "More information →"
 msgstr ""
 
-#: templates/core/index.html:88
+#: templates/core/index.html:105
 msgid "No notifications available yet."
 msgstr ""
 
@@ -1017,21 +1294,6 @@ msgid ""
 "    "
 msgstr ""
 
-#: templates/core/pages/offline.html:6
-msgid ""
-"No internet\n"
-"    connection."
-msgstr ""
-
-#: templates/core/pages/offline.html:10
-msgid ""
-"\n"
-"      There was an error accessing this page. You probably don't have an internet connection. Check to see if your WiFi\n"
-"      or mobile data is turned on and try again. If you think you are connected, please contact the system\n"
-"      administrators:\n"
-"    "
-msgstr ""
-
 #: templates/core/pages/progress.html:27
 msgid ""
 "\n"
@@ -1151,37 +1413,19 @@ msgid ""
 "            "
 msgstr ""
 
-#: templates/core/partials/crud_events.html:10
-#, python-format
-msgid ""
-"\n"
-"              Created by %(person)s\n"
-"            "
-msgstr ""
-
-#: templates/core/partials/crud_events.html:14
-#: templates/core/partials/crud_events.html:22
-#: templates/core/partials/crud_events.html:26
-#, python-format
-msgid ""
-"\n"
-"              Updated by %(person)s\n"
-"            "
+#: templates/core/partials/crud_events.html:15
+msgid "Changed by"
 msgstr ""
 
-#: templates/core/partials/crud_events.html:18
-#, python-format
-msgid ""
-"\n"
-"              Deleted by %(person)s\n"
-"            "
+#: templates/core/partials/crud_events.html:15
+msgid "Unknown"
 msgstr ""
 
-#: templates/core/partials/language_form.html:16
+#: templates/core/partials/language_form.html:15
 msgid "Language"
 msgstr ""
 
-#: templates/core/partials/language_form.html:28
+#: templates/core/partials/language_form.html:27
 msgid "Select language"
 msgstr ""
 
@@ -1202,11 +1446,12 @@ msgid ""
 "          "
 msgstr ""
 
-#: templates/core/person/accounts.html:7 templates/core/person/accounts.html:9
+#: templates/core/person/accounts.html:12
+#: templates/core/person/accounts.html:14
 msgid "Link persons to accounts"
 msgstr ""
 
-#: templates/core/person/accounts.html:16
+#: templates/core/person/accounts.html:21
 msgid ""
 "\n"
 "        You can use this form to assign user accounts to persons. Use the\n"
@@ -1216,28 +1461,32 @@ msgid ""
 "      "
 msgstr ""
 
-#: templates/core/person/accounts.html:31
-#: templates/core/person/accounts.html:55
+#: templates/core/person/accounts.html:36
+#: templates/core/person/accounts.html:60
 msgid "Update"
 msgstr ""
 
-#: templates/core/person/accounts.html:37
+#: templates/core/person/accounts.html:42
 msgid "Existing account"
 msgstr ""
 
-#: templates/core/person/accounts.html:38
+#: templates/core/person/accounts.html:43
 msgid "New account"
 msgstr ""
 
-#: templates/core/person/edit.html:11 templates/core/person/edit.html:12
+#: templates/core/person/edit.html:12 templates/core/person/edit.html:13
 msgid "Edit person"
 msgstr ""
 
-#: templates/core/person/full.html:42
+#: templates/core/person/full.html:44
+msgid "Impersonate"
+msgstr ""
+
+#: templates/core/person/full.html:50
 msgid "Contact details"
 msgstr ""
 
-#: templates/core/person/full.html:122
+#: templates/core/person/full.html:130
 msgid "Children"
 msgstr ""
 
@@ -1281,14 +1530,29 @@ msgstr ""
 msgid "Save preferences"
 msgstr ""
 
-#: templates/dynamic_preferences/sections.html:7
-msgid "All"
-msgstr ""
-
 #: templates/impersonate/list_users.html:8
 msgid "Impersonate user"
 msgstr ""
 
+#: templates/offline.html:5
+msgid "Network error"
+msgstr ""
+
+#: templates/offline.html:8
+msgid ""
+"No internet\n"
+"    connection."
+msgstr ""
+
+#: templates/offline.html:12
+msgid ""
+"\n"
+"      There was an error accessing this page. You probably don't have an internet connection. Check to see if your WiFi\n"
+"      or mobile data is turned on and try again. If you think you are connected, please contact the system\n"
+"      administrators:\n"
+"    "
+msgstr ""
+
 #: templates/search/search.html:8
 msgid "Global Search"
 msgstr ""
@@ -1309,6 +1573,39 @@ msgstr ""
 msgid "Please enter a search term above."
 msgstr ""
 
+#: templates/templated_email/data_checks.email:4
+msgid "The system detected some new problems with your data."
+msgstr ""
+
+#: templates/templated_email/data_checks.email:8
+#: templates/templated_email/data_checks.email:24
+msgid "Hello,"
+msgstr ""
+
+#: templates/templated_email/data_checks.email:10
+msgid ""
+"\n"
+"  the system detected some new problems with your data.\n"
+"  Please take some time to inspect them and solve the issues or mark them as ignored.\n"
+" "
+msgstr ""
+
+#: templates/templated_email/data_checks.email:26
+msgid ""
+"\n"
+"   the system detected some new problems with your data.\n"
+"   Please take some time to inspect them and solve the issues or mark them as ignored.\n"
+"  "
+msgstr ""
+
+#: templates/templated_email/data_checks.email:34
+msgid "Problem description"
+msgstr ""
+
+#: templates/templated_email/data_checks.email:35
+msgid "Count of objects with new problems"
+msgstr ""
+
 #: templates/templated_email/notification.email:3
 msgid "New notification for"
 msgstr ""
@@ -1695,58 +1992,91 @@ msgstr ""
 msgid "SMS"
 msgstr ""
 
-#: views.py:122
+#: views.py:141
 msgid "The school term has been created."
 msgstr ""
 
-#: views.py:133
+#: views.py:153
 msgid "The school term has been saved."
 msgstr ""
 
-#: views.py:273
+#: views.py:298
 msgid "The child groups were successfully saved."
 msgstr ""
 
-#: views.py:309
+#: views.py:336
 msgid "The person has been saved."
 msgstr ""
 
-#: views.py:346
+#: views.py:375
 msgid "The group has been saved."
 msgstr ""
 
-#: views.py:434
+#: views.py:467
 msgid "The announcement has been saved."
 msgstr ""
 
-#: views.py:450
+#: views.py:483
 msgid "The announcement has been deleted."
 msgstr ""
 
-#: views.py:521
+#: views.py:562
 msgid "The preferences have been saved successfully."
 msgstr ""
 
-#: views.py:544
+#: views.py:586
 msgid "The person has been deleted."
 msgstr ""
 
-#: views.py:557
+#: views.py:600
 msgid "The group has been deleted."
 msgstr ""
 
-#: views.py:588
+#: views.py:632
 msgid "The additional_field has been saved."
 msgstr ""
 
-#: views.py:622
+#: views.py:666
 msgid "The additional field has been deleted."
 msgstr ""
 
-#: views.py:646
+#: views.py:691
 msgid "The group type has been saved."
 msgstr ""
 
-#: views.py:676
+#: views.py:721
 msgid "The group type has been deleted."
 msgstr ""
+
+#: views.py:749
+msgid "The data check has been started. Please note that it may take a while before you are able to fetch the data on this page."
+msgstr ""
+
+#: views.py:754
+msgid "The data check has finished."
+msgstr ""
+
+#: views.py:769
+#, python-brace-format
+msgid "The solve option '{solve_option_obj.verbose_name}' "
+msgstr ""
+
+#: views.py:811
+msgid "The dashboard widget has been saved."
+msgstr ""
+
+#: views.py:841
+msgid "The dashboard widget has been created."
+msgstr ""
+
+#: views.py:851
+msgid "The dashboard widget has been deleted."
+msgstr ""
+
+#: views.py:914
+msgid "Your dashboard configuration has been saved successfully."
+msgstr ""
+
+#: views.py:916
+msgid "The configuration of the default dashboard has been saved successfully."
+msgstr ""
diff --git a/aleksis/core/locale/ar/LC_MESSAGES/djangojs.po b/aleksis/core/locale/ar/LC_MESSAGES/djangojs.po
index c48da556b093acc67242995ed684ce8bfa609426..126b0ef841fd5c5732a533ae0604af89fcfb093b 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: 2020-08-02 16:29+0200\n"
+"POT-Creation-Date: 2021-01-11 21:30+0100\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -18,14 +18,18 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=6; plural=n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5;\n"
 
-#: static/js/main.js:21
+#: static/js/main.js:15
 msgid "Today"
 msgstr ""
 
-#: static/js/main.js:22
+#: static/js/main.js:16
 msgid "Cancel"
 msgstr ""
 
-#: static/js/main.js:23
+#: static/js/main.js:17
 msgid "OK"
 msgstr ""
+
+#: static/js/main.js:118
+msgid "This page may contain outdated information since there is no internet connection."
+msgstr ""
diff --git a/aleksis/core/locale/de_DE/LC_MESSAGES/django.po b/aleksis/core/locale/de_DE/LC_MESSAGES/django.po
index 6f6d8fc83f732fbd2abdedbb8f4793e2591c1ca1..f44814ae73c4edaaa27294f5468eb3cb5eb9e44f 100644
--- a/aleksis/core/locale/de_DE/LC_MESSAGES/django.po
+++ b/aleksis/core/locale/de_DE/LC_MESSAGES/django.po
@@ -7,8 +7,8 @@ msgid ""
 msgstr ""
 "Project-Id-Version: AlekSIS (School Information System) 0.1\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2020-08-02 16:29+0200\n"
-"PO-Revision-Date: 2020-12-19 12:57+0000\n"
+"POT-Creation-Date: 2021-01-11 21:30+0100\n"
+"PO-Revision-Date: 2021-01-11 20:42+0000\n"
 "Last-Translator: Jonathan Weth <teckids@jonathanweth.de>\n"
 "Language-Team: German <https://translate.edugit.org/projects/aleksis/aleksis/"
 "de/>\n"
@@ -17,7 +17,16 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=n != 1;\n"
-"X-Generator: Weblate 4.3.2\n"
+"X-Generator: Weblate 4.4\n"
+
+#: data_checks.py:53
+msgid "Ignore problem"
+msgstr "Problem ignorieren"
+
+#: data_checks.py:174
+#, python-brace-format
+msgid "Solve option '{solve_option_obj.verbose_name}' "
+msgstr "Lösungsoption \"{solve_option_obj.verbose_name}\" "
 
 #: filters.py:37 templates/core/base.html:77 templates/core/group/list.html:20
 #: templates/core/person/list.html:24 templates/search/search.html:7
@@ -33,92 +42,96 @@ msgstr "Nach Namen suchen"
 msgid "Search by contact details"
 msgstr "Nach Kontaktdetails suchen"
 
-#: forms.py:46
+#: forms.py:54
 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."
 
-#: forms.py:50
+#: forms.py:58
 msgid "This username is already in use."
 msgstr "Dieser Benutzername wird bereits genutzt."
 
-#: forms.py:74
+#: forms.py:82
 msgid "Base data"
 msgstr "Basisdaten"
 
-#: forms.py:80
+#: forms.py:88
 msgid "Address"
 msgstr "Adresse"
 
-#: forms.py:81
+#: forms.py:89
 msgid "Contact data"
 msgstr "Kontaktdaten"
 
-#: forms.py:83
+#: forms.py:91
 msgid "Advanced personal data"
 msgstr "Zusätzliche persönliche Daten"
 
-#: forms.py:114
+#: forms.py:134
 msgid "New user"
 msgstr "Neuer Benutzer"
 
-#: forms.py:114
+#: forms.py:134
 msgid "Create a new account"
 msgstr "Neues Benutzerkonto erstellen"
 
-#: forms.py:126 models.py:91
+#: forms.py:146 models.py:102
 msgid "School term"
 msgstr "Schuljahr"
 
-#: forms.py:127
+#: forms.py:147
 msgid "Common data"
 msgstr "Allgemeine Daten"
 
-#: forms.py:128 forms.py:170 menus.py:152 models.py:105
+#: forms.py:148 forms.py:197 menus.py:169 models.py:116
 #: templates/core/person/list.html:8 templates/core/person/list.html:9
 msgid "Persons"
 msgstr "Personen"
 
-#: forms.py:129
+#: forms.py:149
 msgid "Additional data"
 msgstr "Zusätzliche Datne"
 
-#: forms.py:163 forms.py:166 models.py:35
+#: forms.py:189 forms.py:192 models.py:45
 msgid "Date"
 msgstr "Datum"
 
-#: forms.py:164 forms.py:167 models.py:43
+#: forms.py:190 forms.py:193 models.py:53
 msgid "Time"
 msgstr "Zeit"
 
-#: forms.py:172 menus.py:160 models.py:319 templates/core/group/list.html:8
-#: templates/core/group/list.html:9 templates/core/person/full.html:136
+#: forms.py:210 menus.py:177 models.py:338 templates/core/group/list.html:8
+#: templates/core/group/list.html:9 templates/core/person/full.html:144
 msgid "Groups"
 msgstr "Gruppen"
 
-#: forms.py:176
+#: forms.py:220
 msgid "From when until when should the announcement be displayed?"
 msgstr "Von wann bis wann soll die Ankündigung angezeigt werden?"
 
-#: forms.py:179
+#: forms.py:223
 msgid "Who should see the announcement?"
 msgstr "Wer soll die Ankündigung sehen?"
 
-#: forms.py:180
+#: forms.py:224
 msgid "Write your announcement:"
 msgstr "Schreiben Sie ihre Ankündigung:"
 
-#: forms.py:219
+#: forms.py:263
 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."
 
-#: forms.py:223
+#: forms.py:267
 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."
 
-#: forms.py:232
+#: forms.py:276
 msgid "You need at least one recipient."
 msgstr "Sie benötigen mindestens einen Empfänger."
 
+#: health_checks.py:15
+msgid "There are unresolved data problems."
+msgstr "Es gibt keine ungelösten Datenprobleme."
+
 #: menus.py:7 templates/two_factor/core/login.html:6
 #: templates/two_factor/core/login.html:10
 #: templates/two_factor/core/login.html:86
@@ -157,540 +170,657 @@ msgstr "Einstellungen"
 msgid "Admin"
 msgstr "Admin"
 
-#: menus.py:75 models.py:564 templates/core/announcement/list.html:7
+#: menus.py:75 models.py:602 templates/core/announcement/list.html:7
 #: templates/core/announcement/list.html:8
 msgid "Announcements"
 msgstr "Ankündigungen"
 
-#: menus.py:86 models.py:92 templates/core/school_term/list.html:8
+#: menus.py:86 models.py:103 templates/core/school_term/list.html:8
 #: templates/core/school_term/list.html:9
 msgid "School terms"
 msgstr "Schuljahre"
 
-#: menus.py:97 templates/core/management/data_management.html:6
+#: menus.py:97 templates/core/dashboard_widget/list.html:8
+#: templates/core/dashboard_widget/list.html:9
+msgid "Dashboard widgets"
+msgstr "Dashboard-Widgets"
+
+#: menus.py:108 templates/core/management/data_management.html:6
 #: templates/core/management/data_management.html:7
 msgid "Data management"
 msgstr "Datenverwaltung"
 
-#: menus.py:105 templates/core/pages/system_status.html:5
+#: menus.py:116 templates/core/pages/system_status.html:5
 #: templates/core/pages/system_status.html:7
 msgid "System status"
 msgstr "Systemstatus"
 
-#: menus.py:116
+#: menus.py:127
 msgid "Impersonation"
 msgstr "Verkleidung"
 
-#: menus.py:124
+#: menus.py:135
 msgid "Configuration"
 msgstr "Konfiguration"
 
-#: menus.py:135
+#: menus.py:146 templates/core/data_check/list.html:9
+#: templates/core/data_check/list.html:10
+msgid "Data checks"
+msgstr "Datenprüfungen"
+
+#: menus.py:152
 msgid "Backend Admin"
 msgstr "Backend-Administration"
 
-#: menus.py:143
+#: menus.py:160
 msgid "People"
 msgstr "Leute"
 
-#: menus.py:168 models.py:727 templates/core/group_type/list.html:8
+#: menus.py:185 models.py:812 templates/core/group_type/list.html:8
 #: templates/core/group_type/list.html:9
 msgid "Group types"
 msgstr "Gruppentypen"
 
-#: menus.py:179
+#: menus.py:196
 msgid "Persons and accounts"
 msgstr "Personen und Konten"
 
-#: menus.py:190
+#: menus.py:207
 msgid "Groups and child groups"
 msgstr "Gruppen und Kindgruppen"
 
-#: menus.py:201 models.py:363 templates/core/additional_field/list.html:8
+#: menus.py:218 models.py:385 templates/core/additional_field/list.html:8
 #: templates/core/additional_field/list.html:9
 msgid "Additional fields"
 msgstr "Zusätzliche Felder"
 
-#: menus.py:216 templates/core/group/child_groups.html:7
+#: menus.py:233 templates/core/group/child_groups.html:7
 #: templates/core/group/child_groups.html:9
 msgid "Assign child groups to groups"
 msgstr "Kindgruppen zu Gruppen zuordnen"
 
-#: mixins.py:406
+#: mixins.py:384
 msgid "Linked school term"
 msgstr "Zugeordnetes Schuljahr"
 
-#: models.py:33
+#: models.py:43
 msgid "Boolean (Yes/No)"
 msgstr "Boolean (Ja/Nein)"
 
-#: models.py:34
+#: models.py:44
 msgid "Text (one line)"
 msgstr "Text (eine Zeile)"
 
-#: models.py:36
+#: models.py:46
 msgid "Date and time"
 msgstr "Datum und Uhrzeit"
 
-#: models.py:37
+#: models.py:47
 msgid "Decimal number"
 msgstr "Dezimalzahl"
 
-#: models.py:38 models.py:146
+#: models.py:48 models.py:157
 msgid "E-mail address"
 msgstr "E-Mail-Adresse"
 
-#: models.py:39
+#: models.py:49
 msgid "Integer"
 msgstr "Ganze Zahl"
 
-#: models.py:40
+#: models.py:50
 msgid "IP address"
 msgstr "IP-Adresse"
 
-#: models.py:41
+#: models.py:51
 msgid "Boolean or empty (Yes/No/Neither)"
 msgstr "Boolean oder leer (Ja/Nein/weder)"
 
-#: models.py:42
+#: models.py:52
 msgid "Text (multi-line)"
 msgstr "Text (mehrzeilig)"
 
-#: models.py:44
+#: models.py:54
 msgid "URL / Link"
 msgstr "URL / Link"
 
-#: models.py:56 models.py:700
+#: models.py:66 models.py:785
 msgid "Name"
 msgstr "Name"
 
-#: models.py:58
+#: models.py:68
 msgid "Start date"
 msgstr "Startdatum"
 
-#: models.py:59
+#: models.py:69
 msgid "End date"
 msgstr "Enddatum"
 
-#: models.py:77
+#: models.py:88
 msgid "The start date must be earlier than the end date."
 msgstr "Das Startdatum muss vor dem Enddatum liegen."
 
-#: models.py:84
+#: models.py:95
 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."
+msgstr "Es gibt bereits ein Schuljahr für diesen Zeitraum oder einen Teilzeitraum."
 
-#: models.py:104 templates/core/person/accounts.html:36
+#: models.py:115 models.py:744 templates/core/person/accounts.html:41
 msgid "Person"
 msgstr "Person"
 
-#: models.py:107
+#: models.py:118
 msgid "Can view address"
 msgstr "Kann Adresse sehen"
 
-#: models.py:108
+#: models.py:119
 msgid "Can view contact details"
 msgstr "Kann Kontaktdetails sehen"
 
-#: models.py:109
+#: models.py:120
 msgid "Can view photo"
 msgstr "Kann Foto sehen"
 
-#: models.py:110
+#: models.py:121
 msgid "Can view persons groups"
 msgstr "Kann Gruppen einer Person sehen"
 
-#: models.py:111
+#: models.py:122
 msgid "Can view personal details"
 msgstr "Kann persönliche Daten sehen"
 
-#: models.py:116
+#: models.py:127
 msgid "female"
 msgstr "weiblich"
 
-#: models.py:116
+#: models.py:127
 msgid "male"
 msgstr "männlich"
 
-#: models.py:124
+#: models.py:135
 msgid "Linked user"
 msgstr "Verknüpfter Benutzer"
 
-#: models.py:126
+#: models.py:137
 msgid "Is person active?"
 msgstr "Ist die Person aktiv?"
 
-#: models.py:128
+#: models.py:139
 msgid "First name"
 msgstr "Vorname"
 
-#: models.py:129
+#: models.py:140
 msgid "Last name"
 msgstr "Nachname"
 
-#: models.py:131
+#: models.py:142
 msgid "Additional name(s)"
 msgstr "Zusätzliche Namen"
 
-#: models.py:135 models.py:332
+#: models.py:146 models.py:354
 msgid "Short name"
 msgstr "Kurzname"
 
-#: models.py:138
+#: models.py:149
 msgid "Street"
 msgstr "Straße"
 
-#: models.py:139
+#: models.py:150
 msgid "Street number"
 msgstr "Hausnummer"
 
-#: models.py:140
+#: models.py:151
 msgid "Postal code"
 msgstr "Postleitzahl"
 
-#: models.py:141
+#: models.py:152
 msgid "Place"
 msgstr "Ort"
 
-#: models.py:143
+#: models.py:154
 msgid "Home phone"
 msgstr "Festnetz"
 
-#: models.py:144
+#: models.py:155
 msgid "Mobile phone"
 msgstr "Handy"
 
-#: models.py:148
+#: models.py:159
 msgid "Date of birth"
 msgstr "Geburtsdatum"
 
-#: models.py:149
+#: models.py:160
 msgid "Sex"
 msgstr "Geschlecht"
 
-#: models.py:151
+#: models.py:162
 msgid "Photo"
 msgstr "Foto"
 
-#: models.py:155 templates/core/person/full.html:129
+#: models.py:166 templates/core/person/full.html:137
 msgid "Guardians / Parents"
 msgstr "Erziehungsberechtigte / Eltern"
 
-#: models.py:162
+#: models.py:173
 msgid "Primary group"
 msgstr "Primärgruppe"
 
-#: models.py:165 models.py:423 models.py:447 models.py:532 models.py:720
-#: templates/core/person/full.html:112
+#: models.py:176 models.py:461 models.py:485 models.py:570 models.py:805
+#: templates/core/person/full.html:120
 msgid "Description"
 msgstr "Beschreibung"
 
-#: models.py:296
+#: models.py:313
 msgid "Title of field"
 msgstr "Feldtitel"
 
-#: models.py:298
+#: models.py:315
 msgid "Type of field"
 msgstr "Feldtyp"
 
-#: models.py:305
+#: models.py:322
 msgid "Addtitional field for groups"
 msgstr "Zusätzliche Felder für Gruppen"
 
-#: models.py:306
+#: models.py:323
 msgid "Addtitional fields for groups"
 msgstr "Zusätzliche Felder für Gruppen"
 
-#: models.py:318
+#: models.py:337
 msgid "Group"
 msgstr "Gruppe"
 
-#: models.py:320
+#: models.py:340
 msgid "Can assign child groups to groups"
 msgstr "Kann Kindgruppen zu Gruppen zuordnen"
 
-#: models.py:330
+#: models.py:341
+msgid "Can view statistics about group."
+msgstr "Kann Statistiken über Gruppen sehen."
+
+#: models.py:352
 msgid "Long name"
 msgstr "Langname"
 
-#: models.py:340 templates/core/group/full.html:65
+#: models.py:362 templates/core/group/full.html:85
 msgid "Members"
 msgstr "Mitglieder"
 
-#: models.py:343 templates/core/group/full.html:62
+#: models.py:365 templates/core/group/full.html:82
 msgid "Owners"
 msgstr "Leiter/-innen"
 
-#: models.py:350 templates/core/group/full.html:54
+#: models.py:372 templates/core/group/full.html:55
 msgid "Parent groups"
 msgstr "Übergeordnete Gruppen"
 
-#: models.py:358
+#: models.py:380
 msgid "Type of group"
 msgstr "Gruppentyp"
 
-#: models.py:419
+#: models.py:457
 msgid "User"
 msgstr "Benutzer"
 
-#: models.py:422 models.py:446 models.py:531
+#: models.py:460 models.py:484 models.py:569
 #: templates/core/announcement/list.html:18
 msgid "Title"
 msgstr "Titel"
 
-#: models.py:425
+#: models.py:463
 msgid "Application"
 msgstr "Anwendung"
 
-#: models.py:431
+#: models.py:469
 msgid "Activity"
 msgstr "Aktivität"
 
-#: models.py:432
+#: models.py:470
 msgid "Activities"
 msgstr "Aktivitäten"
 
-#: models.py:438
+#: models.py:476
 msgid "Sender"
 msgstr "Absender"
 
-#: models.py:443
+#: models.py:481
 msgid "Recipient"
 msgstr "Empfänger"
 
-#: models.py:448 models.py:701
+#: models.py:486 models.py:786
 msgid "Link"
 msgstr "Link"
 
-#: models.py:450
+#: models.py:488
 msgid "Read"
 msgstr "Gelesen"
 
-#: models.py:451
+#: models.py:489
 msgid "Sent"
 msgstr "Versandt"
 
-#: models.py:464
+#: models.py:502
 msgid "Notification"
 msgstr "Benachrichtigung"
 
-#: models.py:465
+#: models.py:503
 msgid "Notifications"
 msgstr "Benachrichtigungen"
 
-#: models.py:533
+#: models.py:571
 msgid "Link to detailed view"
 msgstr "Link zur detaillierten Ansicht"
 
-#: models.py:536
+#: models.py:574
 msgid "Date and time from when to show"
 msgstr "Datum und Uhrzeit des Anzeigestarts"
 
-#: models.py:539
+#: models.py:577
 msgid "Date and time until when to show"
 msgstr "Anzeigezeitraum"
 
-#: models.py:563
+#: models.py:601
 msgid "Announcement"
 msgstr "Ankündigung"
 
-#: models.py:601
+#: models.py:639
 msgid "Announcement recipient"
 msgstr "Empfänger der Ankündigung"
 
-#: models.py:602
+#: models.py:640
 msgid "Announcement recipients"
 msgstr "Empfänger der Ankündigung"
 
-#: models.py:652
+#: models.py:690
 msgid "Widget Title"
 msgstr "Widget-Titel"
 
-#: models.py:653
+#: models.py:691
 msgid "Activate Widget"
 msgstr "Widget aktivieren"
 
-#: models.py:671
+#: models.py:694
+msgid "Size on mobile devices"
+msgstr "Größe auf Mobilgeräten"
+
+#: models.py:695
+msgid "<= 600 px, 12 columns"
+msgstr "<= 600 px, 12 Spalten"
+
+#: models.py:700
+msgid "Size on tablet devices"
+msgstr "Größe auf Tablets"
+
+#: models.py:701
+msgid "> 600 px, 12 columns"
+msgstr "> 600px, 12 Spalten"
+
+#: models.py:706
+msgid "Size on desktop devices"
+msgstr "Größe auf Desktopgeräten"
+
+#: models.py:707
+msgid "> 992 px, 12 columns"
+msgstr "> 992 px, 12 Spalten"
+
+#: models.py:712
+msgid "Size on large desktop devices"
+msgstr "Größe auf großen Desktopgeräten"
+
+#: models.py:713
+msgid "> 1200 px>, 12 columns"
+msgstr "> 1200 px, 12 Spalten"
+
+#: models.py:734
+msgid "Can edit default dashboard"
+msgstr "Kann Standarddashboard bearbeiten"
+
+#: models.py:735
 msgid "Dashboard Widget"
 msgstr "Dashboard-Widget"
 
-#: models.py:672
+#: models.py:736
 msgid "Dashboard Widgets"
 msgstr "Dashboard-Widgets"
 
-#: models.py:678
+#: models.py:741
+msgid "Dashboard widget"
+msgstr "Dashboard-Widget"
+
+#: models.py:746
+msgid "Order"
+msgstr "Reihenfolge"
+
+#: models.py:747
+msgid "Part of the default dashboard"
+msgstr "Teil des Standarddashboards"
+
+#: models.py:755
+msgid "Dashboard widget order"
+msgstr "Reihenfolge der Dashboard-Widgets"
+
+#: models.py:756
+msgid "Dashboard widget orders"
+msgstr "Reihenfolgen der Dashboard-Widgets"
+
+#: models.py:762
 msgid "Menu ID"
 msgstr "Menü-ID"
 
-#: models.py:690
+#: models.py:775
 msgid "Custom menu"
 msgstr "Benutzerdefiniertes Menü"
 
-#: models.py:691
+#: models.py:776
 msgid "Custom menus"
 msgstr "Benutzerdefinierte Menüs"
 
-#: models.py:698
+#: models.py:783
 msgid "Menu"
 msgstr "Menü"
 
-#: models.py:702
+#: models.py:787
 msgid "Icon"
 msgstr "Icon"
 
-#: models.py:708
+#: models.py:793
 msgid "Custom menu item"
 msgstr "Benutzerdefiniertes Menüelement"
 
-#: models.py:709
+#: models.py:794
 msgid "Custom menu items"
 msgstr "Benutzerdefinierte Menüelemente"
 
-#: models.py:719
+#: models.py:804
 msgid "Title of type"
 msgstr "Titel des Typs"
 
-#: models.py:726 templates/core/group/full.html:46
+#: models.py:811 templates/core/group/full.html:47
 msgid "Group type"
 msgstr "Gruppentyp"
 
-#: models.py:736
+#: models.py:821
 msgid "Can view system status"
 msgstr "Kann Systemstatus sehen"
 
-#: models.py:737
+#: models.py:822
 msgid "Can link persons to accounts"
 msgstr "Kann Personen mit Benutzerkonten verknüpfen"
 
-#: models.py:738
+#: models.py:823
 msgid "Can manage data"
 msgstr "Kann Daten verwalten"
 
-#: models.py:739
+#: models.py:824
 msgid "Can impersonate"
 msgstr "Kann sich verkleiden"
 
-#: models.py:740
+#: models.py:825
 msgid "Can use search"
 msgstr "Kann Suche benutzen"
 
-#: models.py:741
+#: models.py:826
 msgid "Can change site preferences"
 msgstr "Kann Konfiguration ändern"
 
-#: models.py:742
+#: models.py:827
 msgid "Can change person preferences"
 msgstr "Kann Einstellungen einer Person verändern"
 
-#: models.py:743
+#: models.py:828
 msgid "Can change group preferences"
 msgstr "Kann Einstellungen einer Gruppe verändern"
 
-#: preferences.py:24
+#: models.py:864
+msgid "Related data check task"
+msgstr "Zugehörige Datenprüfungsaufgabe"
+
+#: models.py:872
+msgid "Issue solved"
+msgstr "Problem gelöst"
+
+#: models.py:873
+msgid "Notification sent"
+msgstr "Benachrichtigung gesendet"
+
+#: models.py:886
+msgid "Data check result"
+msgstr "Datenprüfungsergebnis"
+
+#: models.py:887
+msgid "Data check results"
+msgstr "Datenprüfungsergebnisse"
+
+#: models.py:889
+msgid "Can run data checks"
+msgstr "Kann Datenprüfungen ausführen"
+
+#: models.py:890
+msgid "Can solve data check problems"
+msgstr "Kann Datenprüfungsprobleme lösen"
+
+#: preferences.py:27
 msgid "Authentication"
 msgstr "Authentifizierung"
 
-#: preferences.py:33
+#: preferences.py:28
+msgid "Internationalisation"
+msgstr "Internationalisierung"
+
+#: preferences.py:37
 msgid "Site title"
 msgstr "Seitentitel"
 
-#: preferences.py:42
+#: preferences.py:46
 msgid "Site description"
 msgstr "Seitenbeschreibung"
 
-#: preferences.py:51
+#: preferences.py:55
 msgid "Primary colour"
 msgstr "Primärfarbe"
 
-#: preferences.py:60
+#: preferences.py:64
 msgid "Secondary colour"
 msgstr "Akzentfarbe"
 
-#: preferences.py:68
+#: preferences.py:72
 msgid "Logo"
 msgstr "Logo"
 
-#: preferences.py:76
+#: preferences.py:80
 msgid "Favicon"
 msgstr "Favicon"
 
-#: preferences.py:84
+#: preferences.py:88
 msgid "PWA-Icon"
 msgstr "PWA-Icon"
 
-#: preferences.py:93
+#: preferences.py:97
 msgid "Mail out name"
 msgstr "Ausgangsmailname"
 
-#: preferences.py:102
+#: preferences.py:106
 msgid "Mail out address"
 msgstr "E-Mail-Ausgangsadresse"
 
-#: preferences.py:112
+#: preferences.py:116
 msgid "Link to privacy policy"
 msgstr "Link zur Datenschutzerklärung"
 
-#: preferences.py:122
+#: preferences.py:126
 msgid "Link to imprint"
 msgstr "Link zum Impressum"
 
-#: preferences.py:132
+#: preferences.py:136
 msgid "Name format for addressing"
 msgstr "Namensformat für Anreden"
 
-#: preferences.py:146
+#: preferences.py:150
 msgid "Channels to use for notifications"
 msgstr "Aktivierte Benachrichtungskanäle"
 
-#: preferences.py:156
+#: preferences.py:160
 msgid "Regular expression to match primary group, e.g. '^Class .*'"
 msgstr "Regulärer Ausdruck um Primärgruppen zu finden, z. B.  '^Class .*'"
 
-#: preferences.py:165
+#: preferences.py:169
 msgid "Field on person to match primary group against"
 msgstr "Feld um Primärgruppen zu finden"
 
-#: preferences.py:177
+#: preferences.py:181
 msgid "Display name of the school"
 msgstr "Sichtbarer Name der Schule"
 
-#: preferences.py:186
+#: preferences.py:190
 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"
 
-#: preferences.py:194
+#: preferences.py:198
 msgid "Enabled custom authentication backends"
 msgstr "Benutzerdefinierte Authentifizierungsbackends aktivieren"
 
-#: settings.py:300
+#: preferences.py:211
+msgid "Available languages"
+msgstr "Verfügbare Sprachen"
+
+#: preferences.py:223
+msgid "Send emails if data checks detect problems"
+msgstr "E-Mails versenden, wenn Datenprüfungen Probleme finden"
+
+#: preferences.py:234
+msgid "Email recipients for data checks problem emails"
+msgstr "E-Mailempfänger für Datenprüfungsproblem-E-Mails"
+
+#: preferences.py:245
+msgid "Email recipient groups for data checks problem emails"
+msgstr "E-Mail-Empfängergruppen für Datenprüfungsproblem-E-Mails"
+
+#: settings.py:322
 msgid "English"
 msgstr "Englisch"
 
-#: settings.py:301
+#: settings.py:323
 msgid "German"
 msgstr "Deutsch"
 
-#: settings.py:302
+#: settings.py:324
 msgid "French"
 msgstr "Französisch"
 
-#: settings.py:303
+#: settings.py:325
 msgid "Norwegian (bokmål)"
 msgstr "Norwegisch (bokmål)"
 
 #: tables.py:19 templates/core/announcement/list.html:36
-#: templates/core/group/full.html:23 templates/core/person/full.html:22
+#: templates/core/group/full.html:24 templates/core/person/full.html:23
 msgid "Edit"
 msgstr "Bearbeiten"
 
-#: tables.py:21 templates/core/announcement/list.html:22
+#: tables.py:21 tables.py:89 templates/core/announcement/list.html:22
 msgid "Actions"
 msgstr "Aktionen"
 
-#: tables.py:56 tables.py:57 tables.py:71
-#: templates/core/announcement/list.html:42 templates/core/group/full.html:30
-#: templates/core/pages/delete.html:22 templates/core/person/full.html:29
+#: tables.py:56 tables.py:57 tables.py:71 tables.py:87
+#: templates/core/announcement/list.html:42 templates/core/group/full.html:31
+#: templates/core/pages/delete.html:22 templates/core/person/full.html:30
 msgid "Delete"
 msgstr "Löschen"
 
@@ -785,21 +915,21 @@ msgstr "Zusätzliches Feld bearbeiten"
 msgid "Create additional field"
 msgstr "Zusätzliches Feld erstellen"
 
-#: templates/core/announcement/form.html:10
-#: templates/core/announcement/form.html:17
+#: templates/core/announcement/form.html:14
+#: templates/core/announcement/form.html:21
 msgid "Edit announcement"
 msgstr "Ankündigung bearbeiten"
 
-#: templates/core/announcement/form.html:12
+#: templates/core/announcement/form.html:16
 msgid "Publish announcement"
 msgstr "Ankündigung veröffentlichen"
 
-#: templates/core/announcement/form.html:19
+#: templates/core/announcement/form.html:23
 #: templates/core/announcement/list.html:13
 msgid "Publish new announcement"
 msgstr "Neue Ankündigung veröffentlichen"
 
-#: templates/core/announcement/form.html:30
+#: templates/core/announcement/form.html:34
 msgid "Save und publish announcement"
 msgstr "Ankündigung speichern und veröffentlichen"
 
@@ -839,6 +969,143 @@ msgstr "Datenschutzerklärung"
 msgid "Powered by AlekSIS"
 msgstr "Betrieben mit AlekSIS"
 
+#: templates/core/dashboard_widget/create.html:8
+#: templates/core/dashboard_widget/create.html:12
+#, python-format
+msgid "Create %(widget)s"
+msgstr "%(widget)s erstellen"
+
+#: templates/core/dashboard_widget/edit.html:8
+#: templates/core/dashboard_widget/edit.html:12
+#, python-format
+msgid "Edit %(widget)s"
+msgstr "%(widget)s bearbeiten"
+
+#: templates/core/dashboard_widget/list.html:17
+#, python-format
+msgid "Create %(name)s"
+msgstr "%(name)s erstellen"
+
+#: templates/core/dashboard_widget/list.html:25
+#: templates/core/edit_dashboard.html:8 templates/core/edit_dashboard.html:15
+msgid "Edit default dashboard"
+msgstr "Standard-Dashboard bearbeiten"
+
+#: templates/core/data_check/list.html:15
+msgid "Check data again"
+msgstr "Daten erneut prüfen"
+
+#: templates/core/data_check/list.html:22
+msgid "The system detected some problems with your data."
+msgstr "Das System hat einige Problemen mit Ihren Daten gefunden."
+
+#: templates/core/data_check/list.html:23
+msgid ""
+"Please go through all data and check whether some extra action is\n"
+"          needed."
+msgstr ""
+"Bitte gehen Sie alle Daten durch und prüfen Sie, ob weitere Aktionen\n"
+"notwendig sind."
+
+#: templates/core/data_check/list.html:31
+msgid "Everything is fine."
+msgstr "Alles ist gut."
+
+#: templates/core/data_check/list.html:32
+msgid "The system hasn't detected any problems with your data."
+msgstr "Das System hat keine Probleme mit Ihren Daten entdeckt."
+
+#: templates/core/data_check/list.html:40
+msgid "Detected problems"
+msgstr "Gefundene Probleme"
+
+#: templates/core/data_check/list.html:45
+msgid "Affected object"
+msgstr "Betroffenes Objekt"
+
+#: templates/core/data_check/list.html:46
+msgid "Detected problem"
+msgstr "Entdecktes Problem"
+
+#: templates/core/data_check/list.html:47
+msgid "Show details"
+msgstr "Details anzeigen"
+
+#: templates/core/data_check/list.html:48
+msgid "Options to solve the problem"
+msgstr "Optionen, das Problem zu lösen"
+
+#: templates/core/data_check/list.html:62
+msgid "Show object"
+msgstr "Objekt anzeigen"
+
+#: templates/core/data_check/list.html:84
+msgid "Registered checks"
+msgstr "Registrierte Prüfungen"
+
+#: templates/core/data_check/list.html:88
+msgid ""
+"\n"
+"            The system will check for the following problems:\n"
+"          "
+msgstr ""
+"\n"
+"            Das System wird nach folgenden Problemen suchen:\n"
+"          "
+
+#: templates/core/edit_dashboard.html:6 templates/core/edit_dashboard.html:13
+#: templates/core/index.html:14
+msgid "Edit dashboard"
+msgstr "Dashboard bearbeiten"
+
+#: templates/core/edit_dashboard.html:24
+msgid ""
+"\n"
+"          On this page you can arrange your personal dashboard. You can drag any items from \"Available widgets\" to \"Your\n"
+"          Dashboard\" or change the order by moving the widgets. After you have finished, please don't forget to click on\n"
+"          \"Save\".\n"
+"        "
+msgstr ""
+"\n"
+"          Auf dieser Seite können Sie Ihr persönliches Dashboard "
+"zusammenstallen. Sie können beliebige Elemente von den \"Verfügbaren "
+"Widgets\" \n"
+"in \"Ihr Dashboard\" ziehen oder die Reihenfolge verändern, indem Sie die "
+"Widgets bewegen. Wenn Sie fertig sind, vergessen Sie bitte nicht, \n"
+"auf \"Speichern\" zu drücken.\n"
+"        "
+
+#: templates/core/edit_dashboard.html:30
+msgid ""
+"\n"
+"          On this page you can arrange the default dashboard which is shown when a user doesn't arrange his own\n"
+"          dashboard. You can drag any items from \"Available widgets\" to \"Default Dashboard\" or change the order\n"
+"          by moving the widgets. After you have finished, please don't forget to click on \"Save\".\n"
+"        "
+msgstr ""
+"\n"
+"          Auf dieser Seite können Sie Ihr das Standard-Dashboard "
+"zusammenstallen, welches angezeigt wird, wenn ein Nutzer kein eigenes "
+"definiert. \n"
+"Sie können beliebige Elemente von den \"Verfügbaren Widgets\" in \"Standard-"
+"Dashboard\" ziehen oder die Reihenfolge verändern, indem Sie die Widgets "
+"bewegen. \n"
+"Wenn Sie fertig sind, vergessen Sie bitte nicht, auf \"Speichern\" zu "
+"drücken.\n"
+"        "
+
+#: templates/core/edit_dashboard.html:48
+msgid "Available widgets"
+msgstr "Verfügbare Widgets"
+
+#: templates/core/edit_dashboard.html:57
+msgid "Your dashboard"
+msgstr "Ihr Dashboard"
+
+#: templates/core/edit_dashboard.html:59
+msgid "Default dashboard"
+msgstr "Standard-Dashboard"
+
 #: templates/core/group/child_groups.html:18
 msgid ""
 "\n"
@@ -923,14 +1190,38 @@ msgstr "Speichern"
 msgid "Save and next"
 msgstr "Speichern und weiter"
 
-#: templates/core/group/edit.html:6 templates/core/group/edit.html:7
+#: templates/core/group/edit.html:11 templates/core/group/edit.html:12
 msgid "Edit group"
 msgstr "Gruppe editieren"
 
-#: templates/core/group/full.html:37 templates/core/person/full.html:36
+#: templates/core/group/full.html:38 templates/core/person/full.html:37
 msgid "Change preferences"
 msgstr "Einstellungen ändern"
 
+#: templates/core/group/full.html:64
+msgid "Statistics"
+msgstr "Statistiken"
+
+#: templates/core/group/full.html:67
+msgid "Count of members"
+msgstr "Anzahl der Mitglieder"
+
+#: templates/core/group/full.html:71
+msgid "Average age"
+msgstr "Durchschnittsalter"
+
+#: templates/core/group/full.html:76
+msgid "Age range"
+msgstr "Altersbereich"
+
+#: templates/core/group/full.html:76
+msgid "years to"
+msgstr "Jahre bis"
+
+#: templates/core/group/full.html:76
+msgid "years "
+msgstr "Jahre "
+
 #: templates/core/group/list.html:14
 msgid "Create group"
 msgstr "Gruppe erstellen"
@@ -959,23 +1250,37 @@ msgstr "Gruppentyp erstellen"
 msgid "Home"
 msgstr "Startseite"
 
-#: templates/core/index.html:42
+#: templates/core/index.html:50
+msgid ""
+"\n"
+"          You didn't customise your dashboard so that you see the system default. Please click on \"Edit dashboard\" to\n"
+"          customise your personal dashboard.\n"
+"        "
+msgstr ""
+"\n"
+"          Sie haben Ihr Dashboard nicht angepasst, sodass Sie das Standard-"
+"Dashboard sehen.\n"
+"Bitte klicken Sie auf \"Dashboard bearbeiten\", um Ihr persönliches "
+"Dashboard anzupassen.\n"
+"        "
+
+#: templates/core/index.html:59
 msgid "Last activities"
 msgstr "Letzte Aktivitäten"
 
-#: templates/core/index.html:60
+#: templates/core/index.html:77
 msgid "No activities available yet."
 msgstr "Aktuell keine Aktivitäten verfügbar."
 
-#: templates/core/index.html:65
+#: templates/core/index.html:82
 msgid "Recent notifications"
 msgstr "Letzte Benachrichtigungen"
 
-#: templates/core/index.html:81
+#: templates/core/index.html:98
 msgid "More information →"
 msgstr "Mehr Informationen →"
 
-#: templates/core/index.html:88
+#: templates/core/index.html:105
 msgid "No notifications available yet."
 msgstr "Aktuell keine Benachrichtigungen verfügbar."
 
@@ -1070,28 +1375,6 @@ msgstr ""
 "      Möchten Sie wirklich %(object_name)s \"%(object)s\" löschen?\n"
 "    "
 
-#: templates/core/pages/offline.html:6
-msgid ""
-"No internet\n"
-"    connection."
-msgstr ""
-"Keine\n"
-"    Internetverbindung."
-
-#: templates/core/pages/offline.html:10
-msgid ""
-"\n"
-"      There was an error accessing this page. You probably don't have an internet connection. Check to see if your WiFi\n"
-"      or mobile data is turned on and try again. If you think you are connected, please contact the system\n"
-"      administrators:\n"
-"    "
-msgstr ""
-"\n"
-"      Es ist ein Fehler beim Aufrufen der Seite aufgetreten. Eventuell haben Sie keine Internetverbindung. Bitte prüfen Sie, ob WLAN oder mobile Daten aktiv sind, \n"
-"      und probieren Sie es erneut. Wenn Sie der Meinung sind, dass Sie mit dem Internet verbunden sind, kontaktieren Sie bitte einen Ihrer \n"
-"      Systemadministratoren:\n"
-"    "
-
 #: templates/core/pages/progress.html:27
 msgid ""
 "\n"
@@ -1099,8 +1382,7 @@ msgid ""
 "            "
 msgstr ""
 "\n"
-"              Ohne aktiviertes JavaScript kann der Fortschritt leider nicht "
-"aktualisiert werden.\n"
+"              Ohne aktiviertes JavaScript kann der Fortschritt leider nicht aktualisiert werden.\n"
 "            "
 
 #: templates/core/pages/progress.html:47
@@ -1233,46 +1515,19 @@ msgstr ""
 "              Gültig von %(from)s – %(until)s\n"
 "            "
 
-#: templates/core/partials/crud_events.html:10
-#, python-format
-msgid ""
-"\n"
-"              Created by %(person)s\n"
-"            "
-msgstr ""
-"\n"
-"              Erstellt von %(person)s\n"
-"            "
-
-#: templates/core/partials/crud_events.html:14
-#: templates/core/partials/crud_events.html:22
-#: templates/core/partials/crud_events.html:26
-#, python-format
-msgid ""
-"\n"
-"              Updated by %(person)s\n"
-"            "
-msgstr ""
-"\n"
-"              Aktualisiert von %(person)s\n"
-"            "
+#: templates/core/partials/crud_events.html:15
+msgid "Changed by"
+msgstr "Verändert von"
 
-#: templates/core/partials/crud_events.html:18
-#, python-format
-msgid ""
-"\n"
-"              Deleted by %(person)s\n"
-"            "
-msgstr ""
-"\n"
-"              Gelöscht von %(person)s\n"
-"            "
+#: templates/core/partials/crud_events.html:15
+msgid "Unknown"
+msgstr "Unbekannt"
 
-#: templates/core/partials/language_form.html:16
+#: templates/core/partials/language_form.html:15
 msgid "Language"
 msgstr "Sprache"
 
-#: templates/core/partials/language_form.html:28
+#: templates/core/partials/language_form.html:27
 msgid "Select language"
 msgstr "Sprache auswählen"
 
@@ -1302,11 +1557,12 @@ msgstr ""
 "        die Verwaltenden von AlekSIS an Ihrer Schule.\n"
 "          "
 
-#: templates/core/person/accounts.html:7 templates/core/person/accounts.html:9
+#: templates/core/person/accounts.html:12
+#: templates/core/person/accounts.html:14
 msgid "Link persons to accounts"
 msgstr "Personen mit Benutzerkonten verknüpfen"
 
-#: templates/core/person/accounts.html:16
+#: templates/core/person/accounts.html:21
 msgid ""
 "\n"
 "        You can use this form to assign user accounts to persons. Use the\n"
@@ -1322,28 +1578,32 @@ msgstr ""
 "    eingegebenen Benutzernamen und kopiert alle anderen Daten der Person.\n"
 "      "
 
-#: templates/core/person/accounts.html:31
-#: templates/core/person/accounts.html:55
+#: templates/core/person/accounts.html:36
+#: templates/core/person/accounts.html:60
 msgid "Update"
 msgstr "Aktualisieren"
 
-#: templates/core/person/accounts.html:37
+#: templates/core/person/accounts.html:42
 msgid "Existing account"
 msgstr "Existierendes Konto"
 
-#: templates/core/person/accounts.html:38
+#: templates/core/person/accounts.html:43
 msgid "New account"
 msgstr "Neues Konto"
 
-#: templates/core/person/edit.html:11 templates/core/person/edit.html:12
+#: templates/core/person/edit.html:12 templates/core/person/edit.html:13
 msgid "Edit person"
 msgstr "Person editieren"
 
-#: templates/core/person/full.html:42
+#: templates/core/person/full.html:44
+msgid "Impersonate"
+msgstr "Verkleiden"
+
+#: templates/core/person/full.html:50
 msgid "Contact details"
 msgstr "Kontaktdetails"
 
-#: templates/core/person/full.html:122
+#: templates/core/person/full.html:130
 msgid "Children"
 msgstr "Kinder"
 
@@ -1387,14 +1647,36 @@ msgstr "Einstellungen für %(instance)s"
 msgid "Save preferences"
 msgstr "Einstellungen speichern"
 
-#: templates/dynamic_preferences/sections.html:7
-msgid "All"
-msgstr "Alle"
-
 #: templates/impersonate/list_users.html:8
 msgid "Impersonate user"
 msgstr "Als Benutzer verkleiden"
 
+#: templates/offline.html:5
+msgid "Network error"
+msgstr "Netzwerkfehler"
+
+#: templates/offline.html:8
+msgid ""
+"No internet\n"
+"    connection."
+msgstr ""
+"Keine\n"
+"    Internetverbindung."
+
+#: templates/offline.html:12
+msgid ""
+"\n"
+"      There was an error accessing this page. You probably don't have an internet connection. Check to see if your WiFi\n"
+"      or mobile data is turned on and try again. If you think you are connected, please contact the system\n"
+"      administrators:\n"
+"    "
+msgstr ""
+"\n"
+"      Es ist ein Fehler beim Aufrufen der Seite aufgetreten. Eventuell haben Sie keine Internetverbindung. Bitte prüfen Sie, ob WLAN oder mobile Daten aktiv sind, \n"
+"      und probieren Sie es erneut. Wenn Sie der Meinung sind, dass Sie mit dem Internet verbunden sind, kontaktieren Sie bitte einen Ihrer \n"
+"      Systemadministratoren:\n"
+"    "
+
 #: templates/search/search.html:8
 msgid "Global Search"
 msgstr "Globale Suche"
@@ -1415,6 +1697,47 @@ msgstr "Es konnten keine Suchergebnisse zu Ihrem Suchausdruck gefunden werden."
 msgid "Please enter a search term above."
 msgstr "Bitte geben Sie einen Suchausdruck ein."
 
+#: templates/templated_email/data_checks.email:4
+msgid "The system detected some new problems with your data."
+msgstr "Das System hat einige neue Probleme mit Ihren Daten entdeckt."
+
+#: templates/templated_email/data_checks.email:8
+#: templates/templated_email/data_checks.email:24
+msgid "Hello,"
+msgstr "Hallo,"
+
+#: templates/templated_email/data_checks.email:10
+msgid ""
+"\n"
+"  the system detected some new problems with your data.\n"
+"  Please take some time to inspect them and solve the issues or mark them as ignored.\n"
+" "
+msgstr ""
+"\n"
+"  das System hat einige neue Probleme mit Ihren Daten entdeckt.\n"
+"Bitte nehmen Sie sich etwas Zeit, diese zu überprüfen und sie zu lösen oder als ignoriert zu markieren.\n"
+" "
+
+#: templates/templated_email/data_checks.email:26
+msgid ""
+"\n"
+"   the system detected some new problems with your data.\n"
+"   Please take some time to inspect them and solve the issues or mark them as ignored.\n"
+"  "
+msgstr ""
+"\n"
+"   das System hat einige neue Probleme mit Ihren Daten entdeckt.\n"
+"Bitte nehmen Sie sich etwas Zeit, diese zu überprüfen und sie zu lösen oder als ignoriert zu markieren.\n"
+"  "
+
+#: templates/templated_email/data_checks.email:34
+msgid "Problem description"
+msgstr "Problembeschreibung"
+
+#: templates/templated_email/data_checks.email:35
+msgid "Count of objects with new problems"
+msgstr "Anzahl der Objekte mit neuen Problemen"
+
 #: templates/templated_email/notification.email:3
 msgid "New notification for"
 msgstr "Neue Benachrichtigung für"
@@ -1897,62 +2220,126 @@ msgstr "E-Mail"
 msgid "SMS"
 msgstr "SMS"
 
-#: views.py:122
+#: views.py:141
 msgid "The school term has been created."
 msgstr "Das Schuljahr wurde erstellt."
 
-#: views.py:133
+#: views.py:153
 msgid "The school term has been saved."
 msgstr "Das Schuljahr wurde gespeichert."
 
-#: views.py:273
+#: views.py:298
 msgid "The child groups were successfully saved."
 msgstr "Die Untergruppen wurden gespeichert."
 
-#: views.py:309
+#: views.py:336
 msgid "The person has been saved."
 msgstr "Die Person wurde gespeichert."
 
-#: views.py:346
+#: views.py:375
 msgid "The group has been saved."
 msgstr "Die Gruppe wurde gespeichert."
 
-#: views.py:434
+#: views.py:467
 msgid "The announcement has been saved."
 msgstr "Die Ankündigung wurde gespeichert."
 
-#: views.py:450
+#: views.py:483
 msgid "The announcement has been deleted."
 msgstr "Ankündigung wurde gelöscht."
 
-#: views.py:521
+#: views.py:562
 msgid "The preferences have been saved successfully."
 msgstr "Die Einstellungen wurde gespeichert."
 
-#: views.py:544
+#: views.py:586
 msgid "The person has been deleted."
 msgstr "Die Person wurde gelöscht."
 
-#: views.py:557
+#: views.py:600
 msgid "The group has been deleted."
 msgstr "Die Gruppe wurde gelöscht."
 
-#: views.py:588
+#: views.py:632
 msgid "The additional_field has been saved."
 msgstr "Das zusätzliche Feld wurde gespeichert."
 
-#: views.py:622
+#: views.py:666
 msgid "The additional field has been deleted."
 msgstr "Das zusätzliche Feld wurde gelöscht."
 
-#: views.py:646
+#: views.py:691
 msgid "The group type has been saved."
 msgstr "Der Gruppentyp wurde gespeichert."
 
-#: views.py:676
+#: views.py:721
 msgid "The group type has been deleted."
 msgstr "Der Gruppentyp wurde gelöscht."
 
+#: views.py:749
+msgid "The data check has been started. Please note that it may take a while before you are able to fetch the data on this page."
+msgstr "Die Datenüberprüfung wurde gestartet. Bitte beachten Sie, dass es eine Weile dauern kann, bevor Sie auf dieser Seite Ergebnisse abrufen können."
+
+#: views.py:754
+msgid "The data check has finished."
+msgstr "Die Datenüberprüfung wurde beendet."
+
+#: views.py:769
+#, python-brace-format
+msgid "The solve option '{solve_option_obj.verbose_name}' "
+msgstr "Die Lösungsoption \"{solve_option_obj.verbose_name}\" "
+
+#: views.py:811
+msgid "The dashboard widget has been saved."
+msgstr "Das Dashboard-Widget wurde gespeichert."
+
+#: views.py:841
+msgid "The dashboard widget has been created."
+msgstr "Das Dashboard-Widget wurde erstellt."
+
+#: views.py:851
+msgid "The dashboard widget has been deleted."
+msgstr "Das Dashboard-Widget wurde gelöscht."
+
+#: views.py:914
+msgid "Your dashboard configuration has been saved successfully."
+msgstr "Ihre Dashboardkonfiguration wurde erfolgreich gespeichert."
+
+#: views.py:916
+msgid "The configuration of the default dashboard has been saved successfully."
+msgstr ""
+"Die Konfiguration des Standard-Dashboardes wurde erfolgreich gespeichert."
+
+#~ msgid "All"
+#~ msgstr "Alle"
+
+#~ msgid ""
+#~ "\n"
+#~ "              Created by %(person)s\n"
+#~ "            "
+#~ msgstr ""
+#~ "\n"
+#~ "              Erstellt von %(person)s\n"
+#~ "            "
+
+#~ msgid ""
+#~ "\n"
+#~ "              Updated by %(person)s\n"
+#~ "            "
+#~ msgstr ""
+#~ "\n"
+#~ "              Aktualisiert von %(person)s\n"
+#~ "            "
+
+#~ msgid ""
+#~ "\n"
+#~ "              Deleted by %(person)s\n"
+#~ "            "
+#~ msgstr ""
+#~ "\n"
+#~ "              Gelöscht von %(person)s\n"
+#~ "            "
+
 #~ msgid "Dear"
 #~ msgstr "Sehr geehrter"
 
diff --git a/aleksis/core/locale/de_DE/LC_MESSAGES/djangojs.po b/aleksis/core/locale/de_DE/LC_MESSAGES/djangojs.po
index 9dbef6e6f74f842b0e8f25e389edf1a852cd8d99..ea24fc3ff92afc211898fb8b426dccb97fce56ed 100644
--- a/aleksis/core/locale/de_DE/LC_MESSAGES/djangojs.po
+++ b/aleksis/core/locale/de_DE/LC_MESSAGES/djangojs.po
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2020-08-02 16:29+0200\n"
+"POT-Creation-Date: 2021-01-11 21:30+0100\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -17,14 +17,18 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: static/js/main.js:21
+#: static/js/main.js:15
 msgid "Today"
 msgstr ""
 
-#: static/js/main.js:22
+#: static/js/main.js:16
 msgid "Cancel"
 msgstr ""
 
-#: static/js/main.js:23
+#: static/js/main.js:17
 msgid "OK"
 msgstr ""
+
+#: static/js/main.js:118
+msgid "This page may contain outdated information since there is no internet connection."
+msgstr ""
diff --git a/aleksis/core/locale/fr/LC_MESSAGES/django.po b/aleksis/core/locale/fr/LC_MESSAGES/django.po
index a8556727d98887123c05abb853a0bd46e829ead4..0938d0f9e68b50c905b6e0c232ade944ee0907a6 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: 2020-08-02 16:29+0200\n"
+"POT-Creation-Date: 2021-01-11 21:30+0100\n"
 "PO-Revision-Date: 2020-04-27 13:03+0000\n"
 "Last-Translator: Marlene Grundey <grundema@katharineum.de>\n"
 "Language-Team: French <https://translate.edugit.org/projects/aleksis/aleksis/fr/>\n"
@@ -18,6 +18,15 @@ msgstr ""
 "Plural-Forms: nplurals=2; plural=n > 1;\n"
 "X-Generator: Weblate 4.0.1\n"
 
+#: data_checks.py:53
+msgid "Ignore problem"
+msgstr ""
+
+#: data_checks.py:174
+#, python-brace-format
+msgid "Solve option '{solve_option_obj.verbose_name}' "
+msgstr ""
+
 #: filters.py:37 templates/core/base.html:77 templates/core/group/list.html:20
 #: templates/core/person/list.html:24 templates/search/search.html:7
 #: templates/search/search.html:22
@@ -34,104 +43,108 @@ msgstr ""
 msgid "Search by contact details"
 msgstr "Détails de contact"
 
-#: forms.py:46
+#: forms.py:54
 msgid "You cannot set a new username when also selecting an existing user."
 msgstr ""
 
-#: forms.py:50
+#: forms.py:58
 msgid "This username is already in use."
 msgstr ""
 
-#: forms.py:74
+#: forms.py:82
 msgid "Base data"
 msgstr ""
 
-#: forms.py:80
+#: forms.py:88
 msgid "Address"
 msgstr ""
 
-#: forms.py:81
+#: forms.py:89
 #, fuzzy
 #| msgid "Contact details"
 msgid "Contact data"
 msgstr "Détails de contact"
 
-#: forms.py:83
+#: forms.py:91
 #, fuzzy
 #| msgid "Contact details"
 msgid "Advanced personal data"
 msgstr "Détails de contact"
 
-#: forms.py:114
+#: forms.py:134
 msgid "New user"
 msgstr ""
 
-#: forms.py:114
+#: forms.py:134
 msgid "Create a new account"
 msgstr ""
 
-#: forms.py:126 models.py:91
+#: forms.py:146 models.py:102
 msgid "School term"
 msgstr ""
 
-#: forms.py:127
+#: forms.py:147
 #, fuzzy
 #| msgid "Contact details"
 msgid "Common data"
 msgstr "Détails de contact"
 
-#: forms.py:128 forms.py:170 menus.py:152 models.py:105
+#: forms.py:148 forms.py:197 menus.py:169 models.py:116
 #: templates/core/person/list.html:8 templates/core/person/list.html:9
 #, fuzzy
 #| msgid "Person"
 msgid "Persons"
 msgstr "Personne"
 
-#: forms.py:129
+#: forms.py:149
 #, fuzzy
 #| msgid "Contact details"
 msgid "Additional data"
 msgstr "Détails de contact"
 
-#: forms.py:163 forms.py:166 models.py:35
+#: forms.py:189 forms.py:192 models.py:45
 msgid "Date"
 msgstr "Date"
 
-#: forms.py:164 forms.py:167 models.py:43
+#: forms.py:190 forms.py:193 models.py:53
 msgid "Time"
 msgstr ""
 
-#: forms.py:172 menus.py:160 models.py:319 templates/core/group/list.html:8
-#: templates/core/group/list.html:9 templates/core/person/full.html:136
+#: forms.py:210 menus.py:177 models.py:338 templates/core/group/list.html:8
+#: templates/core/group/list.html:9 templates/core/person/full.html:144
 #, fuzzy
 #| msgid "Group"
 msgid "Groups"
 msgstr "Groupe"
 
-#: forms.py:176
+#: forms.py:220
 msgid "From when until when should the announcement be displayed?"
 msgstr ""
 
-#: forms.py:179
+#: forms.py:223
 msgid "Who should see the announcement?"
 msgstr ""
 
-#: forms.py:180
+#: forms.py:224
 msgid "Write your announcement:"
 msgstr ""
 
-#: forms.py:219
+#: forms.py:263
 msgid "You are not allowed to create announcements which are only valid in the past."
 msgstr ""
 
-#: forms.py:223
+#: forms.py:267
 msgid "The from date and time must be earlier then the until date and time."
 msgstr ""
 
-#: forms.py:232
+#: forms.py:276
 msgid "You need at least one recipient."
 msgstr ""
 
+#: health_checks.py:15
+msgid "There are unresolved data problems."
+msgstr ""
+
 #: menus.py:7 templates/two_factor/core/login.html:6
 #: templates/two_factor/core/login.html:10
 #: templates/two_factor/core/login.html:86
@@ -170,569 +183,689 @@ msgstr ""
 msgid "Admin"
 msgstr ""
 
-#: menus.py:75 models.py:564 templates/core/announcement/list.html:7
+#: menus.py:75 models.py:602 templates/core/announcement/list.html:7
 #: templates/core/announcement/list.html:8
 msgid "Announcements"
 msgstr ""
 
-#: menus.py:86 models.py:92 templates/core/school_term/list.html:8
+#: menus.py:86 models.py:103 templates/core/school_term/list.html:8
 #: templates/core/school_term/list.html:9
 msgid "School terms"
 msgstr ""
 
-#: menus.py:97 templates/core/management/data_management.html:6
+#: menus.py:97 templates/core/dashboard_widget/list.html:8
+#: templates/core/dashboard_widget/list.html:9
+msgid "Dashboard widgets"
+msgstr ""
+
+#: menus.py:108 templates/core/management/data_management.html:6
 #: templates/core/management/data_management.html:7
 msgid "Data management"
 msgstr ""
 
-#: menus.py:105 templates/core/pages/system_status.html:5
+#: menus.py:116 templates/core/pages/system_status.html:5
 #: templates/core/pages/system_status.html:7
 msgid "System status"
 msgstr ""
 
-#: menus.py:116
+#: menus.py:127
 msgid "Impersonation"
 msgstr ""
 
-#: menus.py:124
+#: menus.py:135
 msgid "Configuration"
 msgstr ""
 
-#: menus.py:135
+#: menus.py:146 templates/core/data_check/list.html:9
+#: templates/core/data_check/list.html:10
+msgid "Data checks"
+msgstr ""
+
+#: menus.py:152
 msgid "Backend Admin"
 msgstr ""
 
-#: menus.py:143
+#: menus.py:160
 msgid "People"
 msgstr ""
 
-#: menus.py:168 models.py:727 templates/core/group_type/list.html:8
+#: menus.py:185 models.py:812 templates/core/group_type/list.html:8
 #: templates/core/group_type/list.html:9
 #, fuzzy
 #| msgid "Group"
 msgid "Group types"
 msgstr "Groupe"
 
-#: menus.py:179
+#: menus.py:196
 msgid "Persons and accounts"
 msgstr ""
 
-#: menus.py:190
+#: menus.py:207
 msgid "Groups and child groups"
 msgstr ""
 
-#: menus.py:201 models.py:363 templates/core/additional_field/list.html:8
+#: menus.py:218 models.py:385 templates/core/additional_field/list.html:8
 #: templates/core/additional_field/list.html:9
 msgid "Additional fields"
 msgstr ""
 
-#: menus.py:216 templates/core/group/child_groups.html:7
+#: menus.py:233 templates/core/group/child_groups.html:7
 #: templates/core/group/child_groups.html:9
 msgid "Assign child groups to groups"
 msgstr ""
 
-#: mixins.py:406
+#: mixins.py:384
 msgid "Linked school term"
 msgstr ""
 
-#: models.py:33
+#: models.py:43
 msgid "Boolean (Yes/No)"
 msgstr ""
 
-#: models.py:34
+#: models.py:44
 msgid "Text (one line)"
 msgstr ""
 
-#: models.py:36
+#: models.py:46
 msgid "Date and time"
 msgstr ""
 
-#: models.py:37
+#: models.py:47
 msgid "Decimal number"
 msgstr ""
 
-#: models.py:38 models.py:146
+#: models.py:48 models.py:157
 msgid "E-mail address"
 msgstr ""
 
-#: models.py:39
+#: models.py:49
 msgid "Integer"
 msgstr ""
 
-#: models.py:40
+#: models.py:50
 msgid "IP address"
 msgstr ""
 
-#: models.py:41
+#: models.py:51
 msgid "Boolean or empty (Yes/No/Neither)"
 msgstr ""
 
-#: models.py:42
+#: models.py:52
 msgid "Text (multi-line)"
 msgstr ""
 
-#: models.py:44
+#: models.py:54
 msgid "URL / Link"
 msgstr ""
 
-#: models.py:56 models.py:700
+#: models.py:66 models.py:785
 msgid "Name"
 msgstr ""
 
-#: models.py:58
+#: models.py:68
 #, fuzzy
 #| msgid "Contact details"
 msgid "Start date"
 msgstr "Détails de contact"
 
-#: models.py:59
+#: models.py:69
 msgid "End date"
 msgstr ""
 
-#: models.py:77
+#: models.py:88
 msgid "The start date must be earlier than the end date."
 msgstr ""
 
-#: models.py:84
+#: models.py:95
 msgid "There is already a school term for this time or a part of this time."
 msgstr ""
 
-#: models.py:104 templates/core/person/accounts.html:36
+#: models.py:115 models.py:744 templates/core/person/accounts.html:41
 msgid "Person"
 msgstr "Personne"
 
-#: models.py:107
+#: models.py:118
 #, fuzzy
 #| msgid "Contact details"
 msgid "Can view address"
 msgstr "Détails de contact"
 
-#: models.py:108
+#: models.py:119
 #, fuzzy
 #| msgid "Contact details"
 msgid "Can view contact details"
 msgstr "Détails de contact"
 
-#: models.py:109
+#: models.py:120
 #, fuzzy
 #| msgid "Contact details"
 msgid "Can view photo"
 msgstr "Détails de contact"
 
-#: models.py:110
+#: models.py:121
 #, fuzzy
 #| msgid "Contact details"
 msgid "Can view persons groups"
 msgstr "Détails de contact"
 
-#: models.py:111
+#: models.py:122
 #, fuzzy
 #| msgid "Contact details"
 msgid "Can view personal details"
 msgstr "Détails de contact"
 
-#: models.py:116
+#: models.py:127
 msgid "female"
 msgstr ""
 
-#: models.py:116
+#: models.py:127
 msgid "male"
 msgstr ""
 
-#: models.py:124
+#: models.py:135
 msgid "Linked user"
 msgstr ""
 
-#: models.py:126
+#: models.py:137
 msgid "Is person active?"
 msgstr ""
 
-#: models.py:128
+#: models.py:139
 msgid "First name"
 msgstr "Prénom"
 
-#: models.py:129
+#: models.py:140
 msgid "Last name"
 msgstr "Nom de famille"
 
-#: models.py:131
+#: models.py:142
 msgid "Additional name(s)"
 msgstr ""
 
-#: models.py:135 models.py:332
+#: models.py:146 models.py:354
 #, fuzzy
 #| msgid "First name"
 msgid "Short name"
 msgstr "Prénom"
 
-#: models.py:138
+#: models.py:149
 msgid "Street"
 msgstr ""
 
-#: models.py:139
+#: models.py:150
 msgid "Street number"
 msgstr ""
 
-#: models.py:140
+#: models.py:151
 msgid "Postal code"
 msgstr ""
 
-#: models.py:141
+#: models.py:152
 msgid "Place"
 msgstr ""
 
-#: models.py:143
+#: models.py:154
 msgid "Home phone"
 msgstr ""
 
-#: models.py:144
+#: models.py:155
 msgid "Mobile phone"
 msgstr ""
 
-#: models.py:148
+#: models.py:159
 msgid "Date of birth"
 msgstr "Date d'anniversaire"
 
-#: models.py:149
+#: models.py:160
 msgid "Sex"
 msgstr "Sexe"
 
-#: models.py:151
+#: models.py:162
 msgid "Photo"
 msgstr ""
 
-#: models.py:155 templates/core/person/full.html:129
+#: models.py:166 templates/core/person/full.html:137
 msgid "Guardians / Parents"
 msgstr ""
 
-#: models.py:162
+#: models.py:173
 msgid "Primary group"
 msgstr ""
 
-#: models.py:165 models.py:423 models.py:447 models.py:532 models.py:720
-#: templates/core/person/full.html:112
+#: models.py:176 models.py:461 models.py:485 models.py:570 models.py:805
+#: templates/core/person/full.html:120
 msgid "Description"
 msgstr "Description"
 
-#: models.py:296
+#: models.py:313
 msgid "Title of field"
 msgstr ""
 
-#: models.py:298
+#: models.py:315
 msgid "Type of field"
 msgstr ""
 
-#: models.py:305
+#: models.py:322
 msgid "Addtitional field for groups"
 msgstr ""
 
-#: models.py:306
+#: models.py:323
 msgid "Addtitional fields for groups"
 msgstr ""
 
-#: models.py:318
+#: models.py:337
 msgid "Group"
 msgstr "Groupe"
 
-#: models.py:320
+#: models.py:340
 msgid "Can assign child groups to groups"
 msgstr ""
 
-#: models.py:330
+#: models.py:341
+#, fuzzy
+#| msgid "Contact details"
+msgid "Can view statistics about group."
+msgstr "Détails de contact"
+
+#: models.py:352
 #, fuzzy
 #| msgid "Last name"
 msgid "Long name"
 msgstr "Nom de famille"
 
-#: models.py:340 templates/core/group/full.html:65
+#: models.py:362 templates/core/group/full.html:85
 msgid "Members"
 msgstr ""
 
-#: models.py:343 templates/core/group/full.html:62
+#: models.py:365 templates/core/group/full.html:82
 msgid "Owners"
 msgstr "Propriétaires"
 
-#: models.py:350 templates/core/group/full.html:54
+#: models.py:372 templates/core/group/full.html:55
 msgid "Parent groups"
 msgstr ""
 
-#: models.py:358
+#: models.py:380
 msgid "Type of group"
 msgstr ""
 
-#: models.py:419
+#: models.py:457
 msgid "User"
 msgstr ""
 
-#: models.py:422 models.py:446 models.py:531
+#: models.py:460 models.py:484 models.py:569
 #: templates/core/announcement/list.html:18
 msgid "Title"
 msgstr ""
 
-#: models.py:425
+#: models.py:463
 msgid "Application"
 msgstr ""
 
-#: models.py:431
+#: models.py:469
 msgid "Activity"
 msgstr ""
 
-#: models.py:432
+#: models.py:470
 msgid "Activities"
 msgstr ""
 
-#: models.py:438
+#: models.py:476
 msgid "Sender"
 msgstr ""
 
-#: models.py:443
+#: models.py:481
 msgid "Recipient"
 msgstr ""
 
-#: models.py:448 models.py:701
+#: models.py:486 models.py:786
 msgid "Link"
 msgstr ""
 
-#: models.py:450
+#: models.py:488
 msgid "Read"
 msgstr ""
 
-#: models.py:451
+#: models.py:489
 msgid "Sent"
 msgstr ""
 
-#: models.py:464
+#: models.py:502
 msgid "Notification"
 msgstr ""
 
-#: models.py:465
+#: models.py:503
 msgid "Notifications"
 msgstr ""
 
-#: models.py:533
+#: models.py:571
 msgid "Link to detailed view"
 msgstr ""
 
-#: models.py:536
+#: models.py:574
 msgid "Date and time from when to show"
 msgstr ""
 
-#: models.py:539
+#: models.py:577
 msgid "Date and time until when to show"
 msgstr ""
 
-#: models.py:563
+#: models.py:601
 msgid "Announcement"
 msgstr ""
 
-#: models.py:601
+#: models.py:639
 msgid "Announcement recipient"
 msgstr ""
 
-#: models.py:602
+#: models.py:640
 msgid "Announcement recipients"
 msgstr ""
 
-#: models.py:652
+#: models.py:690
 msgid "Widget Title"
 msgstr ""
 
-#: models.py:653
+#: models.py:691
 msgid "Activate Widget"
 msgstr ""
 
-#: models.py:671
+#: models.py:694
+msgid "Size on mobile devices"
+msgstr ""
+
+#: models.py:695
+msgid "<= 600 px, 12 columns"
+msgstr ""
+
+#: models.py:700
+msgid "Size on tablet devices"
+msgstr ""
+
+#: models.py:701
+msgid "> 600 px, 12 columns"
+msgstr ""
+
+#: models.py:706
+msgid "Size on desktop devices"
+msgstr ""
+
+#: models.py:707
+msgid "> 992 px, 12 columns"
+msgstr ""
+
+#: models.py:712
+msgid "Size on large desktop devices"
+msgstr ""
+
+#: models.py:713
+msgid "> 1200 px>, 12 columns"
+msgstr ""
+
+#: models.py:734
+msgid "Can edit default dashboard"
+msgstr ""
+
+#: models.py:735
 msgid "Dashboard Widget"
 msgstr ""
 
-#: models.py:672
+#: models.py:736
 msgid "Dashboard Widgets"
 msgstr ""
 
-#: models.py:678
+#: models.py:741
+msgid "Dashboard widget"
+msgstr ""
+
+#: models.py:746
+msgid "Order"
+msgstr ""
+
+#: models.py:747
+msgid "Part of the default dashboard"
+msgstr ""
+
+#: models.py:755
+msgid "Dashboard widget order"
+msgstr ""
+
+#: models.py:756
+msgid "Dashboard widget orders"
+msgstr ""
+
+#: models.py:762
 msgid "Menu ID"
 msgstr ""
 
-#: models.py:690
+#: models.py:775
 msgid "Custom menu"
 msgstr ""
 
-#: models.py:691
+#: models.py:776
 msgid "Custom menus"
 msgstr ""
 
-#: models.py:698
+#: models.py:783
 msgid "Menu"
 msgstr ""
 
-#: models.py:702
+#: models.py:787
 msgid "Icon"
 msgstr ""
 
-#: models.py:708
+#: models.py:793
 msgid "Custom menu item"
 msgstr ""
 
-#: models.py:709
+#: models.py:794
 msgid "Custom menu items"
 msgstr ""
 
-#: models.py:719
+#: models.py:804
 msgid "Title of type"
 msgstr ""
 
-#: models.py:726 templates/core/group/full.html:46
+#: models.py:811 templates/core/group/full.html:47
 #, fuzzy
 #| msgid "Group"
 msgid "Group type"
 msgstr "Groupe"
 
-#: models.py:736
+#: models.py:821
 #, fuzzy
 #| msgid "Contact details"
 msgid "Can view system status"
 msgstr "Détails de contact"
 
-#: models.py:737
+#: models.py:822
 #, fuzzy
 #| msgid "Contact details"
 msgid "Can link persons to accounts"
 msgstr "Détails de contact"
 
-#: models.py:738
+#: models.py:823
 msgid "Can manage data"
 msgstr ""
 
-#: models.py:739
+#: models.py:824
 #, fuzzy
 #| msgid "Contact details"
 msgid "Can impersonate"
 msgstr "Détails de contact"
 
-#: models.py:740
+#: models.py:825
 msgid "Can use search"
 msgstr ""
 
-#: models.py:741
+#: models.py:826
 msgid "Can change site preferences"
 msgstr ""
 
-#: models.py:742
+#: models.py:827
 msgid "Can change person preferences"
 msgstr ""
 
-#: models.py:743
+#: models.py:828
 msgid "Can change group preferences"
 msgstr ""
 
-#: preferences.py:24
+#: models.py:864
+msgid "Related data check task"
+msgstr ""
+
+#: models.py:872
+msgid "Issue solved"
+msgstr ""
+
+#: models.py:873
+msgid "Notification sent"
+msgstr ""
+
+#: models.py:886
+msgid "Data check result"
+msgstr ""
+
+#: models.py:887
+msgid "Data check results"
+msgstr ""
+
+#: models.py:889
+msgid "Can run data checks"
+msgstr ""
+
+#: models.py:890
+msgid "Can solve data check problems"
+msgstr ""
+
+#: preferences.py:27
 msgid "Authentication"
 msgstr ""
 
-#: preferences.py:33
+#: preferences.py:28
+msgid "Internationalisation"
+msgstr ""
+
+#: preferences.py:37
 msgid "Site title"
 msgstr ""
 
-#: preferences.py:42
+#: preferences.py:46
 #, fuzzy
 #| msgid "Description"
 msgid "Site description"
 msgstr "Description"
 
-#: preferences.py:51
+#: preferences.py:55
 msgid "Primary colour"
 msgstr ""
 
-#: preferences.py:60
+#: preferences.py:64
 msgid "Secondary colour"
 msgstr ""
 
-#: preferences.py:68
+#: preferences.py:72
 msgid "Logo"
 msgstr ""
 
-#: preferences.py:76
+#: preferences.py:80
 msgid "Favicon"
 msgstr ""
 
-#: preferences.py:84
+#: preferences.py:88
 msgid "PWA-Icon"
 msgstr ""
 
-#: preferences.py:93
+#: preferences.py:97
 #, fuzzy
 #| msgid "Last name"
 msgid "Mail out name"
 msgstr "Nom de famille"
 
-#: preferences.py:102
+#: preferences.py:106
 msgid "Mail out address"
 msgstr ""
 
-#: preferences.py:112
+#: preferences.py:116
 msgid "Link to privacy policy"
 msgstr ""
 
-#: preferences.py:122
+#: preferences.py:126
 msgid "Link to imprint"
 msgstr ""
 
-#: preferences.py:132
+#: preferences.py:136
 msgid "Name format for addressing"
 msgstr ""
 
-#: preferences.py:146
+#: preferences.py:150
 msgid "Channels to use for notifications"
 msgstr ""
 
-#: preferences.py:156
+#: preferences.py:160
 msgid "Regular expression to match primary group, e.g. '^Class .*'"
 msgstr ""
 
-#: preferences.py:165
+#: preferences.py:169
 msgid "Field on person to match primary group against"
 msgstr ""
 
-#: preferences.py:177
+#: preferences.py:181
 msgid "Display name of the school"
 msgstr ""
 
-#: preferences.py:186
+#: preferences.py:190
 msgid "Official name of the school, e.g. as given by supervisory authority"
 msgstr ""
 
-#: preferences.py:194
+#: preferences.py:198
 msgid "Enabled custom authentication backends"
 msgstr ""
 
-#: settings.py:300
+#: preferences.py:211
+msgid "Available languages"
+msgstr ""
+
+#: preferences.py:223
+msgid "Send emails if data checks detect problems"
+msgstr ""
+
+#: preferences.py:234
+msgid "Email recipients for data checks problem emails"
+msgstr ""
+
+#: preferences.py:245
+msgid "Email recipient groups for data checks problem emails"
+msgstr ""
+
+#: settings.py:322
 msgid "English"
 msgstr ""
 
-#: settings.py:301
+#: settings.py:323
 msgid "German"
 msgstr ""
 
-#: settings.py:302
+#: settings.py:324
 msgid "French"
 msgstr ""
 
-#: settings.py:303
+#: settings.py:325
 msgid "Norwegian (bokmål)"
 msgstr ""
 
 #: tables.py:19 templates/core/announcement/list.html:36
-#: templates/core/group/full.html:23 templates/core/person/full.html:22
+#: templates/core/group/full.html:24 templates/core/person/full.html:23
 msgid "Edit"
 msgstr ""
 
-#: tables.py:21 templates/core/announcement/list.html:22
+#: tables.py:21 tables.py:89 templates/core/announcement/list.html:22
 msgid "Actions"
 msgstr ""
 
-#: tables.py:56 tables.py:57 tables.py:71
-#: templates/core/announcement/list.html:42 templates/core/group/full.html:30
-#: templates/core/pages/delete.html:22 templates/core/person/full.html:29
+#: tables.py:56 tables.py:57 tables.py:71 tables.py:87
+#: templates/core/announcement/list.html:42 templates/core/group/full.html:31
+#: templates/core/pages/delete.html:22 templates/core/person/full.html:30
 msgid "Delete"
 msgstr ""
 
@@ -804,21 +937,21 @@ msgstr ""
 msgid "Create additional field"
 msgstr ""
 
-#: templates/core/announcement/form.html:10
-#: templates/core/announcement/form.html:17
+#: templates/core/announcement/form.html:14
+#: templates/core/announcement/form.html:21
 msgid "Edit announcement"
 msgstr ""
 
-#: templates/core/announcement/form.html:12
+#: templates/core/announcement/form.html:16
 msgid "Publish announcement"
 msgstr ""
 
-#: templates/core/announcement/form.html:19
+#: templates/core/announcement/form.html:23
 #: templates/core/announcement/list.html:13
 msgid "Publish new announcement"
 msgstr ""
 
-#: templates/core/announcement/form.html:30
+#: templates/core/announcement/form.html:34
 msgid "Save und publish announcement"
 msgstr ""
 
@@ -858,6 +991,124 @@ msgstr ""
 msgid "Powered by AlekSIS"
 msgstr ""
 
+#: templates/core/dashboard_widget/create.html:8
+#: templates/core/dashboard_widget/create.html:12
+#, fuzzy, python-format
+#| msgid "Contact details"
+msgid "Create %(widget)s"
+msgstr "Détails de contact"
+
+#: templates/core/dashboard_widget/edit.html:8
+#: templates/core/dashboard_widget/edit.html:12
+#, python-format
+msgid "Edit %(widget)s"
+msgstr ""
+
+#: templates/core/dashboard_widget/list.html:17
+#, fuzzy, python-format
+#| msgid "Contact details"
+msgid "Create %(name)s"
+msgstr "Détails de contact"
+
+#: templates/core/dashboard_widget/list.html:25
+#: templates/core/edit_dashboard.html:8 templates/core/edit_dashboard.html:15
+msgid "Edit default dashboard"
+msgstr ""
+
+#: templates/core/data_check/list.html:15
+msgid "Check data again"
+msgstr ""
+
+#: templates/core/data_check/list.html:22
+msgid "The system detected some problems with your data."
+msgstr ""
+
+#: templates/core/data_check/list.html:23
+msgid ""
+"Please go through all data and check whether some extra action is\n"
+"          needed."
+msgstr ""
+
+#: templates/core/data_check/list.html:31
+msgid "Everything is fine."
+msgstr ""
+
+#: templates/core/data_check/list.html:32
+msgid "The system hasn't detected any problems with your data."
+msgstr ""
+
+#: templates/core/data_check/list.html:40
+msgid "Detected problems"
+msgstr ""
+
+#: templates/core/data_check/list.html:45
+msgid "Affected object"
+msgstr ""
+
+#: templates/core/data_check/list.html:46
+msgid "Detected problem"
+msgstr ""
+
+#: templates/core/data_check/list.html:47
+#, fuzzy
+#| msgid "Contact details"
+msgid "Show details"
+msgstr "Détails de contact"
+
+#: templates/core/data_check/list.html:48
+msgid "Options to solve the problem"
+msgstr ""
+
+#: templates/core/data_check/list.html:62
+msgid "Show object"
+msgstr ""
+
+#: templates/core/data_check/list.html:84
+msgid "Registered checks"
+msgstr ""
+
+#: templates/core/data_check/list.html:88
+msgid ""
+"\n"
+"            The system will check for the following problems:\n"
+"          "
+msgstr ""
+
+#: templates/core/edit_dashboard.html:6 templates/core/edit_dashboard.html:13
+#: templates/core/index.html:14
+msgid "Edit dashboard"
+msgstr ""
+
+#: templates/core/edit_dashboard.html:24
+msgid ""
+"\n"
+"          On this page you can arrange your personal dashboard. You can drag any items from \"Available widgets\" to \"Your\n"
+"          Dashboard\" or change the order by moving the widgets. After you have finished, please don't forget to click on\n"
+"          \"Save\".\n"
+"        "
+msgstr ""
+
+#: templates/core/edit_dashboard.html:30
+msgid ""
+"\n"
+"          On this page you can arrange the default dashboard which is shown when a user doesn't arrange his own\n"
+"          dashboard. You can drag any items from \"Available widgets\" to \"Default Dashboard\" or change the order\n"
+"          by moving the widgets. After you have finished, please don't forget to click on \"Save\".\n"
+"        "
+msgstr ""
+
+#: templates/core/edit_dashboard.html:48
+msgid "Available widgets"
+msgstr ""
+
+#: templates/core/edit_dashboard.html:57
+msgid "Your dashboard"
+msgstr ""
+
+#: templates/core/edit_dashboard.html:59
+msgid "Default dashboard"
+msgstr ""
+
 #: templates/core/group/child_groups.html:18
 msgid ""
 "\n"
@@ -930,14 +1181,38 @@ msgstr ""
 msgid "Save and next"
 msgstr ""
 
-#: templates/core/group/edit.html:6 templates/core/group/edit.html:7
+#: templates/core/group/edit.html:11 templates/core/group/edit.html:12
 msgid "Edit group"
 msgstr ""
 
-#: templates/core/group/full.html:37 templates/core/person/full.html:36
+#: templates/core/group/full.html:38 templates/core/person/full.html:37
 msgid "Change preferences"
 msgstr ""
 
+#: templates/core/group/full.html:64
+msgid "Statistics"
+msgstr ""
+
+#: templates/core/group/full.html:67
+msgid "Count of members"
+msgstr ""
+
+#: templates/core/group/full.html:71
+msgid "Average age"
+msgstr ""
+
+#: templates/core/group/full.html:76
+msgid "Age range"
+msgstr ""
+
+#: templates/core/group/full.html:76
+msgid "years to"
+msgstr ""
+
+#: templates/core/group/full.html:76
+msgid "years "
+msgstr ""
+
 #: templates/core/group/list.html:14
 msgid "Create group"
 msgstr ""
@@ -970,23 +1245,31 @@ msgstr "Groupe"
 msgid "Home"
 msgstr ""
 
-#: templates/core/index.html:42
+#: templates/core/index.html:50
+msgid ""
+"\n"
+"          You didn't customise your dashboard so that you see the system default. Please click on \"Edit dashboard\" to\n"
+"          customise your personal dashboard.\n"
+"        "
+msgstr ""
+
+#: templates/core/index.html:59
 msgid "Last activities"
 msgstr ""
 
-#: templates/core/index.html:60
+#: templates/core/index.html:77
 msgid "No activities available yet."
 msgstr ""
 
-#: templates/core/index.html:65
+#: templates/core/index.html:82
 msgid "Recent notifications"
 msgstr ""
 
-#: templates/core/index.html:81
+#: templates/core/index.html:98
 msgid "More information →"
 msgstr ""
 
-#: templates/core/index.html:88
+#: templates/core/index.html:105
 msgid "No notifications available yet."
 msgstr ""
 
@@ -1065,21 +1348,6 @@ msgid ""
 "    "
 msgstr ""
 
-#: templates/core/pages/offline.html:6
-msgid ""
-"No internet\n"
-"    connection."
-msgstr ""
-
-#: templates/core/pages/offline.html:10
-msgid ""
-"\n"
-"      There was an error accessing this page. You probably don't have an internet connection. Check to see if your WiFi\n"
-"      or mobile data is turned on and try again. If you think you are connected, please contact the system\n"
-"      administrators:\n"
-"    "
-msgstr ""
-
 #: templates/core/pages/progress.html:27
 msgid ""
 "\n"
@@ -1201,37 +1469,19 @@ msgid ""
 "            "
 msgstr ""
 
-#: templates/core/partials/crud_events.html:10
-#, python-format
-msgid ""
-"\n"
-"              Created by %(person)s\n"
-"            "
-msgstr ""
-
-#: templates/core/partials/crud_events.html:14
-#: templates/core/partials/crud_events.html:22
-#: templates/core/partials/crud_events.html:26
-#, python-format
-msgid ""
-"\n"
-"              Updated by %(person)s\n"
-"            "
+#: templates/core/partials/crud_events.html:15
+msgid "Changed by"
 msgstr ""
 
-#: templates/core/partials/crud_events.html:18
-#, python-format
-msgid ""
-"\n"
-"              Deleted by %(person)s\n"
-"            "
+#: templates/core/partials/crud_events.html:15
+msgid "Unknown"
 msgstr ""
 
-#: templates/core/partials/language_form.html:16
+#: templates/core/partials/language_form.html:15
 msgid "Language"
 msgstr ""
 
-#: templates/core/partials/language_form.html:28
+#: templates/core/partials/language_form.html:27
 msgid "Select language"
 msgstr ""
 
@@ -1252,11 +1502,12 @@ msgid ""
 "          "
 msgstr ""
 
-#: templates/core/person/accounts.html:7 templates/core/person/accounts.html:9
+#: templates/core/person/accounts.html:12
+#: templates/core/person/accounts.html:14
 msgid "Link persons to accounts"
 msgstr ""
 
-#: templates/core/person/accounts.html:16
+#: templates/core/person/accounts.html:21
 msgid ""
 "\n"
 "        You can use this form to assign user accounts to persons. Use the\n"
@@ -1266,28 +1517,34 @@ msgid ""
 "      "
 msgstr ""
 
-#: templates/core/person/accounts.html:31
-#: templates/core/person/accounts.html:55
+#: templates/core/person/accounts.html:36
+#: templates/core/person/accounts.html:60
 msgid "Update"
 msgstr ""
 
-#: templates/core/person/accounts.html:37
+#: templates/core/person/accounts.html:42
 msgid "Existing account"
 msgstr ""
 
-#: templates/core/person/accounts.html:38
+#: templates/core/person/accounts.html:43
 msgid "New account"
 msgstr ""
 
-#: templates/core/person/edit.html:11 templates/core/person/edit.html:12
+#: templates/core/person/edit.html:12 templates/core/person/edit.html:13
 msgid "Edit person"
 msgstr ""
 
-#: templates/core/person/full.html:42
+#: templates/core/person/full.html:44
+#, fuzzy
+#| msgid "Contact details"
+msgid "Impersonate"
+msgstr "Détails de contact"
+
+#: templates/core/person/full.html:50
 msgid "Contact details"
 msgstr "Détails de contact"
 
-#: templates/core/person/full.html:122
+#: templates/core/person/full.html:130
 msgid "Children"
 msgstr ""
 
@@ -1333,14 +1590,29 @@ msgstr ""
 msgid "Save preferences"
 msgstr ""
 
-#: templates/dynamic_preferences/sections.html:7
-msgid "All"
-msgstr ""
-
 #: templates/impersonate/list_users.html:8
 msgid "Impersonate user"
 msgstr ""
 
+#: templates/offline.html:5
+msgid "Network error"
+msgstr ""
+
+#: templates/offline.html:8
+msgid ""
+"No internet\n"
+"    connection."
+msgstr ""
+
+#: templates/offline.html:12
+msgid ""
+"\n"
+"      There was an error accessing this page. You probably don't have an internet connection. Check to see if your WiFi\n"
+"      or mobile data is turned on and try again. If you think you are connected, please contact the system\n"
+"      administrators:\n"
+"    "
+msgstr ""
+
 #: templates/search/search.html:8
 msgid "Global Search"
 msgstr ""
@@ -1361,6 +1633,41 @@ msgstr ""
 msgid "Please enter a search term above."
 msgstr ""
 
+#: templates/templated_email/data_checks.email:4
+msgid "The system detected some new problems with your data."
+msgstr ""
+
+#: templates/templated_email/data_checks.email:8
+#: templates/templated_email/data_checks.email:24
+msgid "Hello,"
+msgstr ""
+
+#: templates/templated_email/data_checks.email:10
+msgid ""
+"\n"
+"  the system detected some new problems with your data.\n"
+"  Please take some time to inspect them and solve the issues or mark them as ignored.\n"
+" "
+msgstr ""
+
+#: templates/templated_email/data_checks.email:26
+msgid ""
+"\n"
+"   the system detected some new problems with your data.\n"
+"   Please take some time to inspect them and solve the issues or mark them as ignored.\n"
+"  "
+msgstr ""
+
+#: templates/templated_email/data_checks.email:34
+#, fuzzy
+#| msgid "Description"
+msgid "Problem description"
+msgstr "Description"
+
+#: templates/templated_email/data_checks.email:35
+msgid "Count of objects with new problems"
+msgstr ""
+
 #: templates/templated_email/notification.email:3
 msgid "New notification for"
 msgstr ""
@@ -1743,58 +2050,91 @@ msgstr ""
 msgid "SMS"
 msgstr ""
 
-#: views.py:122
+#: views.py:141
 msgid "The school term has been created."
 msgstr ""
 
-#: views.py:133
+#: views.py:153
 msgid "The school term has been saved."
 msgstr ""
 
-#: views.py:273
+#: views.py:298
 msgid "The child groups were successfully saved."
 msgstr ""
 
-#: views.py:309
+#: views.py:336
 msgid "The person has been saved."
 msgstr ""
 
-#: views.py:346
+#: views.py:375
 msgid "The group has been saved."
 msgstr ""
 
-#: views.py:434
+#: views.py:467
 msgid "The announcement has been saved."
 msgstr ""
 
-#: views.py:450
+#: views.py:483
 msgid "The announcement has been deleted."
 msgstr ""
 
-#: views.py:521
+#: views.py:562
 msgid "The preferences have been saved successfully."
 msgstr ""
 
-#: views.py:544
+#: views.py:586
 msgid "The person has been deleted."
 msgstr ""
 
-#: views.py:557
+#: views.py:600
 msgid "The group has been deleted."
 msgstr ""
 
-#: views.py:588
+#: views.py:632
 msgid "The additional_field has been saved."
 msgstr ""
 
-#: views.py:622
+#: views.py:666
 msgid "The additional field has been deleted."
 msgstr ""
 
-#: views.py:646
+#: views.py:691
 msgid "The group type has been saved."
 msgstr ""
 
-#: views.py:676
+#: views.py:721
 msgid "The group type has been deleted."
 msgstr ""
+
+#: views.py:749
+msgid "The data check has been started. Please note that it may take a while before you are able to fetch the data on this page."
+msgstr ""
+
+#: views.py:754
+msgid "The data check has finished."
+msgstr ""
+
+#: views.py:769
+#, python-brace-format
+msgid "The solve option '{solve_option_obj.verbose_name}' "
+msgstr ""
+
+#: views.py:811
+msgid "The dashboard widget has been saved."
+msgstr ""
+
+#: views.py:841
+msgid "The dashboard widget has been created."
+msgstr ""
+
+#: views.py:851
+msgid "The dashboard widget has been deleted."
+msgstr ""
+
+#: views.py:914
+msgid "Your dashboard configuration has been saved successfully."
+msgstr ""
+
+#: views.py:916
+msgid "The configuration of the default dashboard has been saved successfully."
+msgstr ""
diff --git a/aleksis/core/locale/fr/LC_MESSAGES/djangojs.po b/aleksis/core/locale/fr/LC_MESSAGES/djangojs.po
index 62da02ce6b9e58455b9ed6547a5d1380b2b062ac..83a1c140c8889eef6a1633f00a741cd110c52e05 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: 2020-08-02 16:29+0200\n"
+"POT-Creation-Date: 2021-01-11 21:30+0100\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -18,14 +18,18 @@ msgstr ""
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=2; plural=(n > 1);\n"
 
-#: static/js/main.js:21
+#: static/js/main.js:15
 msgid "Today"
 msgstr ""
 
-#: static/js/main.js:22
+#: static/js/main.js:16
 msgid "Cancel"
 msgstr ""
 
-#: static/js/main.js:23
+#: static/js/main.js:17
 msgid "OK"
 msgstr ""
+
+#: static/js/main.js:118
+msgid "This page may contain outdated information since there is no internet connection."
+msgstr ""
diff --git a/aleksis/core/locale/la/LC_MESSAGES/django.po b/aleksis/core/locale/la/LC_MESSAGES/django.po
index 6fa38602c123109a48b5f34b07415b76a666f5a5..5fb260aac6828ea32031b9b03bd64424984cd8ab 100644
--- a/aleksis/core/locale/la/LC_MESSAGES/django.po
+++ b/aleksis/core/locale/la/LC_MESSAGES/django.po
@@ -7,11 +7,10 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2020-08-02 16:29+0200\n"
+"POT-Creation-Date: 2021-01-11 21:30+0100\n"
 "PO-Revision-Date: 2020-12-19 12:57+0000\n"
 "Last-Translator: Julian <leuckerj@gmail.com>\n"
-"Language-Team: Latin <https://translate.edugit.org/projects/aleksis/aleksis/"
-"la/>\n"
+"Language-Team: Latin <https://translate.edugit.org/projects/aleksis/aleksis/la/>\n"
 "Language: la\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
@@ -19,6 +18,15 @@ msgstr ""
 "Plural-Forms: nplurals=2; plural=n != 1;\n"
 "X-Generator: Weblate 4.3.2\n"
 
+#: data_checks.py:53
+msgid "Ignore problem"
+msgstr ""
+
+#: data_checks.py:174
+#, python-brace-format
+msgid "Solve option '{solve_option_obj.verbose_name}' "
+msgstr ""
+
 #: filters.py:37 templates/core/base.html:77 templates/core/group/list.html:20
 #: templates/core/person/list.html:24 templates/search/search.html:7
 #: templates/search/search.html:22
@@ -35,100 +43,106 @@ msgstr "Quaerere cum breve nomine"
 msgid "Search by contact details"
 msgstr "Inscriptio electronica"
 
-#: forms.py:46
+#: forms.py:54
 msgid "You cannot set a new username when also selecting an existing user."
 msgstr ""
 
-#: forms.py:50
+#: forms.py:58
 msgid "This username is already in use."
 msgstr ""
 
-#: forms.py:74
+#: forms.py:82
 msgid "Base data"
 msgstr ""
 
-#: forms.py:80
+#: forms.py:88
 #, fuzzy
 #| msgid "E-mail address"
 msgid "Address"
 msgstr "Inscriptio electronica"
 
-#: forms.py:81
+#: forms.py:89
 msgid "Contact data"
 msgstr ""
 
-#: forms.py:83
+#: forms.py:91
 msgid "Advanced personal data"
 msgstr ""
 
-#: forms.py:114
+#: forms.py:134
 msgid "New user"
 msgstr ""
 
-#: forms.py:114
+#: forms.py:134
 #, fuzzy
 #| msgid "Persons and accounts"
 msgid "Create a new account"
 msgstr "Personae et computi"
 
-#: forms.py:126 models.py:91
+#: forms.py:146 models.py:102
 msgid "School term"
 msgstr "Anus scolae"
 
-#: forms.py:127
+#: forms.py:147
 #, fuzzy
 #| msgid "Data management"
 msgid "Common data"
 msgstr "Adminstratio datarum"
 
-#: forms.py:128 forms.py:170 menus.py:152 models.py:105
+#: forms.py:148 forms.py:197 menus.py:169 models.py:116
 #: templates/core/person/list.html:8 templates/core/person/list.html:9
 msgid "Persons"
 msgstr "personae"
 
-#: forms.py:129
+#: forms.py:149
 #, fuzzy
 #| msgid "Additional name(s)"
 msgid "Additional data"
 msgstr "addita nomines"
 
-#: forms.py:163 forms.py:166 models.py:35
+#: forms.py:189 forms.py:192 models.py:45
 msgid "Date"
 msgstr "dies"
 
-#: forms.py:164 forms.py:167 models.py:43
+#: forms.py:190 forms.py:193 models.py:53
 msgid "Time"
 msgstr "tempus"
 
-#: forms.py:172 menus.py:160 models.py:319 templates/core/group/list.html:8
-#: templates/core/group/list.html:9 templates/core/person/full.html:136
+#: forms.py:210 menus.py:177 models.py:338 templates/core/group/list.html:8
+#: templates/core/group/list.html:9 templates/core/person/full.html:144
 msgid "Groups"
 msgstr "Greges"
 
-#: forms.py:176
+#: forms.py:220
 msgid "From when until when should the announcement be displayed?"
 msgstr ""
 
-#: forms.py:179
+#: forms.py:223
 msgid "Who should see the announcement?"
 msgstr "Quis nuntium videatne?"
 
-#: forms.py:180
+#: forms.py:224
 msgid "Write your announcement:"
 msgstr "Scribe nuntium:"
 
-#: forms.py:219
+#: forms.py:263
 msgid "You are not allowed to create announcements which are only valid in the past."
 msgstr ""
 
-#: forms.py:223
+#: forms.py:267
 msgid "The from date and time must be earlier then the until date and time."
 msgstr ""
 
-#: forms.py:232
+#: forms.py:276
 msgid "You need at least one recipient."
 msgstr ""
 
+#: health_checks.py:15
+#, fuzzy
+#| msgid "Write your announcement:"
+msgid "There are unresolved data problems."
+msgstr "Scribe nuntium:"
+
 #: menus.py:7 templates/two_factor/core/login.html:6
 #: templates/two_factor/core/login.html:10
 #: templates/two_factor/core/login.html:86
@@ -167,603 +181,739 @@ msgstr ""
 msgid "Admin"
 msgstr "Administratio"
 
-#: menus.py:75 models.py:564 templates/core/announcement/list.html:7
+#: menus.py:75 models.py:602 templates/core/announcement/list.html:7
 #: templates/core/announcement/list.html:8
 msgid "Announcements"
 msgstr "Nuntii"
 
-#: menus.py:86 models.py:92 templates/core/school_term/list.html:8
+#: menus.py:86 models.py:103 templates/core/school_term/list.html:8
 #: templates/core/school_term/list.html:9
 msgid "School terms"
 msgstr "ani scolae"
 
-#: menus.py:97 templates/core/management/data_management.html:6
+#: menus.py:97 templates/core/dashboard_widget/list.html:8
+#: templates/core/dashboard_widget/list.html:9
+#, fuzzy
+#| msgid "Dashboard"
+msgid "Dashboard widgets"
+msgstr "Forum"
+
+#: menus.py:108 templates/core/management/data_management.html:6
 #: templates/core/management/data_management.html:7
 msgid "Data management"
 msgstr "Adminstratio datarum"
 
-#: menus.py:105 templates/core/pages/system_status.html:5
+#: menus.py:116 templates/core/pages/system_status.html:5
 #: templates/core/pages/system_status.html:7
 msgid "System status"
 msgstr "Status systemae"
 
-#: menus.py:116
+#: menus.py:127
 msgid "Impersonation"
 msgstr "Simulare aliquem"
 
-#: menus.py:124
+#: menus.py:135
 #, fuzzy
 #| msgid "Notification"
 msgid "Configuration"
 msgstr "Nuntius"
 
-#: menus.py:135
+#: menus.py:146 templates/core/data_check/list.html:9
+#: templates/core/data_check/list.html:10
+#, fuzzy
+#| msgid "System status"
+msgid "Data checks"
+msgstr "Status systemae"
+
+#: menus.py:152
 msgid "Backend Admin"
 msgstr ""
 
-#: menus.py:143
+#: menus.py:160
 msgid "People"
 msgstr "Personae"
 
-#: menus.py:168 models.py:727 templates/core/group_type/list.html:8
+#: menus.py:185 models.py:812 templates/core/group_type/list.html:8
 #: templates/core/group_type/list.html:9
 #, fuzzy
 #| msgid "Groups"
 msgid "Group types"
 msgstr "Greges"
 
-#: menus.py:179
+#: menus.py:196
 msgid "Persons and accounts"
 msgstr "Personae et computi"
 
-#: menus.py:190
+#: menus.py:207
 msgid "Groups and child groups"
 msgstr ""
 
-#: menus.py:201 models.py:363 templates/core/additional_field/list.html:8
+#: menus.py:218 models.py:385 templates/core/additional_field/list.html:8
 #: templates/core/additional_field/list.html:9
 #, fuzzy
 #| msgid "Additional name(s)"
 msgid "Additional fields"
 msgstr "addita nomines"
 
-#: menus.py:216 templates/core/group/child_groups.html:7
+#: menus.py:233 templates/core/group/child_groups.html:7
 #: templates/core/group/child_groups.html:9
 msgid "Assign child groups to groups"
 msgstr ""
 
-#: mixins.py:406
+#: mixins.py:384
 #, fuzzy
 #| msgid "Edit school term"
 msgid "Linked school term"
 msgstr "Muta anum scolae"
 
-#: models.py:33
+#: models.py:43
 msgid "Boolean (Yes/No)"
 msgstr ""
 
-#: models.py:34
+#: models.py:44
 msgid "Text (one line)"
 msgstr ""
 
-#: models.py:36
+#: models.py:46
 msgid "Date and time"
 msgstr "Dies et hora"
 
-#: models.py:37
+#: models.py:47
 msgid "Decimal number"
 msgstr ""
 
-#: models.py:38 models.py:146
+#: models.py:48 models.py:157
 msgid "E-mail address"
 msgstr "Inscriptio electronica"
 
-#: models.py:39
+#: models.py:49
 msgid "Integer"
 msgstr ""
 
-#: models.py:40
+#: models.py:50
 #, fuzzy
 #| msgid "E-mail address"
 msgid "IP address"
 msgstr "Inscriptio electronica"
 
-#: models.py:41
+#: models.py:51
 msgid "Boolean or empty (Yes/No/Neither)"
 msgstr ""
 
-#: models.py:42
+#: models.py:52
 msgid "Text (multi-line)"
 msgstr ""
 
-#: models.py:44
+#: models.py:54
 msgid "URL / Link"
 msgstr ""
 
-#: models.py:56 models.py:700
+#: models.py:66 models.py:785
 msgid "Name"
 msgstr "Nomen"
 
-#: models.py:58
+#: models.py:68
 msgid "Start date"
 msgstr ""
 
-#: models.py:59
+#: models.py:69
 msgid "End date"
 msgstr ""
 
-#: models.py:77
+#: models.py:88
 msgid "The start date must be earlier than the end date."
 msgstr ""
 
-#: models.py:84
+#: models.py:95
 msgid "There is already a school term for this time or a part of this time."
 msgstr ""
 
-#: models.py:104 templates/core/person/accounts.html:36
+#: models.py:115 models.py:744 templates/core/person/accounts.html:41
 msgid "Person"
 msgstr "Persona"
 
-#: models.py:107
+#: models.py:118
 #, fuzzy
 #| msgid "E-mail address"
 msgid "Can view address"
 msgstr "Inscriptio electronica"
 
-#: models.py:108
+#: models.py:119
 #, fuzzy
 #| msgid "E-mail address"
 msgid "Can view contact details"
 msgstr "Inscriptio electronica"
 
-#: models.py:109
+#: models.py:120
 #, fuzzy
 #| msgid "E-mail address"
 msgid "Can view photo"
 msgstr "Inscriptio electronica"
 
-#: models.py:110
+#: models.py:121
 #, fuzzy
 #| msgid "Persons and accounts"
 msgid "Can view persons groups"
 msgstr "Personae et computi"
 
-#: models.py:111
+#: models.py:122
 #, fuzzy
 #| msgid "Stop impersonation"
 msgid "Can view personal details"
 msgstr "Simulandum aliquem finire"
 
-#: models.py:116
+#: models.py:127
 msgid "female"
 msgstr "femininum"
 
-#: models.py:116
+#: models.py:127
 msgid "male"
 msgstr "maskulinum"
 
-#: models.py:124
+#: models.py:135
 msgid "Linked user"
 msgstr ""
 
-#: models.py:126
+#: models.py:137
 #, fuzzy
 #| msgid "Impersonation"
 msgid "Is person active?"
 msgstr "Simulare aliquem"
 
-#: models.py:128
+#: models.py:139
 msgid "First name"
 msgstr "Primus nomen"
 
-#: models.py:129
+#: models.py:140
 msgid "Last name"
 msgstr "Secondus nomen"
 
-#: models.py:131
+#: models.py:142
 msgid "Additional name(s)"
 msgstr "addita nomines"
 
-#: models.py:135 models.py:332
+#: models.py:146 models.py:354
 msgid "Short name"
 msgstr "Breve nomen"
 
-#: models.py:138
+#: models.py:149
 msgid "Street"
 msgstr "Via"
 
-#: models.py:139
+#: models.py:150
 msgid "Street number"
 msgstr "Numerus domini"
 
-#: models.py:140
+#: models.py:151
 msgid "Postal code"
 msgstr "Numerus directorius"
 
-#: models.py:141
+#: models.py:152
 msgid "Place"
 msgstr "Urbs"
 
-#: models.py:143
+#: models.py:154
 msgid "Home phone"
 msgstr "Numerus telephoni domi"
 
-#: models.py:144
+#: models.py:155
 msgid "Mobile phone"
 msgstr "Numerus telephoni mobilis"
 
-#: models.py:148
+#: models.py:159
 msgid "Date of birth"
 msgstr "Dies natalis"
 
-#: models.py:149
+#: models.py:160
 msgid "Sex"
 msgstr "Genus"
 
-#: models.py:151
+#: models.py:162
 msgid "Photo"
 msgstr "Photographia"
 
-#: models.py:155 templates/core/person/full.html:129
+#: models.py:166 templates/core/person/full.html:137
 msgid "Guardians / Parents"
 msgstr "Parentes"
 
-#: models.py:162
+#: models.py:173
 msgid "Primary group"
 msgstr ""
 
-#: models.py:165 models.py:423 models.py:447 models.py:532 models.py:720
-#: templates/core/person/full.html:112
+#: models.py:176 models.py:461 models.py:485 models.py:570 models.py:805
+#: templates/core/person/full.html:120
 msgid "Description"
 msgstr "Descriptio"
 
-#: models.py:296
+#: models.py:313
 msgid "Title of field"
 msgstr ""
 
-#: models.py:298
+#: models.py:315
 msgid "Type of field"
 msgstr ""
 
-#: models.py:305
+#: models.py:322
 #, fuzzy
 #| msgid "Additional name(s)"
 msgid "Addtitional field for groups"
 msgstr "addita nomines"
 
-#: models.py:306
+#: models.py:323
 #, fuzzy
 #| msgid "Additional name(s)"
 msgid "Addtitional fields for groups"
 msgstr "addita nomines"
 
-#: models.py:318
+#: models.py:337
 msgid "Group"
 msgstr "Grex"
 
-#: models.py:320
+#: models.py:340
 msgid "Can assign child groups to groups"
 msgstr ""
 
-#: models.py:330
+#: models.py:341
+#, fuzzy
+#| msgid "Persons and accounts"
+msgid "Can view statistics about group."
+msgstr "Personae et computi"
+
+#: models.py:352
 #, fuzzy
 #| msgid "Last name"
 msgid "Long name"
 msgstr "Secondus nomen"
 
-#: models.py:340 templates/core/group/full.html:65
+#: models.py:362 templates/core/group/full.html:85
 msgid "Members"
 msgstr ""
 
-#: models.py:343 templates/core/group/full.html:62
+#: models.py:365 templates/core/group/full.html:82
 msgid "Owners"
 msgstr ""
 
-#: models.py:350 templates/core/group/full.html:54
+#: models.py:372 templates/core/group/full.html:55
 msgid "Parent groups"
 msgstr ""
 
-#: models.py:358
+#: models.py:380
 msgid "Type of group"
 msgstr ""
 
-#: models.py:419
+#: models.py:457
 msgid "User"
 msgstr ""
 
-#: models.py:422 models.py:446 models.py:531
+#: models.py:460 models.py:484 models.py:569
 #: templates/core/announcement/list.html:18
 msgid "Title"
 msgstr "Titulus"
 
-#: models.py:425
+#: models.py:463
 msgid "Application"
 msgstr ""
 
-#: models.py:431
+#: models.py:469
 msgid "Activity"
 msgstr ""
 
-#: models.py:432
+#: models.py:470
 msgid "Activities"
 msgstr ""
 
-#: models.py:438
+#: models.py:476
 msgid "Sender"
 msgstr "Mittens"
 
-#: models.py:443
+#: models.py:481
 msgid "Recipient"
 msgstr ""
 
-#: models.py:448 models.py:701
+#: models.py:486 models.py:786
 msgid "Link"
 msgstr ""
 
-#: models.py:450
+#: models.py:488
 msgid "Read"
 msgstr ""
 
-#: models.py:451
+#: models.py:489
 msgid "Sent"
 msgstr ""
 
-#: models.py:464
+#: models.py:502
 #, fuzzy
 #| msgid "Notifications"
 msgid "Notification"
 msgstr "Nuntii"
 
-#: models.py:465
+#: models.py:503
 msgid "Notifications"
 msgstr "Nuntii"
 
-#: models.py:533
+#: models.py:571
 msgid "Link to detailed view"
 msgstr ""
 
-#: models.py:536
+#: models.py:574
 msgid "Date and time from when to show"
 msgstr ""
 
-#: models.py:539
+#: models.py:577
 msgid "Date and time until when to show"
 msgstr ""
 
-#: models.py:563
+#: models.py:601
 #, fuzzy
 #| msgid "Announcements"
 msgid "Announcement"
 msgstr "Nuntii"
 
-#: models.py:601
+#: models.py:639
 #, fuzzy
 #| msgid "Announcements"
 msgid "Announcement recipient"
 msgstr "Nuntii"
 
-#: models.py:602
+#: models.py:640
 #, fuzzy
 #| msgid "Announcements"
 msgid "Announcement recipients"
 msgstr "Nuntii"
 
-#: models.py:652
+#: models.py:690
 #, fuzzy
 #| msgid "Site title"
 msgid "Widget Title"
 msgstr "Titulus paginae"
 
-#: models.py:653
+#: models.py:691
 msgid "Activate Widget"
 msgstr ""
 
-#: models.py:671
+#: models.py:694
+msgid "Size on mobile devices"
+msgstr ""
+
+#: models.py:695
+msgid "<= 600 px, 12 columns"
+msgstr ""
+
+#: models.py:700
+msgid "Size on tablet devices"
+msgstr ""
+
+#: models.py:701
+msgid "> 600 px, 12 columns"
+msgstr ""
+
+#: models.py:706
+msgid "Size on desktop devices"
+msgstr ""
+
+#: models.py:707
+msgid "> 992 px, 12 columns"
+msgstr ""
+
+#: models.py:712
+msgid "Size on large desktop devices"
+msgstr ""
+
+#: models.py:713
+msgid "> 1200 px>, 12 columns"
+msgstr ""
+
+#: models.py:734
+#, fuzzy
+#| msgid "Dashboard"
+msgid "Can edit default dashboard"
+msgstr "Forum"
+
+#: models.py:735
 #, fuzzy
 #| msgid "Dashboard"
 msgid "Dashboard Widget"
 msgstr "Forum"
 
-#: models.py:672
+#: models.py:736
 #, fuzzy
 #| msgid "Dashboard"
 msgid "Dashboard Widgets"
 msgstr "Forum"
 
-#: models.py:678
+#: models.py:741
+#, fuzzy
+#| msgid "Dashboard"
+msgid "Dashboard widget"
+msgstr "Forum"
+
+#: models.py:746
+msgid "Order"
+msgstr ""
+
+#: models.py:747
+msgid "Part of the default dashboard"
+msgstr ""
+
+#: models.py:755
+#, fuzzy
+#| msgid "Dashboard"
+msgid "Dashboard widget order"
+msgstr "Forum"
+
+#: models.py:756
+#, fuzzy
+#| msgid "Dashboard"
+msgid "Dashboard widget orders"
+msgstr "Forum"
+
+#: models.py:762
 msgid "Menu ID"
 msgstr ""
 
-#: models.py:690
+#: models.py:775
 msgid "Custom menu"
 msgstr ""
 
-#: models.py:691
+#: models.py:776
 msgid "Custom menus"
 msgstr ""
 
-#: models.py:698
+#: models.py:783
 msgid "Menu"
 msgstr ""
 
-#: models.py:702
+#: models.py:787
 msgid "Icon"
 msgstr "Nota"
 
-#: models.py:708
+#: models.py:793
 msgid "Custom menu item"
 msgstr ""
 
-#: models.py:709
+#: models.py:794
 msgid "Custom menu items"
 msgstr ""
 
-#: models.py:719
+#: models.py:804
 msgid "Title of type"
 msgstr ""
 
-#: models.py:726 templates/core/group/full.html:46
+#: models.py:811 templates/core/group/full.html:47
 #, fuzzy
 #| msgid "Group"
 msgid "Group type"
 msgstr "Grex"
 
-#: models.py:736
+#: models.py:821
 #, fuzzy
 #| msgid "System status"
 msgid "Can view system status"
 msgstr "Status systemae"
 
-#: models.py:737
+#: models.py:822
 #, fuzzy
 #| msgid "Persons and accounts"
 msgid "Can link persons to accounts"
 msgstr "Personae et computi"
 
-#: models.py:738
+#: models.py:823
 #, fuzzy
 #| msgid "Data management"
 msgid "Can manage data"
 msgstr "Adminstratio datarum"
 
-#: models.py:739
+#: models.py:824
 #, fuzzy
 #| msgid "Stop impersonation"
 msgid "Can impersonate"
 msgstr "Simulandum aliquem finire"
 
-#: models.py:740
+#: models.py:825
 msgid "Can use search"
 msgstr ""
 
-#: models.py:741
+#: models.py:826
 msgid "Can change site preferences"
 msgstr ""
 
-#: models.py:742
+#: models.py:827
 msgid "Can change person preferences"
 msgstr ""
 
-#: models.py:743
+#: models.py:828
 msgid "Can change group preferences"
 msgstr ""
 
-#: preferences.py:24
+#: models.py:864
+msgid "Related data check task"
+msgstr ""
+
+#: models.py:872
+msgid "Issue solved"
+msgstr ""
+
+#: models.py:873
+#, fuzzy
+#| msgid "Notifications"
+msgid "Notification sent"
+msgstr "Nuntii"
+
+#: models.py:886
+msgid "Data check result"
+msgstr ""
+
+#: models.py:887
+msgid "Data check results"
+msgstr ""
+
+#: models.py:889
+msgid "Can run data checks"
+msgstr ""
+
+#: models.py:890
+msgid "Can solve data check problems"
+msgstr ""
+
+#: preferences.py:27
 #, fuzzy
 #| msgid "Notifications"
 msgid "Authentication"
 msgstr "Nuntii"
 
-#: preferences.py:33
+#: preferences.py:28
+#, fuzzy
+#| msgid "Impersonation"
+msgid "Internationalisation"
+msgstr "Simulare aliquem"
+
+#: preferences.py:37
 msgid "Site title"
 msgstr "Titulus paginae"
 
-#: preferences.py:42
+#: preferences.py:46
 msgid "Site description"
 msgstr "Descriptio paginae"
 
-#: preferences.py:51
+#: preferences.py:55
 msgid "Primary colour"
 msgstr ""
 
-#: preferences.py:60
+#: preferences.py:64
 msgid "Secondary colour"
 msgstr ""
 
-#: preferences.py:68
+#: preferences.py:72
 #, fuzzy
 #| msgid "Logout"
 msgid "Logo"
 msgstr "nomen retractare"
 
-#: preferences.py:76
+#: preferences.py:80
 msgid "Favicon"
 msgstr ""
 
-#: preferences.py:84
+#: preferences.py:88
 #, fuzzy
 #| msgid "Icon"
 msgid "PWA-Icon"
 msgstr "Nota"
 
-#: preferences.py:93
+#: preferences.py:97
 #, fuzzy
 #| msgid "Last name"
 msgid "Mail out name"
 msgstr "Secondus nomen"
 
-#: preferences.py:102
+#: preferences.py:106
 #, fuzzy
 #| msgid "E-mail address"
 msgid "Mail out address"
 msgstr "Inscriptio electronica"
 
-#: preferences.py:112
+#: preferences.py:116
 msgid "Link to privacy policy"
 msgstr ""
 
-#: preferences.py:122
+#: preferences.py:126
 msgid "Link to imprint"
 msgstr ""
 
-#: preferences.py:132
+#: preferences.py:136
 msgid "Name format for addressing"
 msgstr ""
 
-#: preferences.py:146
+#: preferences.py:150
 msgid "Channels to use for notifications"
 msgstr ""
 
-#: preferences.py:156
+#: preferences.py:160
 msgid "Regular expression to match primary group, e.g. '^Class .*'"
 msgstr ""
 
-#: preferences.py:165
+#: preferences.py:169
 msgid "Field on person to match primary group against"
 msgstr ""
 
-#: preferences.py:177
+#: preferences.py:181
 msgid "Display name of the school"
 msgstr ""
 
-#: preferences.py:186
+#: preferences.py:190
 msgid "Official name of the school, e.g. as given by supervisory authority"
 msgstr "Officialis nomen scolae, e. g."
 
-#: preferences.py:194
+#: preferences.py:198
 msgid "Enabled custom authentication backends"
 msgstr ""
 
-#: settings.py:300
+#: preferences.py:211
+msgid "Available languages"
+msgstr ""
+
+#: preferences.py:223
+msgid "Send emails if data checks detect problems"
+msgstr ""
+
+#: preferences.py:234
+msgid "Email recipients for data checks problem emails"
+msgstr ""
+
+#: preferences.py:245
+msgid "Email recipient groups for data checks problem emails"
+msgstr ""
+
+#: settings.py:322
 msgid "English"
 msgstr "Britannicus"
 
-#: settings.py:301
+#: settings.py:323
 msgid "German"
 msgstr "Germanus"
 
-#: settings.py:302
+#: settings.py:324
 msgid "French"
 msgstr ""
 
-#: settings.py:303
+#: settings.py:325
 msgid "Norwegian (bokmål)"
 msgstr ""
 
 #: tables.py:19 templates/core/announcement/list.html:36
-#: templates/core/group/full.html:23 templates/core/person/full.html:22
+#: templates/core/group/full.html:24 templates/core/person/full.html:23
 msgid "Edit"
 msgstr ""
 
-#: tables.py:21 templates/core/announcement/list.html:22
+#: tables.py:21 tables.py:89 templates/core/announcement/list.html:22
 #, fuzzy
 #| msgid "Notifications"
 msgid "Actions"
 msgstr "Nuntii"
 
-#: tables.py:56 tables.py:57 tables.py:71
-#: templates/core/announcement/list.html:42 templates/core/group/full.html:30
-#: templates/core/pages/delete.html:22 templates/core/person/full.html:29
+#: tables.py:56 tables.py:57 tables.py:71 tables.py:87
+#: templates/core/announcement/list.html:42 templates/core/group/full.html:31
+#: templates/core/pages/delete.html:22 templates/core/person/full.html:30
 msgid "Delete"
 msgstr ""
 
@@ -839,27 +989,27 @@ msgstr "addita nomines"
 msgid "Create additional field"
 msgstr "addita nomines"
 
-#: templates/core/announcement/form.html:10
-#: templates/core/announcement/form.html:17
+#: templates/core/announcement/form.html:14
+#: templates/core/announcement/form.html:21
 #, fuzzy
 #| msgid "Announcements"
 msgid "Edit announcement"
 msgstr "Nuntii"
 
-#: templates/core/announcement/form.html:12
+#: templates/core/announcement/form.html:16
 #, fuzzy
 #| msgid "Announcements"
 msgid "Publish announcement"
 msgstr "Nuntii"
 
-#: templates/core/announcement/form.html:19
+#: templates/core/announcement/form.html:23
 #: templates/core/announcement/list.html:13
 #, fuzzy
 #| msgid "Who should see the announcement?"
 msgid "Publish new announcement"
 msgstr "Quis nuntium videatne?"
 
-#: templates/core/announcement/form.html:30
+#: templates/core/announcement/form.html:34
 #, fuzzy
 #| msgid "Who should see the announcement?"
 msgid "Save und publish announcement"
@@ -903,6 +1053,132 @@ msgstr ""
 msgid "Powered by AlekSIS"
 msgstr ""
 
+#: templates/core/dashboard_widget/create.html:8
+#: templates/core/dashboard_widget/create.html:12
+#, fuzzy, python-format
+#| msgid "Stop impersonation"
+msgid "Create %(widget)s"
+msgstr "Simulandum aliquem finire"
+
+#: templates/core/dashboard_widget/edit.html:8
+#: templates/core/dashboard_widget/edit.html:12
+#, python-format
+msgid "Edit %(widget)s"
+msgstr ""
+
+#: templates/core/dashboard_widget/list.html:17
+#, fuzzy, python-format
+#| msgid "Stop impersonation"
+msgid "Create %(name)s"
+msgstr "Simulandum aliquem finire"
+
+#: templates/core/dashboard_widget/list.html:25
+#: templates/core/edit_dashboard.html:8 templates/core/edit_dashboard.html:15
+#, fuzzy
+#| msgid "Dashboard"
+msgid "Edit default dashboard"
+msgstr "Forum"
+
+#: templates/core/data_check/list.html:15
+msgid "Check data again"
+msgstr ""
+
+#: templates/core/data_check/list.html:22
+msgid "The system detected some problems with your data."
+msgstr ""
+
+#: templates/core/data_check/list.html:23
+msgid ""
+"Please go through all data and check whether some extra action is\n"
+"          needed."
+msgstr ""
+
+#: templates/core/data_check/list.html:31
+msgid "Everything is fine."
+msgstr ""
+
+#: templates/core/data_check/list.html:32
+msgid "The system hasn't detected any problems with your data."
+msgstr ""
+
+#: templates/core/data_check/list.html:40
+msgid "Detected problems"
+msgstr ""
+
+#: templates/core/data_check/list.html:45
+msgid "Affected object"
+msgstr ""
+
+#: templates/core/data_check/list.html:46
+msgid "Detected problem"
+msgstr ""
+
+#: templates/core/data_check/list.html:47
+msgid "Show details"
+msgstr ""
+
+#: templates/core/data_check/list.html:48
+msgid "Options to solve the problem"
+msgstr ""
+
+#: templates/core/data_check/list.html:62
+msgid "Show object"
+msgstr ""
+
+#: templates/core/data_check/list.html:84
+#, fuzzy
+#| msgid "System status"
+msgid "Registered checks"
+msgstr "Status systemae"
+
+#: templates/core/data_check/list.html:88
+msgid ""
+"\n"
+"            The system will check for the following problems:\n"
+"          "
+msgstr ""
+
+#: templates/core/edit_dashboard.html:6 templates/core/edit_dashboard.html:13
+#: templates/core/index.html:14
+#, fuzzy
+#| msgid "Dashboard"
+msgid "Edit dashboard"
+msgstr "Forum"
+
+#: templates/core/edit_dashboard.html:24
+msgid ""
+"\n"
+"          On this page you can arrange your personal dashboard. You can drag any items from \"Available widgets\" to \"Your\n"
+"          Dashboard\" or change the order by moving the widgets. After you have finished, please don't forget to click on\n"
+"          \"Save\".\n"
+"        "
+msgstr ""
+
+#: templates/core/edit_dashboard.html:30
+msgid ""
+"\n"
+"          On this page you can arrange the default dashboard which is shown when a user doesn't arrange his own\n"
+"          dashboard. You can drag any items from \"Available widgets\" to \"Default Dashboard\" or change the order\n"
+"          by moving the widgets. After you have finished, please don't forget to click on \"Save\".\n"
+"        "
+msgstr ""
+
+#: templates/core/edit_dashboard.html:48
+msgid "Available widgets"
+msgstr ""
+
+#: templates/core/edit_dashboard.html:57
+#, fuzzy
+#| msgid "Dashboard"
+msgid "Your dashboard"
+msgstr "Forum"
+
+#: templates/core/edit_dashboard.html:59
+#, fuzzy
+#| msgid "Dashboard"
+msgid "Default dashboard"
+msgstr "Forum"
+
 #: templates/core/group/child_groups.html:18
 msgid ""
 "\n"
@@ -975,14 +1251,40 @@ msgstr ""
 msgid "Save and next"
 msgstr ""
 
-#: templates/core/group/edit.html:6 templates/core/group/edit.html:7
+#: templates/core/group/edit.html:11 templates/core/group/edit.html:12
 msgid "Edit group"
 msgstr ""
 
-#: templates/core/group/full.html:37 templates/core/person/full.html:36
+#: templates/core/group/full.html:38 templates/core/person/full.html:37
 msgid "Change preferences"
 msgstr ""
 
+#: templates/core/group/full.html:64
+#, fuzzy
+#| msgid "System status"
+msgid "Statistics"
+msgstr "Status systemae"
+
+#: templates/core/group/full.html:67
+msgid "Count of members"
+msgstr ""
+
+#: templates/core/group/full.html:71
+msgid "Average age"
+msgstr ""
+
+#: templates/core/group/full.html:76
+msgid "Age range"
+msgstr ""
+
+#: templates/core/group/full.html:76
+msgid "years to"
+msgstr ""
+
+#: templates/core/group/full.html:76
+msgid "years "
+msgstr ""
+
 #: templates/core/group/list.html:14
 msgid "Create group"
 msgstr ""
@@ -1015,27 +1317,35 @@ msgstr "Grex"
 msgid "Home"
 msgstr ""
 
-#: templates/core/index.html:42
+#: templates/core/index.html:50
+msgid ""
+"\n"
+"          You didn't customise your dashboard so that you see the system default. Please click on \"Edit dashboard\" to\n"
+"          customise your personal dashboard.\n"
+"        "
+msgstr ""
+
+#: templates/core/index.html:59
 msgid "Last activities"
 msgstr ""
 
-#: templates/core/index.html:60
+#: templates/core/index.html:77
 msgid "No activities available yet."
 msgstr ""
 
-#: templates/core/index.html:65
+#: templates/core/index.html:82
 #, fuzzy
 #| msgid "Notifications"
 msgid "Recent notifications"
 msgstr "Nuntii"
 
-#: templates/core/index.html:81
+#: templates/core/index.html:98
 #, fuzzy
 #| msgid "Edit school information"
 msgid "More information →"
 msgstr "Muta informationes scolae"
 
-#: templates/core/index.html:88
+#: templates/core/index.html:105
 msgid "No notifications available yet."
 msgstr ""
 
@@ -1118,21 +1428,6 @@ msgid ""
 "    "
 msgstr ""
 
-#: templates/core/pages/offline.html:6
-msgid ""
-"No internet\n"
-"    connection."
-msgstr ""
-
-#: templates/core/pages/offline.html:10
-msgid ""
-"\n"
-"      There was an error accessing this page. You probably don't have an internet connection. Check to see if your WiFi\n"
-"      or mobile data is turned on and try again. If you think you are connected, please contact the system\n"
-"      administrators:\n"
-"    "
-msgstr ""
-
 #: templates/core/pages/progress.html:27
 msgid ""
 "\n"
@@ -1260,37 +1555,19 @@ msgid ""
 "            "
 msgstr ""
 
-#: templates/core/partials/crud_events.html:10
-#, python-format
-msgid ""
-"\n"
-"              Created by %(person)s\n"
-"            "
-msgstr ""
-
-#: templates/core/partials/crud_events.html:14
-#: templates/core/partials/crud_events.html:22
-#: templates/core/partials/crud_events.html:26
-#, python-format
-msgid ""
-"\n"
-"              Updated by %(person)s\n"
-"            "
+#: templates/core/partials/crud_events.html:15
+msgid "Changed by"
 msgstr ""
 
-#: templates/core/partials/crud_events.html:18
-#, python-format
-msgid ""
-"\n"
-"              Deleted by %(person)s\n"
-"            "
+#: templates/core/partials/crud_events.html:15
+msgid "Unknown"
 msgstr ""
 
-#: templates/core/partials/language_form.html:16
+#: templates/core/partials/language_form.html:15
 msgid "Language"
 msgstr ""
 
-#: templates/core/partials/language_form.html:28
+#: templates/core/partials/language_form.html:27
 msgid "Select language"
 msgstr ""
 
@@ -1311,13 +1588,14 @@ msgid ""
 "          "
 msgstr ""
 
-#: templates/core/person/accounts.html:7 templates/core/person/accounts.html:9
+#: templates/core/person/accounts.html:12
+#: templates/core/person/accounts.html:14
 #, fuzzy
 #| msgid "Persons and accounts"
 msgid "Link persons to accounts"
 msgstr "Personae et computi"
 
-#: templates/core/person/accounts.html:16
+#: templates/core/person/accounts.html:21
 msgid ""
 "\n"
 "        You can use this form to assign user accounts to persons. Use the\n"
@@ -1327,28 +1605,34 @@ msgid ""
 "      "
 msgstr ""
 
-#: templates/core/person/accounts.html:31
-#: templates/core/person/accounts.html:55
+#: templates/core/person/accounts.html:36
+#: templates/core/person/accounts.html:60
 msgid "Update"
 msgstr ""
 
-#: templates/core/person/accounts.html:37
+#: templates/core/person/accounts.html:42
 msgid "Existing account"
 msgstr ""
 
-#: templates/core/person/accounts.html:38
+#: templates/core/person/accounts.html:43
 msgid "New account"
 msgstr ""
 
-#: templates/core/person/edit.html:11 templates/core/person/edit.html:12
+#: templates/core/person/edit.html:12 templates/core/person/edit.html:13
 msgid "Edit person"
 msgstr ""
 
-#: templates/core/person/full.html:42
+#: templates/core/person/full.html:44
+#, fuzzy
+#| msgid "Impersonation"
+msgid "Impersonate"
+msgstr "Simulare aliquem"
+
+#: templates/core/person/full.html:50
 msgid "Contact details"
 msgstr ""
 
-#: templates/core/person/full.html:122
+#: templates/core/person/full.html:130
 msgid "Children"
 msgstr ""
 
@@ -1396,16 +1680,31 @@ msgstr ""
 msgid "Save preferences"
 msgstr ""
 
-#: templates/dynamic_preferences/sections.html:7
-msgid "All"
-msgstr ""
-
 #: templates/impersonate/list_users.html:8
 #, fuzzy
 #| msgid "Impersonation"
 msgid "Impersonate user"
 msgstr "Simulare aliquem"
 
+#: templates/offline.html:5
+msgid "Network error"
+msgstr ""
+
+#: templates/offline.html:8
+msgid ""
+"No internet\n"
+"    connection."
+msgstr ""
+
+#: templates/offline.html:12
+msgid ""
+"\n"
+"      There was an error accessing this page. You probably don't have an internet connection. Check to see if your WiFi\n"
+"      or mobile data is turned on and try again. If you think you are connected, please contact the system\n"
+"      administrators:\n"
+"    "
+msgstr ""
+
 #: templates/search/search.html:8
 msgid "Global Search"
 msgstr ""
@@ -1426,6 +1725,41 @@ msgstr ""
 msgid "Please enter a search term above."
 msgstr ""
 
+#: templates/templated_email/data_checks.email:4
+msgid "The system detected some new problems with your data."
+msgstr ""
+
+#: templates/templated_email/data_checks.email:8
+#: templates/templated_email/data_checks.email:24
+msgid "Hello,"
+msgstr ""
+
+#: templates/templated_email/data_checks.email:10
+msgid ""
+"\n"
+"  the system detected some new problems with your data.\n"
+"  Please take some time to inspect them and solve the issues or mark them as ignored.\n"
+" "
+msgstr ""
+
+#: templates/templated_email/data_checks.email:26
+msgid ""
+"\n"
+"   the system detected some new problems with your data.\n"
+"   Please take some time to inspect them and solve the issues or mark them as ignored.\n"
+"  "
+msgstr ""
+
+#: templates/templated_email/data_checks.email:34
+#, fuzzy
+#| msgid "Site description"
+msgid "Problem description"
+msgstr "Descriptio paginae"
+
+#: templates/templated_email/data_checks.email:35
+msgid "Count of objects with new problems"
+msgstr ""
+
 #: templates/templated_email/notification.email:3
 #, fuzzy
 #| msgid "Notification"
@@ -1815,62 +2149,95 @@ msgstr ""
 msgid "SMS"
 msgstr ""
 
-#: views.py:122
+#: views.py:141
 msgid "The school term has been created."
 msgstr ""
 
-#: views.py:133
+#: views.py:153
 msgid "The school term has been saved."
 msgstr ""
 
-#: views.py:273
+#: views.py:298
 msgid "The child groups were successfully saved."
 msgstr ""
 
-#: views.py:309
+#: views.py:336
 msgid "The person has been saved."
 msgstr ""
 
-#: views.py:346
+#: views.py:375
 msgid "The group has been saved."
 msgstr ""
 
-#: views.py:434
+#: views.py:467
 msgid "The announcement has been saved."
 msgstr ""
 
-#: views.py:450
+#: views.py:483
 msgid "The announcement has been deleted."
 msgstr ""
 
-#: views.py:521
+#: views.py:562
 msgid "The preferences have been saved successfully."
 msgstr ""
 
-#: views.py:544
+#: views.py:586
 msgid "The person has been deleted."
 msgstr ""
 
-#: views.py:557
+#: views.py:600
 msgid "The group has been deleted."
 msgstr ""
 
-#: views.py:588
+#: views.py:632
 msgid "The additional_field has been saved."
 msgstr ""
 
-#: views.py:622
+#: views.py:666
 msgid "The additional field has been deleted."
 msgstr ""
 
-#: views.py:646
+#: views.py:691
 msgid "The group type has been saved."
 msgstr ""
 
-#: views.py:676
+#: views.py:721
 msgid "The group type has been deleted."
 msgstr ""
 
+#: views.py:749
+msgid "The data check has been started. Please note that it may take a while before you are able to fetch the data on this page."
+msgstr ""
+
+#: views.py:754
+msgid "The data check has finished."
+msgstr ""
+
+#: views.py:769
+#, python-brace-format
+msgid "The solve option '{solve_option_obj.verbose_name}' "
+msgstr ""
+
+#: views.py:811
+msgid "The dashboard widget has been saved."
+msgstr ""
+
+#: views.py:841
+msgid "The dashboard widget has been created."
+msgstr ""
+
+#: views.py:851
+msgid "The dashboard widget has been deleted."
+msgstr ""
+
+#: views.py:914
+msgid "Your dashboard configuration has been saved successfully."
+msgstr ""
+
+#: views.py:916
+msgid "The configuration of the default dashboard has been saved successfully."
+msgstr ""
+
 #~ 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 9dbef6e6f74f842b0e8f25e389edf1a852cd8d99..ea24fc3ff92afc211898fb8b426dccb97fce56ed 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: 2020-08-02 16:29+0200\n"
+"POT-Creation-Date: 2021-01-11 21:30+0100\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -17,14 +17,18 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: static/js/main.js:21
+#: static/js/main.js:15
 msgid "Today"
 msgstr ""
 
-#: static/js/main.js:22
+#: static/js/main.js:16
 msgid "Cancel"
 msgstr ""
 
-#: static/js/main.js:23
+#: static/js/main.js:17
 msgid "OK"
 msgstr ""
+
+#: static/js/main.js:118
+msgid "This page may contain outdated information since there is no internet connection."
+msgstr ""
diff --git a/aleksis/core/locale/nb_NO/LC_MESSAGES/django.po b/aleksis/core/locale/nb_NO/LC_MESSAGES/django.po
index 5be24e272186dd1985d749b948562bb13f222bc7..6b4be05da6b0a53f60a6ffa060739c419ea4af3a 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: 2020-08-02 16:29+0200\n"
+"POT-Creation-Date: 2021-01-11 21:30+0100\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -17,6 +17,15 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
+#: data_checks.py:53
+msgid "Ignore problem"
+msgstr ""
+
+#: data_checks.py:174
+#, python-brace-format
+msgid "Solve option '{solve_option_obj.verbose_name}' "
+msgstr ""
+
 #: filters.py:37 templates/core/base.html:77 templates/core/group/list.html:20
 #: templates/core/person/list.html:24 templates/search/search.html:7
 #: templates/search/search.html:22
@@ -31,92 +40,96 @@ msgstr ""
 msgid "Search by contact details"
 msgstr ""
 
-#: forms.py:46
+#: forms.py:54
 msgid "You cannot set a new username when also selecting an existing user."
 msgstr ""
 
-#: forms.py:50
+#: forms.py:58
 msgid "This username is already in use."
 msgstr ""
 
-#: forms.py:74
+#: forms.py:82
 msgid "Base data"
 msgstr ""
 
-#: forms.py:80
+#: forms.py:88
 msgid "Address"
 msgstr ""
 
-#: forms.py:81
+#: forms.py:89
 msgid "Contact data"
 msgstr ""
 
-#: forms.py:83
+#: forms.py:91
 msgid "Advanced personal data"
 msgstr ""
 
-#: forms.py:114
+#: forms.py:134
 msgid "New user"
 msgstr ""
 
-#: forms.py:114
+#: forms.py:134
 msgid "Create a new account"
 msgstr ""
 
-#: forms.py:126 models.py:91
+#: forms.py:146 models.py:102
 msgid "School term"
 msgstr ""
 
-#: forms.py:127
+#: forms.py:147
 msgid "Common data"
 msgstr ""
 
-#: forms.py:128 forms.py:170 menus.py:152 models.py:105
+#: forms.py:148 forms.py:197 menus.py:169 models.py:116
 #: templates/core/person/list.html:8 templates/core/person/list.html:9
 msgid "Persons"
 msgstr ""
 
-#: forms.py:129
+#: forms.py:149
 msgid "Additional data"
 msgstr ""
 
-#: forms.py:163 forms.py:166 models.py:35
+#: forms.py:189 forms.py:192 models.py:45
 msgid "Date"
 msgstr ""
 
-#: forms.py:164 forms.py:167 models.py:43
+#: forms.py:190 forms.py:193 models.py:53
 msgid "Time"
 msgstr ""
 
-#: forms.py:172 menus.py:160 models.py:319 templates/core/group/list.html:8
-#: templates/core/group/list.html:9 templates/core/person/full.html:136
+#: forms.py:210 menus.py:177 models.py:338 templates/core/group/list.html:8
+#: templates/core/group/list.html:9 templates/core/person/full.html:144
 msgid "Groups"
 msgstr ""
 
-#: forms.py:176
+#: forms.py:220
 msgid "From when until when should the announcement be displayed?"
 msgstr ""
 
-#: forms.py:179
+#: forms.py:223
 msgid "Who should see the announcement?"
 msgstr ""
 
-#: forms.py:180
+#: forms.py:224
 msgid "Write your announcement:"
 msgstr ""
 
-#: forms.py:219
+#: forms.py:263
 msgid "You are not allowed to create announcements which are only valid in the past."
 msgstr ""
 
-#: forms.py:223
+#: forms.py:267
 msgid "The from date and time must be earlier then the until date and time."
 msgstr ""
 
-#: forms.py:232
+#: forms.py:276
 msgid "You need at least one recipient."
 msgstr ""
 
+#: health_checks.py:15
+msgid "There are unresolved data problems."
+msgstr ""
+
 #: menus.py:7 templates/two_factor/core/login.html:6
 #: templates/two_factor/core/login.html:10
 #: templates/two_factor/core/login.html:86
@@ -155,539 +168,657 @@ msgstr ""
 msgid "Admin"
 msgstr ""
 
-#: menus.py:75 models.py:564 templates/core/announcement/list.html:7
+#: menus.py:75 models.py:602 templates/core/announcement/list.html:7
 #: templates/core/announcement/list.html:8
 msgid "Announcements"
 msgstr ""
 
-#: menus.py:86 models.py:92 templates/core/school_term/list.html:8
+#: menus.py:86 models.py:103 templates/core/school_term/list.html:8
 #: templates/core/school_term/list.html:9
 msgid "School terms"
 msgstr ""
 
-#: menus.py:97 templates/core/management/data_management.html:6
+#: menus.py:97 templates/core/dashboard_widget/list.html:8
+#: templates/core/dashboard_widget/list.html:9
+msgid "Dashboard widgets"
+msgstr ""
+
+#: menus.py:108 templates/core/management/data_management.html:6
 #: templates/core/management/data_management.html:7
 msgid "Data management"
 msgstr ""
 
-#: menus.py:105 templates/core/pages/system_status.html:5
+#: menus.py:116 templates/core/pages/system_status.html:5
 #: templates/core/pages/system_status.html:7
 msgid "System status"
 msgstr ""
 
-#: menus.py:116
+#: menus.py:127
 msgid "Impersonation"
 msgstr ""
 
-#: menus.py:124
+#: menus.py:135
 msgid "Configuration"
 msgstr ""
 
-#: menus.py:135
+#: menus.py:146 templates/core/data_check/list.html:9
+#: templates/core/data_check/list.html:10
+msgid "Data checks"
+msgstr ""
+
+#: menus.py:152
 msgid "Backend Admin"
 msgstr ""
 
-#: menus.py:143
+#: menus.py:160
 msgid "People"
 msgstr ""
 
-#: menus.py:168 models.py:727 templates/core/group_type/list.html:8
+#: menus.py:185 models.py:812 templates/core/group_type/list.html:8
 #: templates/core/group_type/list.html:9
 msgid "Group types"
 msgstr ""
 
-#: menus.py:179
+#: menus.py:196
 msgid "Persons and accounts"
 msgstr ""
 
-#: menus.py:190
+#: menus.py:207
 msgid "Groups and child groups"
 msgstr ""
 
-#: menus.py:201 models.py:363 templates/core/additional_field/list.html:8
+#: menus.py:218 models.py:385 templates/core/additional_field/list.html:8
 #: templates/core/additional_field/list.html:9
 msgid "Additional fields"
 msgstr ""
 
-#: menus.py:216 templates/core/group/child_groups.html:7
+#: menus.py:233 templates/core/group/child_groups.html:7
 #: templates/core/group/child_groups.html:9
 msgid "Assign child groups to groups"
 msgstr ""
 
-#: mixins.py:406
+#: mixins.py:384
 msgid "Linked school term"
 msgstr ""
 
-#: models.py:33
+#: models.py:43
 msgid "Boolean (Yes/No)"
 msgstr ""
 
-#: models.py:34
+#: models.py:44
 msgid "Text (one line)"
 msgstr ""
 
-#: models.py:36
+#: models.py:46
 msgid "Date and time"
 msgstr ""
 
-#: models.py:37
+#: models.py:47
 msgid "Decimal number"
 msgstr ""
 
-#: models.py:38 models.py:146
+#: models.py:48 models.py:157
 msgid "E-mail address"
 msgstr ""
 
-#: models.py:39
+#: models.py:49
 msgid "Integer"
 msgstr ""
 
-#: models.py:40
+#: models.py:50
 msgid "IP address"
 msgstr ""
 
-#: models.py:41
+#: models.py:51
 msgid "Boolean or empty (Yes/No/Neither)"
 msgstr ""
 
-#: models.py:42
+#: models.py:52
 msgid "Text (multi-line)"
 msgstr ""
 
-#: models.py:44
+#: models.py:54
 msgid "URL / Link"
 msgstr ""
 
-#: models.py:56 models.py:700
+#: models.py:66 models.py:785
 msgid "Name"
 msgstr ""
 
-#: models.py:58
+#: models.py:68
 msgid "Start date"
 msgstr ""
 
-#: models.py:59
+#: models.py:69
 msgid "End date"
 msgstr ""
 
-#: models.py:77
+#: models.py:88
 msgid "The start date must be earlier than the end date."
 msgstr ""
 
-#: models.py:84
+#: models.py:95
 msgid "There is already a school term for this time or a part of this time."
 msgstr ""
 
-#: models.py:104 templates/core/person/accounts.html:36
+#: models.py:115 models.py:744 templates/core/person/accounts.html:41
 msgid "Person"
 msgstr ""
 
-#: models.py:107
+#: models.py:118
 msgid "Can view address"
 msgstr ""
 
-#: models.py:108
+#: models.py:119
 msgid "Can view contact details"
 msgstr ""
 
-#: models.py:109
+#: models.py:120
 msgid "Can view photo"
 msgstr ""
 
-#: models.py:110
+#: models.py:121
 msgid "Can view persons groups"
 msgstr ""
 
-#: models.py:111
+#: models.py:122
 msgid "Can view personal details"
 msgstr ""
 
-#: models.py:116
+#: models.py:127
 msgid "female"
 msgstr ""
 
-#: models.py:116
+#: models.py:127
 msgid "male"
 msgstr ""
 
-#: models.py:124
+#: models.py:135
 msgid "Linked user"
 msgstr ""
 
-#: models.py:126
+#: models.py:137
 msgid "Is person active?"
 msgstr ""
 
-#: models.py:128
+#: models.py:139
 msgid "First name"
 msgstr ""
 
-#: models.py:129
+#: models.py:140
 msgid "Last name"
 msgstr ""
 
-#: models.py:131
+#: models.py:142
 msgid "Additional name(s)"
 msgstr ""
 
-#: models.py:135 models.py:332
+#: models.py:146 models.py:354
 msgid "Short name"
 msgstr ""
 
-#: models.py:138
+#: models.py:149
 msgid "Street"
 msgstr ""
 
-#: models.py:139
+#: models.py:150
 msgid "Street number"
 msgstr ""
 
-#: models.py:140
+#: models.py:151
 msgid "Postal code"
 msgstr ""
 
-#: models.py:141
+#: models.py:152
 msgid "Place"
 msgstr ""
 
-#: models.py:143
+#: models.py:154
 msgid "Home phone"
 msgstr ""
 
-#: models.py:144
+#: models.py:155
 msgid "Mobile phone"
 msgstr ""
 
-#: models.py:148
+#: models.py:159
 msgid "Date of birth"
 msgstr ""
 
-#: models.py:149
+#: models.py:160
 msgid "Sex"
 msgstr ""
 
-#: models.py:151
+#: models.py:162
 msgid "Photo"
 msgstr ""
 
-#: models.py:155 templates/core/person/full.html:129
+#: models.py:166 templates/core/person/full.html:137
 msgid "Guardians / Parents"
 msgstr ""
 
-#: models.py:162
+#: models.py:173
 msgid "Primary group"
 msgstr ""
 
-#: models.py:165 models.py:423 models.py:447 models.py:532 models.py:720
-#: templates/core/person/full.html:112
+#: models.py:176 models.py:461 models.py:485 models.py:570 models.py:805
+#: templates/core/person/full.html:120
 msgid "Description"
 msgstr ""
 
-#: models.py:296
+#: models.py:313
 msgid "Title of field"
 msgstr ""
 
-#: models.py:298
+#: models.py:315
 msgid "Type of field"
 msgstr ""
 
-#: models.py:305
+#: models.py:322
 msgid "Addtitional field for groups"
 msgstr ""
 
-#: models.py:306
+#: models.py:323
 msgid "Addtitional fields for groups"
 msgstr ""
 
-#: models.py:318
+#: models.py:337
 msgid "Group"
 msgstr ""
 
-#: models.py:320
+#: models.py:340
 msgid "Can assign child groups to groups"
 msgstr ""
 
-#: models.py:330
+#: models.py:341
+msgid "Can view statistics about group."
+msgstr ""
+
+#: models.py:352
 msgid "Long name"
 msgstr ""
 
-#: models.py:340 templates/core/group/full.html:65
+#: models.py:362 templates/core/group/full.html:85
 msgid "Members"
 msgstr ""
 
-#: models.py:343 templates/core/group/full.html:62
+#: models.py:365 templates/core/group/full.html:82
 msgid "Owners"
 msgstr ""
 
-#: models.py:350 templates/core/group/full.html:54
+#: models.py:372 templates/core/group/full.html:55
 msgid "Parent groups"
 msgstr ""
 
-#: models.py:358
+#: models.py:380
 msgid "Type of group"
 msgstr ""
 
-#: models.py:419
+#: models.py:457
 msgid "User"
 msgstr ""
 
-#: models.py:422 models.py:446 models.py:531
+#: models.py:460 models.py:484 models.py:569
 #: templates/core/announcement/list.html:18
 msgid "Title"
 msgstr ""
 
-#: models.py:425
+#: models.py:463
 msgid "Application"
 msgstr ""
 
-#: models.py:431
+#: models.py:469
 msgid "Activity"
 msgstr ""
 
-#: models.py:432
+#: models.py:470
 msgid "Activities"
 msgstr ""
 
-#: models.py:438
+#: models.py:476
 msgid "Sender"
 msgstr ""
 
-#: models.py:443
+#: models.py:481
 msgid "Recipient"
 msgstr ""
 
-#: models.py:448 models.py:701
+#: models.py:486 models.py:786
 msgid "Link"
 msgstr ""
 
-#: models.py:450
+#: models.py:488
 msgid "Read"
 msgstr ""
 
-#: models.py:451
+#: models.py:489
 msgid "Sent"
 msgstr ""
 
-#: models.py:464
+#: models.py:502
 msgid "Notification"
 msgstr ""
 
-#: models.py:465
+#: models.py:503
 msgid "Notifications"
 msgstr ""
 
-#: models.py:533
+#: models.py:571
 msgid "Link to detailed view"
 msgstr ""
 
-#: models.py:536
+#: models.py:574
 msgid "Date and time from when to show"
 msgstr ""
 
-#: models.py:539
+#: models.py:577
 msgid "Date and time until when to show"
 msgstr ""
 
-#: models.py:563
+#: models.py:601
 msgid "Announcement"
 msgstr ""
 
-#: models.py:601
+#: models.py:639
 msgid "Announcement recipient"
 msgstr ""
 
-#: models.py:602
+#: models.py:640
 msgid "Announcement recipients"
 msgstr ""
 
-#: models.py:652
+#: models.py:690
 msgid "Widget Title"
 msgstr ""
 
-#: models.py:653
+#: models.py:691
 msgid "Activate Widget"
 msgstr ""
 
-#: models.py:671
+#: models.py:694
+msgid "Size on mobile devices"
+msgstr ""
+
+#: models.py:695
+msgid "<= 600 px, 12 columns"
+msgstr ""
+
+#: models.py:700
+msgid "Size on tablet devices"
+msgstr ""
+
+#: models.py:701
+msgid "> 600 px, 12 columns"
+msgstr ""
+
+#: models.py:706
+msgid "Size on desktop devices"
+msgstr ""
+
+#: models.py:707
+msgid "> 992 px, 12 columns"
+msgstr ""
+
+#: models.py:712
+msgid "Size on large desktop devices"
+msgstr ""
+
+#: models.py:713
+msgid "> 1200 px>, 12 columns"
+msgstr ""
+
+#: models.py:734
+msgid "Can edit default dashboard"
+msgstr ""
+
+#: models.py:735
 msgid "Dashboard Widget"
 msgstr ""
 
-#: models.py:672
+#: models.py:736
 msgid "Dashboard Widgets"
 msgstr ""
 
-#: models.py:678
+#: models.py:741
+msgid "Dashboard widget"
+msgstr ""
+
+#: models.py:746
+msgid "Order"
+msgstr ""
+
+#: models.py:747
+msgid "Part of the default dashboard"
+msgstr ""
+
+#: models.py:755
+msgid "Dashboard widget order"
+msgstr ""
+
+#: models.py:756
+msgid "Dashboard widget orders"
+msgstr ""
+
+#: models.py:762
 msgid "Menu ID"
 msgstr ""
 
-#: models.py:690
+#: models.py:775
 msgid "Custom menu"
 msgstr ""
 
-#: models.py:691
+#: models.py:776
 msgid "Custom menus"
 msgstr ""
 
-#: models.py:698
+#: models.py:783
 msgid "Menu"
 msgstr ""
 
-#: models.py:702
+#: models.py:787
 msgid "Icon"
 msgstr ""
 
-#: models.py:708
+#: models.py:793
 msgid "Custom menu item"
 msgstr ""
 
-#: models.py:709
+#: models.py:794
 msgid "Custom menu items"
 msgstr ""
 
-#: models.py:719
+#: models.py:804
 msgid "Title of type"
 msgstr ""
 
-#: models.py:726 templates/core/group/full.html:46
+#: models.py:811 templates/core/group/full.html:47
 msgid "Group type"
 msgstr ""
 
-#: models.py:736
+#: models.py:821
 msgid "Can view system status"
 msgstr ""
 
-#: models.py:737
+#: models.py:822
 msgid "Can link persons to accounts"
 msgstr ""
 
-#: models.py:738
+#: models.py:823
 msgid "Can manage data"
 msgstr ""
 
-#: models.py:739
+#: models.py:824
 msgid "Can impersonate"
 msgstr ""
 
-#: models.py:740
+#: models.py:825
 msgid "Can use search"
 msgstr ""
 
-#: models.py:741
+#: models.py:826
 msgid "Can change site preferences"
 msgstr ""
 
-#: models.py:742
+#: models.py:827
 msgid "Can change person preferences"
 msgstr ""
 
-#: models.py:743
+#: models.py:828
 msgid "Can change group preferences"
 msgstr ""
 
-#: preferences.py:24
+#: models.py:864
+msgid "Related data check task"
+msgstr ""
+
+#: models.py:872
+msgid "Issue solved"
+msgstr ""
+
+#: models.py:873
+msgid "Notification sent"
+msgstr ""
+
+#: models.py:886
+msgid "Data check result"
+msgstr ""
+
+#: models.py:887
+msgid "Data check results"
+msgstr ""
+
+#: models.py:889
+msgid "Can run data checks"
+msgstr ""
+
+#: models.py:890
+msgid "Can solve data check problems"
+msgstr ""
+
+#: preferences.py:27
 msgid "Authentication"
 msgstr ""
 
-#: preferences.py:33
+#: preferences.py:28
+msgid "Internationalisation"
+msgstr ""
+
+#: preferences.py:37
 msgid "Site title"
 msgstr ""
 
-#: preferences.py:42
+#: preferences.py:46
 msgid "Site description"
 msgstr ""
 
-#: preferences.py:51
+#: preferences.py:55
 msgid "Primary colour"
 msgstr ""
 
-#: preferences.py:60
+#: preferences.py:64
 msgid "Secondary colour"
 msgstr ""
 
-#: preferences.py:68
+#: preferences.py:72
 msgid "Logo"
 msgstr ""
 
-#: preferences.py:76
+#: preferences.py:80
 msgid "Favicon"
 msgstr ""
 
-#: preferences.py:84
+#: preferences.py:88
 msgid "PWA-Icon"
 msgstr ""
 
-#: preferences.py:93
+#: preferences.py:97
 msgid "Mail out name"
 msgstr ""
 
-#: preferences.py:102
+#: preferences.py:106
 msgid "Mail out address"
 msgstr ""
 
-#: preferences.py:112
+#: preferences.py:116
 msgid "Link to privacy policy"
 msgstr ""
 
-#: preferences.py:122
+#: preferences.py:126
 msgid "Link to imprint"
 msgstr ""
 
-#: preferences.py:132
+#: preferences.py:136
 msgid "Name format for addressing"
 msgstr ""
 
-#: preferences.py:146
+#: preferences.py:150
 msgid "Channels to use for notifications"
 msgstr ""
 
-#: preferences.py:156
+#: preferences.py:160
 msgid "Regular expression to match primary group, e.g. '^Class .*'"
 msgstr ""
 
-#: preferences.py:165
+#: preferences.py:169
 msgid "Field on person to match primary group against"
 msgstr ""
 
-#: preferences.py:177
+#: preferences.py:181
 msgid "Display name of the school"
 msgstr ""
 
-#: preferences.py:186
+#: preferences.py:190
 msgid "Official name of the school, e.g. as given by supervisory authority"
 msgstr ""
 
-#: preferences.py:194
+#: preferences.py:198
 msgid "Enabled custom authentication backends"
 msgstr ""
 
-#: settings.py:300
+#: preferences.py:211
+msgid "Available languages"
+msgstr ""
+
+#: preferences.py:223
+msgid "Send emails if data checks detect problems"
+msgstr ""
+
+#: preferences.py:234
+msgid "Email recipients for data checks problem emails"
+msgstr ""
+
+#: preferences.py:245
+msgid "Email recipient groups for data checks problem emails"
+msgstr ""
+
+#: settings.py:322
 msgid "English"
 msgstr ""
 
-#: settings.py:301
+#: settings.py:323
 msgid "German"
 msgstr ""
 
-#: settings.py:302
+#: settings.py:324
 msgid "French"
 msgstr ""
 
-#: settings.py:303
+#: settings.py:325
 msgid "Norwegian (bokmål)"
 msgstr "Norsk (bokmål)"
 
 #: tables.py:19 templates/core/announcement/list.html:36
-#: templates/core/group/full.html:23 templates/core/person/full.html:22
+#: templates/core/group/full.html:24 templates/core/person/full.html:23
 msgid "Edit"
 msgstr ""
 
-#: tables.py:21 templates/core/announcement/list.html:22
+#: tables.py:21 tables.py:89 templates/core/announcement/list.html:22
 msgid "Actions"
 msgstr ""
 
-#: tables.py:56 tables.py:57 tables.py:71
-#: templates/core/announcement/list.html:42 templates/core/group/full.html:30
-#: templates/core/pages/delete.html:22 templates/core/person/full.html:29
+#: tables.py:56 tables.py:57 tables.py:71 tables.py:87
+#: templates/core/announcement/list.html:42 templates/core/group/full.html:31
+#: templates/core/pages/delete.html:22 templates/core/person/full.html:30
 msgid "Delete"
 msgstr ""
 
@@ -759,21 +890,21 @@ msgstr ""
 msgid "Create additional field"
 msgstr ""
 
-#: templates/core/announcement/form.html:10
-#: templates/core/announcement/form.html:17
+#: templates/core/announcement/form.html:14
+#: templates/core/announcement/form.html:21
 msgid "Edit announcement"
 msgstr ""
 
-#: templates/core/announcement/form.html:12
+#: templates/core/announcement/form.html:16
 msgid "Publish announcement"
 msgstr ""
 
-#: templates/core/announcement/form.html:19
+#: templates/core/announcement/form.html:23
 #: templates/core/announcement/list.html:13
 msgid "Publish new announcement"
 msgstr ""
 
-#: templates/core/announcement/form.html:30
+#: templates/core/announcement/form.html:34
 msgid "Save und publish announcement"
 msgstr ""
 
@@ -813,6 +944,120 @@ msgstr ""
 msgid "Powered by AlekSIS"
 msgstr ""
 
+#: templates/core/dashboard_widget/create.html:8
+#: templates/core/dashboard_widget/create.html:12
+#, python-format
+msgid "Create %(widget)s"
+msgstr ""
+
+#: templates/core/dashboard_widget/edit.html:8
+#: templates/core/dashboard_widget/edit.html:12
+#, python-format
+msgid "Edit %(widget)s"
+msgstr ""
+
+#: templates/core/dashboard_widget/list.html:17
+#, python-format
+msgid "Create %(name)s"
+msgstr ""
+
+#: templates/core/dashboard_widget/list.html:25
+#: templates/core/edit_dashboard.html:8 templates/core/edit_dashboard.html:15
+msgid "Edit default dashboard"
+msgstr ""
+
+#: templates/core/data_check/list.html:15
+msgid "Check data again"
+msgstr ""
+
+#: templates/core/data_check/list.html:22
+msgid "The system detected some problems with your data."
+msgstr ""
+
+#: templates/core/data_check/list.html:23
+msgid ""
+"Please go through all data and check whether some extra action is\n"
+"          needed."
+msgstr ""
+
+#: templates/core/data_check/list.html:31
+msgid "Everything is fine."
+msgstr ""
+
+#: templates/core/data_check/list.html:32
+msgid "The system hasn't detected any problems with your data."
+msgstr ""
+
+#: templates/core/data_check/list.html:40
+msgid "Detected problems"
+msgstr ""
+
+#: templates/core/data_check/list.html:45
+msgid "Affected object"
+msgstr ""
+
+#: templates/core/data_check/list.html:46
+msgid "Detected problem"
+msgstr ""
+
+#: templates/core/data_check/list.html:47
+msgid "Show details"
+msgstr ""
+
+#: templates/core/data_check/list.html:48
+msgid "Options to solve the problem"
+msgstr ""
+
+#: templates/core/data_check/list.html:62
+msgid "Show object"
+msgstr ""
+
+#: templates/core/data_check/list.html:84
+msgid "Registered checks"
+msgstr ""
+
+#: templates/core/data_check/list.html:88
+msgid ""
+"\n"
+"            The system will check for the following problems:\n"
+"          "
+msgstr ""
+
+#: templates/core/edit_dashboard.html:6 templates/core/edit_dashboard.html:13
+#: templates/core/index.html:14
+msgid "Edit dashboard"
+msgstr ""
+
+#: templates/core/edit_dashboard.html:24
+msgid ""
+"\n"
+"          On this page you can arrange your personal dashboard. You can drag any items from \"Available widgets\" to \"Your\n"
+"          Dashboard\" or change the order by moving the widgets. After you have finished, please don't forget to click on\n"
+"          \"Save\".\n"
+"        "
+msgstr ""
+
+#: templates/core/edit_dashboard.html:30
+msgid ""
+"\n"
+"          On this page you can arrange the default dashboard which is shown when a user doesn't arrange his own\n"
+"          dashboard. You can drag any items from \"Available widgets\" to \"Default Dashboard\" or change the order\n"
+"          by moving the widgets. After you have finished, please don't forget to click on \"Save\".\n"
+"        "
+msgstr ""
+
+#: templates/core/edit_dashboard.html:48
+msgid "Available widgets"
+msgstr ""
+
+#: templates/core/edit_dashboard.html:57
+msgid "Your dashboard"
+msgstr ""
+
+#: templates/core/edit_dashboard.html:59
+msgid "Default dashboard"
+msgstr ""
+
 #: templates/core/group/child_groups.html:18
 msgid ""
 "\n"
@@ -885,14 +1130,38 @@ msgstr ""
 msgid "Save and next"
 msgstr ""
 
-#: templates/core/group/edit.html:6 templates/core/group/edit.html:7
+#: templates/core/group/edit.html:11 templates/core/group/edit.html:12
 msgid "Edit group"
 msgstr ""
 
-#: templates/core/group/full.html:37 templates/core/person/full.html:36
+#: templates/core/group/full.html:38 templates/core/person/full.html:37
 msgid "Change preferences"
 msgstr ""
 
+#: templates/core/group/full.html:64
+msgid "Statistics"
+msgstr ""
+
+#: templates/core/group/full.html:67
+msgid "Count of members"
+msgstr ""
+
+#: templates/core/group/full.html:71
+msgid "Average age"
+msgstr ""
+
+#: templates/core/group/full.html:76
+msgid "Age range"
+msgstr ""
+
+#: templates/core/group/full.html:76
+msgid "years to"
+msgstr ""
+
+#: templates/core/group/full.html:76
+msgid "years "
+msgstr ""
+
 #: templates/core/group/list.html:14
 msgid "Create group"
 msgstr ""
@@ -921,23 +1190,31 @@ msgstr ""
 msgid "Home"
 msgstr ""
 
-#: templates/core/index.html:42
+#: templates/core/index.html:50
+msgid ""
+"\n"
+"          You didn't customise your dashboard so that you see the system default. Please click on \"Edit dashboard\" to\n"
+"          customise your personal dashboard.\n"
+"        "
+msgstr ""
+
+#: templates/core/index.html:59
 msgid "Last activities"
 msgstr ""
 
-#: templates/core/index.html:60
+#: templates/core/index.html:77
 msgid "No activities available yet."
 msgstr ""
 
-#: templates/core/index.html:65
+#: templates/core/index.html:82
 msgid "Recent notifications"
 msgstr ""
 
-#: templates/core/index.html:81
+#: templates/core/index.html:98
 msgid "More information →"
 msgstr ""
 
-#: templates/core/index.html:88
+#: templates/core/index.html:105
 msgid "No notifications available yet."
 msgstr ""
 
@@ -1016,21 +1293,6 @@ msgid ""
 "    "
 msgstr ""
 
-#: templates/core/pages/offline.html:6
-msgid ""
-"No internet\n"
-"    connection."
-msgstr ""
-
-#: templates/core/pages/offline.html:10
-msgid ""
-"\n"
-"      There was an error accessing this page. You probably don't have an internet connection. Check to see if your WiFi\n"
-"      or mobile data is turned on and try again. If you think you are connected, please contact the system\n"
-"      administrators:\n"
-"    "
-msgstr ""
-
 #: templates/core/pages/progress.html:27
 msgid ""
 "\n"
@@ -1150,37 +1412,19 @@ msgid ""
 "            "
 msgstr ""
 
-#: templates/core/partials/crud_events.html:10
-#, python-format
-msgid ""
-"\n"
-"              Created by %(person)s\n"
-"            "
-msgstr ""
-
-#: templates/core/partials/crud_events.html:14
-#: templates/core/partials/crud_events.html:22
-#: templates/core/partials/crud_events.html:26
-#, python-format
-msgid ""
-"\n"
-"              Updated by %(person)s\n"
-"            "
+#: templates/core/partials/crud_events.html:15
+msgid "Changed by"
 msgstr ""
 
-#: templates/core/partials/crud_events.html:18
-#, python-format
-msgid ""
-"\n"
-"              Deleted by %(person)s\n"
-"            "
+#: templates/core/partials/crud_events.html:15
+msgid "Unknown"
 msgstr ""
 
-#: templates/core/partials/language_form.html:16
+#: templates/core/partials/language_form.html:15
 msgid "Language"
 msgstr ""
 
-#: templates/core/partials/language_form.html:28
+#: templates/core/partials/language_form.html:27
 msgid "Select language"
 msgstr ""
 
@@ -1201,11 +1445,12 @@ msgid ""
 "          "
 msgstr ""
 
-#: templates/core/person/accounts.html:7 templates/core/person/accounts.html:9
+#: templates/core/person/accounts.html:12
+#: templates/core/person/accounts.html:14
 msgid "Link persons to accounts"
 msgstr ""
 
-#: templates/core/person/accounts.html:16
+#: templates/core/person/accounts.html:21
 msgid ""
 "\n"
 "        You can use this form to assign user accounts to persons. Use the\n"
@@ -1215,28 +1460,32 @@ msgid ""
 "      "
 msgstr ""
 
-#: templates/core/person/accounts.html:31
-#: templates/core/person/accounts.html:55
+#: templates/core/person/accounts.html:36
+#: templates/core/person/accounts.html:60
 msgid "Update"
 msgstr ""
 
-#: templates/core/person/accounts.html:37
+#: templates/core/person/accounts.html:42
 msgid "Existing account"
 msgstr ""
 
-#: templates/core/person/accounts.html:38
+#: templates/core/person/accounts.html:43
 msgid "New account"
 msgstr ""
 
-#: templates/core/person/edit.html:11 templates/core/person/edit.html:12
+#: templates/core/person/edit.html:12 templates/core/person/edit.html:13
 msgid "Edit person"
 msgstr ""
 
-#: templates/core/person/full.html:42
+#: templates/core/person/full.html:44
+msgid "Impersonate"
+msgstr ""
+
+#: templates/core/person/full.html:50
 msgid "Contact details"
 msgstr ""
 
-#: templates/core/person/full.html:122
+#: templates/core/person/full.html:130
 msgid "Children"
 msgstr ""
 
@@ -1280,14 +1529,29 @@ msgstr ""
 msgid "Save preferences"
 msgstr ""
 
-#: templates/dynamic_preferences/sections.html:7
-msgid "All"
-msgstr ""
-
 #: templates/impersonate/list_users.html:8
 msgid "Impersonate user"
 msgstr ""
 
+#: templates/offline.html:5
+msgid "Network error"
+msgstr ""
+
+#: templates/offline.html:8
+msgid ""
+"No internet\n"
+"    connection."
+msgstr ""
+
+#: templates/offline.html:12
+msgid ""
+"\n"
+"      There was an error accessing this page. You probably don't have an internet connection. Check to see if your WiFi\n"
+"      or mobile data is turned on and try again. If you think you are connected, please contact the system\n"
+"      administrators:\n"
+"    "
+msgstr ""
+
 #: templates/search/search.html:8
 msgid "Global Search"
 msgstr ""
@@ -1308,6 +1572,39 @@ msgstr ""
 msgid "Please enter a search term above."
 msgstr ""
 
+#: templates/templated_email/data_checks.email:4
+msgid "The system detected some new problems with your data."
+msgstr ""
+
+#: templates/templated_email/data_checks.email:8
+#: templates/templated_email/data_checks.email:24
+msgid "Hello,"
+msgstr ""
+
+#: templates/templated_email/data_checks.email:10
+msgid ""
+"\n"
+"  the system detected some new problems with your data.\n"
+"  Please take some time to inspect them and solve the issues or mark them as ignored.\n"
+" "
+msgstr ""
+
+#: templates/templated_email/data_checks.email:26
+msgid ""
+"\n"
+"   the system detected some new problems with your data.\n"
+"   Please take some time to inspect them and solve the issues or mark them as ignored.\n"
+"  "
+msgstr ""
+
+#: templates/templated_email/data_checks.email:34
+msgid "Problem description"
+msgstr ""
+
+#: templates/templated_email/data_checks.email:35
+msgid "Count of objects with new problems"
+msgstr ""
+
 #: templates/templated_email/notification.email:3
 msgid "New notification for"
 msgstr ""
@@ -1690,58 +1987,91 @@ msgstr ""
 msgid "SMS"
 msgstr ""
 
-#: views.py:122
+#: views.py:141
 msgid "The school term has been created."
 msgstr ""
 
-#: views.py:133
+#: views.py:153
 msgid "The school term has been saved."
 msgstr ""
 
-#: views.py:273
+#: views.py:298
 msgid "The child groups were successfully saved."
 msgstr ""
 
-#: views.py:309
+#: views.py:336
 msgid "The person has been saved."
 msgstr ""
 
-#: views.py:346
+#: views.py:375
 msgid "The group has been saved."
 msgstr ""
 
-#: views.py:434
+#: views.py:467
 msgid "The announcement has been saved."
 msgstr ""
 
-#: views.py:450
+#: views.py:483
 msgid "The announcement has been deleted."
 msgstr ""
 
-#: views.py:521
+#: views.py:562
 msgid "The preferences have been saved successfully."
 msgstr ""
 
-#: views.py:544
+#: views.py:586
 msgid "The person has been deleted."
 msgstr ""
 
-#: views.py:557
+#: views.py:600
 msgid "The group has been deleted."
 msgstr ""
 
-#: views.py:588
+#: views.py:632
 msgid "The additional_field has been saved."
 msgstr ""
 
-#: views.py:622
+#: views.py:666
 msgid "The additional field has been deleted."
 msgstr ""
 
-#: views.py:646
+#: views.py:691
 msgid "The group type has been saved."
 msgstr ""
 
-#: views.py:676
+#: views.py:721
 msgid "The group type has been deleted."
 msgstr ""
+
+#: views.py:749
+msgid "The data check has been started. Please note that it may take a while before you are able to fetch the data on this page."
+msgstr ""
+
+#: views.py:754
+msgid "The data check has finished."
+msgstr ""
+
+#: views.py:769
+#, python-brace-format
+msgid "The solve option '{solve_option_obj.verbose_name}' "
+msgstr ""
+
+#: views.py:811
+msgid "The dashboard widget has been saved."
+msgstr ""
+
+#: views.py:841
+msgid "The dashboard widget has been created."
+msgstr ""
+
+#: views.py:851
+msgid "The dashboard widget has been deleted."
+msgstr ""
+
+#: views.py:914
+msgid "Your dashboard configuration has been saved successfully."
+msgstr ""
+
+#: views.py:916
+msgid "The configuration of the default dashboard has been saved successfully."
+msgstr ""
diff --git a/aleksis/core/locale/nb_NO/LC_MESSAGES/djangojs.po b/aleksis/core/locale/nb_NO/LC_MESSAGES/djangojs.po
index 9dbef6e6f74f842b0e8f25e389edf1a852cd8d99..ea24fc3ff92afc211898fb8b426dccb97fce56ed 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: 2020-08-02 16:29+0200\n"
+"POT-Creation-Date: 2021-01-11 21:30+0100\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -17,14 +17,18 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: static/js/main.js:21
+#: static/js/main.js:15
 msgid "Today"
 msgstr ""
 
-#: static/js/main.js:22
+#: static/js/main.js:16
 msgid "Cancel"
 msgstr ""
 
-#: static/js/main.js:23
+#: static/js/main.js:17
 msgid "OK"
 msgstr ""
+
+#: static/js/main.js:118
+msgid "This page may contain outdated information since there is no internet connection."
+msgstr ""
diff --git a/aleksis/core/locale/tr_TR/LC_MESSAGES/django.po b/aleksis/core/locale/tr_TR/LC_MESSAGES/django.po
index d0417b32bd8aa0df398290eacf5a23491641abd2..7ecf671cf7dd018f3d159265a13605f8f050e518 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: 2020-08-02 16:29+0200\n"
+"POT-Creation-Date: 2021-01-11 21:30+0100\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -17,6 +17,15 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
+#: data_checks.py:53
+msgid "Ignore problem"
+msgstr ""
+
+#: data_checks.py:174
+#, python-brace-format
+msgid "Solve option '{solve_option_obj.verbose_name}' "
+msgstr ""
+
 #: filters.py:37 templates/core/base.html:77 templates/core/group/list.html:20
 #: templates/core/person/list.html:24 templates/search/search.html:7
 #: templates/search/search.html:22
@@ -31,92 +40,96 @@ msgstr ""
 msgid "Search by contact details"
 msgstr ""
 
-#: forms.py:46
+#: forms.py:54
 msgid "You cannot set a new username when also selecting an existing user."
 msgstr ""
 
-#: forms.py:50
+#: forms.py:58
 msgid "This username is already in use."
 msgstr ""
 
-#: forms.py:74
+#: forms.py:82
 msgid "Base data"
 msgstr ""
 
-#: forms.py:80
+#: forms.py:88
 msgid "Address"
 msgstr ""
 
-#: forms.py:81
+#: forms.py:89
 msgid "Contact data"
 msgstr ""
 
-#: forms.py:83
+#: forms.py:91
 msgid "Advanced personal data"
 msgstr ""
 
-#: forms.py:114
+#: forms.py:134
 msgid "New user"
 msgstr ""
 
-#: forms.py:114
+#: forms.py:134
 msgid "Create a new account"
 msgstr ""
 
-#: forms.py:126 models.py:91
+#: forms.py:146 models.py:102
 msgid "School term"
 msgstr ""
 
-#: forms.py:127
+#: forms.py:147
 msgid "Common data"
 msgstr ""
 
-#: forms.py:128 forms.py:170 menus.py:152 models.py:105
+#: forms.py:148 forms.py:197 menus.py:169 models.py:116
 #: templates/core/person/list.html:8 templates/core/person/list.html:9
 msgid "Persons"
 msgstr ""
 
-#: forms.py:129
+#: forms.py:149
 msgid "Additional data"
 msgstr ""
 
-#: forms.py:163 forms.py:166 models.py:35
+#: forms.py:189 forms.py:192 models.py:45
 msgid "Date"
 msgstr ""
 
-#: forms.py:164 forms.py:167 models.py:43
+#: forms.py:190 forms.py:193 models.py:53
 msgid "Time"
 msgstr ""
 
-#: forms.py:172 menus.py:160 models.py:319 templates/core/group/list.html:8
-#: templates/core/group/list.html:9 templates/core/person/full.html:136
+#: forms.py:210 menus.py:177 models.py:338 templates/core/group/list.html:8
+#: templates/core/group/list.html:9 templates/core/person/full.html:144
 msgid "Groups"
 msgstr ""
 
-#: forms.py:176
+#: forms.py:220
 msgid "From when until when should the announcement be displayed?"
 msgstr ""
 
-#: forms.py:179
+#: forms.py:223
 msgid "Who should see the announcement?"
 msgstr ""
 
-#: forms.py:180
+#: forms.py:224
 msgid "Write your announcement:"
 msgstr ""
 
-#: forms.py:219
+#: forms.py:263
 msgid "You are not allowed to create announcements which are only valid in the past."
 msgstr ""
 
-#: forms.py:223
+#: forms.py:267
 msgid "The from date and time must be earlier then the until date and time."
 msgstr ""
 
-#: forms.py:232
+#: forms.py:276
 msgid "You need at least one recipient."
 msgstr ""
 
+#: health_checks.py:15
+msgid "There are unresolved data problems."
+msgstr ""
+
 #: menus.py:7 templates/two_factor/core/login.html:6
 #: templates/two_factor/core/login.html:10
 #: templates/two_factor/core/login.html:86
@@ -155,539 +168,657 @@ msgstr ""
 msgid "Admin"
 msgstr ""
 
-#: menus.py:75 models.py:564 templates/core/announcement/list.html:7
+#: menus.py:75 models.py:602 templates/core/announcement/list.html:7
 #: templates/core/announcement/list.html:8
 msgid "Announcements"
 msgstr ""
 
-#: menus.py:86 models.py:92 templates/core/school_term/list.html:8
+#: menus.py:86 models.py:103 templates/core/school_term/list.html:8
 #: templates/core/school_term/list.html:9
 msgid "School terms"
 msgstr ""
 
-#: menus.py:97 templates/core/management/data_management.html:6
+#: menus.py:97 templates/core/dashboard_widget/list.html:8
+#: templates/core/dashboard_widget/list.html:9
+msgid "Dashboard widgets"
+msgstr ""
+
+#: menus.py:108 templates/core/management/data_management.html:6
 #: templates/core/management/data_management.html:7
 msgid "Data management"
 msgstr ""
 
-#: menus.py:105 templates/core/pages/system_status.html:5
+#: menus.py:116 templates/core/pages/system_status.html:5
 #: templates/core/pages/system_status.html:7
 msgid "System status"
 msgstr ""
 
-#: menus.py:116
+#: menus.py:127
 msgid "Impersonation"
 msgstr ""
 
-#: menus.py:124
+#: menus.py:135
 msgid "Configuration"
 msgstr ""
 
-#: menus.py:135
+#: menus.py:146 templates/core/data_check/list.html:9
+#: templates/core/data_check/list.html:10
+msgid "Data checks"
+msgstr ""
+
+#: menus.py:152
 msgid "Backend Admin"
 msgstr ""
 
-#: menus.py:143
+#: menus.py:160
 msgid "People"
 msgstr ""
 
-#: menus.py:168 models.py:727 templates/core/group_type/list.html:8
+#: menus.py:185 models.py:812 templates/core/group_type/list.html:8
 #: templates/core/group_type/list.html:9
 msgid "Group types"
 msgstr ""
 
-#: menus.py:179
+#: menus.py:196
 msgid "Persons and accounts"
 msgstr ""
 
-#: menus.py:190
+#: menus.py:207
 msgid "Groups and child groups"
 msgstr ""
 
-#: menus.py:201 models.py:363 templates/core/additional_field/list.html:8
+#: menus.py:218 models.py:385 templates/core/additional_field/list.html:8
 #: templates/core/additional_field/list.html:9
 msgid "Additional fields"
 msgstr ""
 
-#: menus.py:216 templates/core/group/child_groups.html:7
+#: menus.py:233 templates/core/group/child_groups.html:7
 #: templates/core/group/child_groups.html:9
 msgid "Assign child groups to groups"
 msgstr ""
 
-#: mixins.py:406
+#: mixins.py:384
 msgid "Linked school term"
 msgstr ""
 
-#: models.py:33
+#: models.py:43
 msgid "Boolean (Yes/No)"
 msgstr ""
 
-#: models.py:34
+#: models.py:44
 msgid "Text (one line)"
 msgstr ""
 
-#: models.py:36
+#: models.py:46
 msgid "Date and time"
 msgstr ""
 
-#: models.py:37
+#: models.py:47
 msgid "Decimal number"
 msgstr ""
 
-#: models.py:38 models.py:146
+#: models.py:48 models.py:157
 msgid "E-mail address"
 msgstr ""
 
-#: models.py:39
+#: models.py:49
 msgid "Integer"
 msgstr ""
 
-#: models.py:40
+#: models.py:50
 msgid "IP address"
 msgstr ""
 
-#: models.py:41
+#: models.py:51
 msgid "Boolean or empty (Yes/No/Neither)"
 msgstr ""
 
-#: models.py:42
+#: models.py:52
 msgid "Text (multi-line)"
 msgstr ""
 
-#: models.py:44
+#: models.py:54
 msgid "URL / Link"
 msgstr ""
 
-#: models.py:56 models.py:700
+#: models.py:66 models.py:785
 msgid "Name"
 msgstr ""
 
-#: models.py:58
+#: models.py:68
 msgid "Start date"
 msgstr ""
 
-#: models.py:59
+#: models.py:69
 msgid "End date"
 msgstr ""
 
-#: models.py:77
+#: models.py:88
 msgid "The start date must be earlier than the end date."
 msgstr ""
 
-#: models.py:84
+#: models.py:95
 msgid "There is already a school term for this time or a part of this time."
 msgstr ""
 
-#: models.py:104 templates/core/person/accounts.html:36
+#: models.py:115 models.py:744 templates/core/person/accounts.html:41
 msgid "Person"
 msgstr ""
 
-#: models.py:107
+#: models.py:118
 msgid "Can view address"
 msgstr ""
 
-#: models.py:108
+#: models.py:119
 msgid "Can view contact details"
 msgstr ""
 
-#: models.py:109
+#: models.py:120
 msgid "Can view photo"
 msgstr ""
 
-#: models.py:110
+#: models.py:121
 msgid "Can view persons groups"
 msgstr ""
 
-#: models.py:111
+#: models.py:122
 msgid "Can view personal details"
 msgstr ""
 
-#: models.py:116
+#: models.py:127
 msgid "female"
 msgstr ""
 
-#: models.py:116
+#: models.py:127
 msgid "male"
 msgstr ""
 
-#: models.py:124
+#: models.py:135
 msgid "Linked user"
 msgstr ""
 
-#: models.py:126
+#: models.py:137
 msgid "Is person active?"
 msgstr ""
 
-#: models.py:128
+#: models.py:139
 msgid "First name"
 msgstr ""
 
-#: models.py:129
+#: models.py:140
 msgid "Last name"
 msgstr ""
 
-#: models.py:131
+#: models.py:142
 msgid "Additional name(s)"
 msgstr ""
 
-#: models.py:135 models.py:332
+#: models.py:146 models.py:354
 msgid "Short name"
 msgstr ""
 
-#: models.py:138
+#: models.py:149
 msgid "Street"
 msgstr ""
 
-#: models.py:139
+#: models.py:150
 msgid "Street number"
 msgstr ""
 
-#: models.py:140
+#: models.py:151
 msgid "Postal code"
 msgstr ""
 
-#: models.py:141
+#: models.py:152
 msgid "Place"
 msgstr ""
 
-#: models.py:143
+#: models.py:154
 msgid "Home phone"
 msgstr ""
 
-#: models.py:144
+#: models.py:155
 msgid "Mobile phone"
 msgstr ""
 
-#: models.py:148
+#: models.py:159
 msgid "Date of birth"
 msgstr ""
 
-#: models.py:149
+#: models.py:160
 msgid "Sex"
 msgstr ""
 
-#: models.py:151
+#: models.py:162
 msgid "Photo"
 msgstr ""
 
-#: models.py:155 templates/core/person/full.html:129
+#: models.py:166 templates/core/person/full.html:137
 msgid "Guardians / Parents"
 msgstr ""
 
-#: models.py:162
+#: models.py:173
 msgid "Primary group"
 msgstr ""
 
-#: models.py:165 models.py:423 models.py:447 models.py:532 models.py:720
-#: templates/core/person/full.html:112
+#: models.py:176 models.py:461 models.py:485 models.py:570 models.py:805
+#: templates/core/person/full.html:120
 msgid "Description"
 msgstr ""
 
-#: models.py:296
+#: models.py:313
 msgid "Title of field"
 msgstr ""
 
-#: models.py:298
+#: models.py:315
 msgid "Type of field"
 msgstr ""
 
-#: models.py:305
+#: models.py:322
 msgid "Addtitional field for groups"
 msgstr ""
 
-#: models.py:306
+#: models.py:323
 msgid "Addtitional fields for groups"
 msgstr ""
 
-#: models.py:318
+#: models.py:337
 msgid "Group"
 msgstr ""
 
-#: models.py:320
+#: models.py:340
 msgid "Can assign child groups to groups"
 msgstr ""
 
-#: models.py:330
+#: models.py:341
+msgid "Can view statistics about group."
+msgstr ""
+
+#: models.py:352
 msgid "Long name"
 msgstr ""
 
-#: models.py:340 templates/core/group/full.html:65
+#: models.py:362 templates/core/group/full.html:85
 msgid "Members"
 msgstr ""
 
-#: models.py:343 templates/core/group/full.html:62
+#: models.py:365 templates/core/group/full.html:82
 msgid "Owners"
 msgstr ""
 
-#: models.py:350 templates/core/group/full.html:54
+#: models.py:372 templates/core/group/full.html:55
 msgid "Parent groups"
 msgstr ""
 
-#: models.py:358
+#: models.py:380
 msgid "Type of group"
 msgstr ""
 
-#: models.py:419
+#: models.py:457
 msgid "User"
 msgstr ""
 
-#: models.py:422 models.py:446 models.py:531
+#: models.py:460 models.py:484 models.py:569
 #: templates/core/announcement/list.html:18
 msgid "Title"
 msgstr ""
 
-#: models.py:425
+#: models.py:463
 msgid "Application"
 msgstr ""
 
-#: models.py:431
+#: models.py:469
 msgid "Activity"
 msgstr ""
 
-#: models.py:432
+#: models.py:470
 msgid "Activities"
 msgstr ""
 
-#: models.py:438
+#: models.py:476
 msgid "Sender"
 msgstr ""
 
-#: models.py:443
+#: models.py:481
 msgid "Recipient"
 msgstr ""
 
-#: models.py:448 models.py:701
+#: models.py:486 models.py:786
 msgid "Link"
 msgstr ""
 
-#: models.py:450
+#: models.py:488
 msgid "Read"
 msgstr ""
 
-#: models.py:451
+#: models.py:489
 msgid "Sent"
 msgstr ""
 
-#: models.py:464
+#: models.py:502
 msgid "Notification"
 msgstr ""
 
-#: models.py:465
+#: models.py:503
 msgid "Notifications"
 msgstr ""
 
-#: models.py:533
+#: models.py:571
 msgid "Link to detailed view"
 msgstr ""
 
-#: models.py:536
+#: models.py:574
 msgid "Date and time from when to show"
 msgstr ""
 
-#: models.py:539
+#: models.py:577
 msgid "Date and time until when to show"
 msgstr ""
 
-#: models.py:563
+#: models.py:601
 msgid "Announcement"
 msgstr ""
 
-#: models.py:601
+#: models.py:639
 msgid "Announcement recipient"
 msgstr ""
 
-#: models.py:602
+#: models.py:640
 msgid "Announcement recipients"
 msgstr ""
 
-#: models.py:652
+#: models.py:690
 msgid "Widget Title"
 msgstr ""
 
-#: models.py:653
+#: models.py:691
 msgid "Activate Widget"
 msgstr ""
 
-#: models.py:671
+#: models.py:694
+msgid "Size on mobile devices"
+msgstr ""
+
+#: models.py:695
+msgid "<= 600 px, 12 columns"
+msgstr ""
+
+#: models.py:700
+msgid "Size on tablet devices"
+msgstr ""
+
+#: models.py:701
+msgid "> 600 px, 12 columns"
+msgstr ""
+
+#: models.py:706
+msgid "Size on desktop devices"
+msgstr ""
+
+#: models.py:707
+msgid "> 992 px, 12 columns"
+msgstr ""
+
+#: models.py:712
+msgid "Size on large desktop devices"
+msgstr ""
+
+#: models.py:713
+msgid "> 1200 px>, 12 columns"
+msgstr ""
+
+#: models.py:734
+msgid "Can edit default dashboard"
+msgstr ""
+
+#: models.py:735
 msgid "Dashboard Widget"
 msgstr ""
 
-#: models.py:672
+#: models.py:736
 msgid "Dashboard Widgets"
 msgstr ""
 
-#: models.py:678
+#: models.py:741
+msgid "Dashboard widget"
+msgstr ""
+
+#: models.py:746
+msgid "Order"
+msgstr ""
+
+#: models.py:747
+msgid "Part of the default dashboard"
+msgstr ""
+
+#: models.py:755
+msgid "Dashboard widget order"
+msgstr ""
+
+#: models.py:756
+msgid "Dashboard widget orders"
+msgstr ""
+
+#: models.py:762
 msgid "Menu ID"
 msgstr ""
 
-#: models.py:690
+#: models.py:775
 msgid "Custom menu"
 msgstr ""
 
-#: models.py:691
+#: models.py:776
 msgid "Custom menus"
 msgstr ""
 
-#: models.py:698
+#: models.py:783
 msgid "Menu"
 msgstr ""
 
-#: models.py:702
+#: models.py:787
 msgid "Icon"
 msgstr ""
 
-#: models.py:708
+#: models.py:793
 msgid "Custom menu item"
 msgstr ""
 
-#: models.py:709
+#: models.py:794
 msgid "Custom menu items"
 msgstr ""
 
-#: models.py:719
+#: models.py:804
 msgid "Title of type"
 msgstr ""
 
-#: models.py:726 templates/core/group/full.html:46
+#: models.py:811 templates/core/group/full.html:47
 msgid "Group type"
 msgstr ""
 
-#: models.py:736
+#: models.py:821
 msgid "Can view system status"
 msgstr ""
 
-#: models.py:737
+#: models.py:822
 msgid "Can link persons to accounts"
 msgstr ""
 
-#: models.py:738
+#: models.py:823
 msgid "Can manage data"
 msgstr ""
 
-#: models.py:739
+#: models.py:824
 msgid "Can impersonate"
 msgstr ""
 
-#: models.py:740
+#: models.py:825
 msgid "Can use search"
 msgstr ""
 
-#: models.py:741
+#: models.py:826
 msgid "Can change site preferences"
 msgstr ""
 
-#: models.py:742
+#: models.py:827
 msgid "Can change person preferences"
 msgstr ""
 
-#: models.py:743
+#: models.py:828
 msgid "Can change group preferences"
 msgstr ""
 
-#: preferences.py:24
+#: models.py:864
+msgid "Related data check task"
+msgstr ""
+
+#: models.py:872
+msgid "Issue solved"
+msgstr ""
+
+#: models.py:873
+msgid "Notification sent"
+msgstr ""
+
+#: models.py:886
+msgid "Data check result"
+msgstr ""
+
+#: models.py:887
+msgid "Data check results"
+msgstr ""
+
+#: models.py:889
+msgid "Can run data checks"
+msgstr ""
+
+#: models.py:890
+msgid "Can solve data check problems"
+msgstr ""
+
+#: preferences.py:27
 msgid "Authentication"
 msgstr ""
 
-#: preferences.py:33
+#: preferences.py:28
+msgid "Internationalisation"
+msgstr ""
+
+#: preferences.py:37
 msgid "Site title"
 msgstr ""
 
-#: preferences.py:42
+#: preferences.py:46
 msgid "Site description"
 msgstr ""
 
-#: preferences.py:51
+#: preferences.py:55
 msgid "Primary colour"
 msgstr ""
 
-#: preferences.py:60
+#: preferences.py:64
 msgid "Secondary colour"
 msgstr ""
 
-#: preferences.py:68
+#: preferences.py:72
 msgid "Logo"
 msgstr ""
 
-#: preferences.py:76
+#: preferences.py:80
 msgid "Favicon"
 msgstr ""
 
-#: preferences.py:84
+#: preferences.py:88
 msgid "PWA-Icon"
 msgstr ""
 
-#: preferences.py:93
+#: preferences.py:97
 msgid "Mail out name"
 msgstr ""
 
-#: preferences.py:102
+#: preferences.py:106
 msgid "Mail out address"
 msgstr ""
 
-#: preferences.py:112
+#: preferences.py:116
 msgid "Link to privacy policy"
 msgstr ""
 
-#: preferences.py:122
+#: preferences.py:126
 msgid "Link to imprint"
 msgstr ""
 
-#: preferences.py:132
+#: preferences.py:136
 msgid "Name format for addressing"
 msgstr ""
 
-#: preferences.py:146
+#: preferences.py:150
 msgid "Channels to use for notifications"
 msgstr ""
 
-#: preferences.py:156
+#: preferences.py:160
 msgid "Regular expression to match primary group, e.g. '^Class .*'"
 msgstr ""
 
-#: preferences.py:165
+#: preferences.py:169
 msgid "Field on person to match primary group against"
 msgstr ""
 
-#: preferences.py:177
+#: preferences.py:181
 msgid "Display name of the school"
 msgstr ""
 
-#: preferences.py:186
+#: preferences.py:190
 msgid "Official name of the school, e.g. as given by supervisory authority"
 msgstr ""
 
-#: preferences.py:194
+#: preferences.py:198
 msgid "Enabled custom authentication backends"
 msgstr ""
 
-#: settings.py:300
+#: preferences.py:211
+msgid "Available languages"
+msgstr ""
+
+#: preferences.py:223
+msgid "Send emails if data checks detect problems"
+msgstr ""
+
+#: preferences.py:234
+msgid "Email recipients for data checks problem emails"
+msgstr ""
+
+#: preferences.py:245
+msgid "Email recipient groups for data checks problem emails"
+msgstr ""
+
+#: settings.py:322
 msgid "English"
 msgstr ""
 
-#: settings.py:301
+#: settings.py:323
 msgid "German"
 msgstr ""
 
-#: settings.py:302
+#: settings.py:324
 msgid "French"
 msgstr ""
 
-#: settings.py:303
+#: settings.py:325
 msgid "Norwegian (bokmål)"
 msgstr ""
 
 #: tables.py:19 templates/core/announcement/list.html:36
-#: templates/core/group/full.html:23 templates/core/person/full.html:22
+#: templates/core/group/full.html:24 templates/core/person/full.html:23
 msgid "Edit"
 msgstr ""
 
-#: tables.py:21 templates/core/announcement/list.html:22
+#: tables.py:21 tables.py:89 templates/core/announcement/list.html:22
 msgid "Actions"
 msgstr ""
 
-#: tables.py:56 tables.py:57 tables.py:71
-#: templates/core/announcement/list.html:42 templates/core/group/full.html:30
-#: templates/core/pages/delete.html:22 templates/core/person/full.html:29
+#: tables.py:56 tables.py:57 tables.py:71 tables.py:87
+#: templates/core/announcement/list.html:42 templates/core/group/full.html:31
+#: templates/core/pages/delete.html:22 templates/core/person/full.html:30
 msgid "Delete"
 msgstr ""
 
@@ -759,21 +890,21 @@ msgstr ""
 msgid "Create additional field"
 msgstr ""
 
-#: templates/core/announcement/form.html:10
-#: templates/core/announcement/form.html:17
+#: templates/core/announcement/form.html:14
+#: templates/core/announcement/form.html:21
 msgid "Edit announcement"
 msgstr ""
 
-#: templates/core/announcement/form.html:12
+#: templates/core/announcement/form.html:16
 msgid "Publish announcement"
 msgstr ""
 
-#: templates/core/announcement/form.html:19
+#: templates/core/announcement/form.html:23
 #: templates/core/announcement/list.html:13
 msgid "Publish new announcement"
 msgstr ""
 
-#: templates/core/announcement/form.html:30
+#: templates/core/announcement/form.html:34
 msgid "Save und publish announcement"
 msgstr ""
 
@@ -813,6 +944,120 @@ msgstr ""
 msgid "Powered by AlekSIS"
 msgstr ""
 
+#: templates/core/dashboard_widget/create.html:8
+#: templates/core/dashboard_widget/create.html:12
+#, python-format
+msgid "Create %(widget)s"
+msgstr ""
+
+#: templates/core/dashboard_widget/edit.html:8
+#: templates/core/dashboard_widget/edit.html:12
+#, python-format
+msgid "Edit %(widget)s"
+msgstr ""
+
+#: templates/core/dashboard_widget/list.html:17
+#, python-format
+msgid "Create %(name)s"
+msgstr ""
+
+#: templates/core/dashboard_widget/list.html:25
+#: templates/core/edit_dashboard.html:8 templates/core/edit_dashboard.html:15
+msgid "Edit default dashboard"
+msgstr ""
+
+#: templates/core/data_check/list.html:15
+msgid "Check data again"
+msgstr ""
+
+#: templates/core/data_check/list.html:22
+msgid "The system detected some problems with your data."
+msgstr ""
+
+#: templates/core/data_check/list.html:23
+msgid ""
+"Please go through all data and check whether some extra action is\n"
+"          needed."
+msgstr ""
+
+#: templates/core/data_check/list.html:31
+msgid "Everything is fine."
+msgstr ""
+
+#: templates/core/data_check/list.html:32
+msgid "The system hasn't detected any problems with your data."
+msgstr ""
+
+#: templates/core/data_check/list.html:40
+msgid "Detected problems"
+msgstr ""
+
+#: templates/core/data_check/list.html:45
+msgid "Affected object"
+msgstr ""
+
+#: templates/core/data_check/list.html:46
+msgid "Detected problem"
+msgstr ""
+
+#: templates/core/data_check/list.html:47
+msgid "Show details"
+msgstr ""
+
+#: templates/core/data_check/list.html:48
+msgid "Options to solve the problem"
+msgstr ""
+
+#: templates/core/data_check/list.html:62
+msgid "Show object"
+msgstr ""
+
+#: templates/core/data_check/list.html:84
+msgid "Registered checks"
+msgstr ""
+
+#: templates/core/data_check/list.html:88
+msgid ""
+"\n"
+"            The system will check for the following problems:\n"
+"          "
+msgstr ""
+
+#: templates/core/edit_dashboard.html:6 templates/core/edit_dashboard.html:13
+#: templates/core/index.html:14
+msgid "Edit dashboard"
+msgstr ""
+
+#: templates/core/edit_dashboard.html:24
+msgid ""
+"\n"
+"          On this page you can arrange your personal dashboard. You can drag any items from \"Available widgets\" to \"Your\n"
+"          Dashboard\" or change the order by moving the widgets. After you have finished, please don't forget to click on\n"
+"          \"Save\".\n"
+"        "
+msgstr ""
+
+#: templates/core/edit_dashboard.html:30
+msgid ""
+"\n"
+"          On this page you can arrange the default dashboard which is shown when a user doesn't arrange his own\n"
+"          dashboard. You can drag any items from \"Available widgets\" to \"Default Dashboard\" or change the order\n"
+"          by moving the widgets. After you have finished, please don't forget to click on \"Save\".\n"
+"        "
+msgstr ""
+
+#: templates/core/edit_dashboard.html:48
+msgid "Available widgets"
+msgstr ""
+
+#: templates/core/edit_dashboard.html:57
+msgid "Your dashboard"
+msgstr ""
+
+#: templates/core/edit_dashboard.html:59
+msgid "Default dashboard"
+msgstr ""
+
 #: templates/core/group/child_groups.html:18
 msgid ""
 "\n"
@@ -885,14 +1130,38 @@ msgstr ""
 msgid "Save and next"
 msgstr ""
 
-#: templates/core/group/edit.html:6 templates/core/group/edit.html:7
+#: templates/core/group/edit.html:11 templates/core/group/edit.html:12
 msgid "Edit group"
 msgstr ""
 
-#: templates/core/group/full.html:37 templates/core/person/full.html:36
+#: templates/core/group/full.html:38 templates/core/person/full.html:37
 msgid "Change preferences"
 msgstr ""
 
+#: templates/core/group/full.html:64
+msgid "Statistics"
+msgstr ""
+
+#: templates/core/group/full.html:67
+msgid "Count of members"
+msgstr ""
+
+#: templates/core/group/full.html:71
+msgid "Average age"
+msgstr ""
+
+#: templates/core/group/full.html:76
+msgid "Age range"
+msgstr ""
+
+#: templates/core/group/full.html:76
+msgid "years to"
+msgstr ""
+
+#: templates/core/group/full.html:76
+msgid "years "
+msgstr ""
+
 #: templates/core/group/list.html:14
 msgid "Create group"
 msgstr ""
@@ -921,23 +1190,31 @@ msgstr ""
 msgid "Home"
 msgstr ""
 
-#: templates/core/index.html:42
+#: templates/core/index.html:50
+msgid ""
+"\n"
+"          You didn't customise your dashboard so that you see the system default. Please click on \"Edit dashboard\" to\n"
+"          customise your personal dashboard.\n"
+"        "
+msgstr ""
+
+#: templates/core/index.html:59
 msgid "Last activities"
 msgstr ""
 
-#: templates/core/index.html:60
+#: templates/core/index.html:77
 msgid "No activities available yet."
 msgstr ""
 
-#: templates/core/index.html:65
+#: templates/core/index.html:82
 msgid "Recent notifications"
 msgstr ""
 
-#: templates/core/index.html:81
+#: templates/core/index.html:98
 msgid "More information →"
 msgstr ""
 
-#: templates/core/index.html:88
+#: templates/core/index.html:105
 msgid "No notifications available yet."
 msgstr ""
 
@@ -1016,21 +1293,6 @@ msgid ""
 "    "
 msgstr ""
 
-#: templates/core/pages/offline.html:6
-msgid ""
-"No internet\n"
-"    connection."
-msgstr ""
-
-#: templates/core/pages/offline.html:10
-msgid ""
-"\n"
-"      There was an error accessing this page. You probably don't have an internet connection. Check to see if your WiFi\n"
-"      or mobile data is turned on and try again. If you think you are connected, please contact the system\n"
-"      administrators:\n"
-"    "
-msgstr ""
-
 #: templates/core/pages/progress.html:27
 msgid ""
 "\n"
@@ -1150,37 +1412,19 @@ msgid ""
 "            "
 msgstr ""
 
-#: templates/core/partials/crud_events.html:10
-#, python-format
-msgid ""
-"\n"
-"              Created by %(person)s\n"
-"            "
-msgstr ""
-
-#: templates/core/partials/crud_events.html:14
-#: templates/core/partials/crud_events.html:22
-#: templates/core/partials/crud_events.html:26
-#, python-format
-msgid ""
-"\n"
-"              Updated by %(person)s\n"
-"            "
+#: templates/core/partials/crud_events.html:15
+msgid "Changed by"
 msgstr ""
 
-#: templates/core/partials/crud_events.html:18
-#, python-format
-msgid ""
-"\n"
-"              Deleted by %(person)s\n"
-"            "
+#: templates/core/partials/crud_events.html:15
+msgid "Unknown"
 msgstr ""
 
-#: templates/core/partials/language_form.html:16
+#: templates/core/partials/language_form.html:15
 msgid "Language"
 msgstr ""
 
-#: templates/core/partials/language_form.html:28
+#: templates/core/partials/language_form.html:27
 msgid "Select language"
 msgstr ""
 
@@ -1201,11 +1445,12 @@ msgid ""
 "          "
 msgstr ""
 
-#: templates/core/person/accounts.html:7 templates/core/person/accounts.html:9
+#: templates/core/person/accounts.html:12
+#: templates/core/person/accounts.html:14
 msgid "Link persons to accounts"
 msgstr ""
 
-#: templates/core/person/accounts.html:16
+#: templates/core/person/accounts.html:21
 msgid ""
 "\n"
 "        You can use this form to assign user accounts to persons. Use the\n"
@@ -1215,28 +1460,32 @@ msgid ""
 "      "
 msgstr ""
 
-#: templates/core/person/accounts.html:31
-#: templates/core/person/accounts.html:55
+#: templates/core/person/accounts.html:36
+#: templates/core/person/accounts.html:60
 msgid "Update"
 msgstr ""
 
-#: templates/core/person/accounts.html:37
+#: templates/core/person/accounts.html:42
 msgid "Existing account"
 msgstr ""
 
-#: templates/core/person/accounts.html:38
+#: templates/core/person/accounts.html:43
 msgid "New account"
 msgstr ""
 
-#: templates/core/person/edit.html:11 templates/core/person/edit.html:12
+#: templates/core/person/edit.html:12 templates/core/person/edit.html:13
 msgid "Edit person"
 msgstr ""
 
-#: templates/core/person/full.html:42
+#: templates/core/person/full.html:44
+msgid "Impersonate"
+msgstr ""
+
+#: templates/core/person/full.html:50
 msgid "Contact details"
 msgstr ""
 
-#: templates/core/person/full.html:122
+#: templates/core/person/full.html:130
 msgid "Children"
 msgstr ""
 
@@ -1280,14 +1529,29 @@ msgstr ""
 msgid "Save preferences"
 msgstr ""
 
-#: templates/dynamic_preferences/sections.html:7
-msgid "All"
-msgstr ""
-
 #: templates/impersonate/list_users.html:8
 msgid "Impersonate user"
 msgstr ""
 
+#: templates/offline.html:5
+msgid "Network error"
+msgstr ""
+
+#: templates/offline.html:8
+msgid ""
+"No internet\n"
+"    connection."
+msgstr ""
+
+#: templates/offline.html:12
+msgid ""
+"\n"
+"      There was an error accessing this page. You probably don't have an internet connection. Check to see if your WiFi\n"
+"      or mobile data is turned on and try again. If you think you are connected, please contact the system\n"
+"      administrators:\n"
+"    "
+msgstr ""
+
 #: templates/search/search.html:8
 msgid "Global Search"
 msgstr ""
@@ -1308,6 +1572,39 @@ msgstr ""
 msgid "Please enter a search term above."
 msgstr ""
 
+#: templates/templated_email/data_checks.email:4
+msgid "The system detected some new problems with your data."
+msgstr ""
+
+#: templates/templated_email/data_checks.email:8
+#: templates/templated_email/data_checks.email:24
+msgid "Hello,"
+msgstr ""
+
+#: templates/templated_email/data_checks.email:10
+msgid ""
+"\n"
+"  the system detected some new problems with your data.\n"
+"  Please take some time to inspect them and solve the issues or mark them as ignored.\n"
+" "
+msgstr ""
+
+#: templates/templated_email/data_checks.email:26
+msgid ""
+"\n"
+"   the system detected some new problems with your data.\n"
+"   Please take some time to inspect them and solve the issues or mark them as ignored.\n"
+"  "
+msgstr ""
+
+#: templates/templated_email/data_checks.email:34
+msgid "Problem description"
+msgstr ""
+
+#: templates/templated_email/data_checks.email:35
+msgid "Count of objects with new problems"
+msgstr ""
+
 #: templates/templated_email/notification.email:3
 msgid "New notification for"
 msgstr ""
@@ -1690,58 +1987,91 @@ msgstr ""
 msgid "SMS"
 msgstr ""
 
-#: views.py:122
+#: views.py:141
 msgid "The school term has been created."
 msgstr ""
 
-#: views.py:133
+#: views.py:153
 msgid "The school term has been saved."
 msgstr ""
 
-#: views.py:273
+#: views.py:298
 msgid "The child groups were successfully saved."
 msgstr ""
 
-#: views.py:309
+#: views.py:336
 msgid "The person has been saved."
 msgstr ""
 
-#: views.py:346
+#: views.py:375
 msgid "The group has been saved."
 msgstr ""
 
-#: views.py:434
+#: views.py:467
 msgid "The announcement has been saved."
 msgstr ""
 
-#: views.py:450
+#: views.py:483
 msgid "The announcement has been deleted."
 msgstr ""
 
-#: views.py:521
+#: views.py:562
 msgid "The preferences have been saved successfully."
 msgstr ""
 
-#: views.py:544
+#: views.py:586
 msgid "The person has been deleted."
 msgstr ""
 
-#: views.py:557
+#: views.py:600
 msgid "The group has been deleted."
 msgstr ""
 
-#: views.py:588
+#: views.py:632
 msgid "The additional_field has been saved."
 msgstr ""
 
-#: views.py:622
+#: views.py:666
 msgid "The additional field has been deleted."
 msgstr ""
 
-#: views.py:646
+#: views.py:691
 msgid "The group type has been saved."
 msgstr ""
 
-#: views.py:676
+#: views.py:721
 msgid "The group type has been deleted."
 msgstr ""
+
+#: views.py:749
+msgid "The data check has been started. Please note that it may take a while before you are able to fetch the data on this page."
+msgstr ""
+
+#: views.py:754
+msgid "The data check has finished."
+msgstr ""
+
+#: views.py:769
+#, python-brace-format
+msgid "The solve option '{solve_option_obj.verbose_name}' "
+msgstr ""
+
+#: views.py:811
+msgid "The dashboard widget has been saved."
+msgstr ""
+
+#: views.py:841
+msgid "The dashboard widget has been created."
+msgstr ""
+
+#: views.py:851
+msgid "The dashboard widget has been deleted."
+msgstr ""
+
+#: views.py:914
+msgid "Your dashboard configuration has been saved successfully."
+msgstr ""
+
+#: views.py:916
+msgid "The configuration of the default dashboard has been saved successfully."
+msgstr ""
diff --git a/aleksis/core/locale/tr_TR/LC_MESSAGES/djangojs.po b/aleksis/core/locale/tr_TR/LC_MESSAGES/djangojs.po
index 9dbef6e6f74f842b0e8f25e389edf1a852cd8d99..ea24fc3ff92afc211898fb8b426dccb97fce56ed 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: 2020-08-02 16:29+0200\n"
+"POT-Creation-Date: 2021-01-11 21:30+0100\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -17,14 +17,18 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: static/js/main.js:21
+#: static/js/main.js:15
 msgid "Today"
 msgstr ""
 
-#: static/js/main.js:22
+#: static/js/main.js:16
 msgid "Cancel"
 msgstr ""
 
-#: static/js/main.js:23
+#: static/js/main.js:17
 msgid "OK"
 msgstr ""
+
+#: static/js/main.js:118
+msgid "This page may contain outdated information since there is no internet connection."
+msgstr ""
diff --git a/aleksis/core/menus.py b/aleksis/core/menus.py
index 9b1c42e931235333fb8d4a9dca55cd7f977b47de..fc9ba63604dabf57e1c4101fc8d7f5700548cc6c 100644
--- a/aleksis/core/menus.py
+++ b/aleksis/core/menus.py
@@ -142,6 +142,12 @@ MENUS = {
                         ),
                     ],
                 },
+                {
+                    "name": _("Data checks"),
+                    "url": "check_data",
+                    "icon": "done_all",
+                    "validators": ["menu_generator.validators.is_superuser"],
+                },
                 {
                     "name": _("Backend Admin"),
                     "url": "admin:index",
diff --git a/aleksis/core/migrations/0008_data_check_result.py b/aleksis/core/migrations/0008_data_check_result.py
new file mode 100644
index 0000000000000000000000000000000000000000..3f8285e22a6af4109a67d6baddccd05e69b1bd6e
--- /dev/null
+++ b/aleksis/core/migrations/0008_data_check_result.py
@@ -0,0 +1,63 @@
+# Generated by Django 3.1.3 on 2020-11-14 16:11
+
+import django.contrib.sites.managers
+from django.db import migrations, models
+import django.db.models.deletion
+import django.utils.timezone
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("sites", "0002_alter_domain_unique"),
+        ("contenttypes", "0002_remove_content_type_name"),
+        ("core", "0007_dashboard_widget_order"),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name="DataCheckResult",
+            fields=[
+                (
+                    "id",
+                    models.AutoField(
+                        auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
+                    ),
+                ),
+                ("extended_data", models.JSONField(default=dict, editable=False)),
+                (
+                    "check",
+                    models.CharField(
+                        choices=[], max_length=255, verbose_name="Related data check task"
+                    ),
+                ),
+                ("object_id", models.CharField(max_length=255)),
+                ("solved", models.BooleanField(default=False, verbose_name="Issue solved")),
+                ("sent", models.BooleanField(default=False, verbose_name="Notification sent")),
+                (
+                    "content_type",
+                    models.ForeignKey(
+                        on_delete=django.db.models.deletion.CASCADE, to="contenttypes.contenttype"
+                    ),
+                ),
+                (
+                    "site",
+                    models.ForeignKey(
+                        default=1,
+                        editable=False,
+                        on_delete=django.db.models.deletion.CASCADE,
+                        to="sites.site",
+                    ),
+                ),
+            ],
+            options={
+                "permissions": (
+                    ("run_data_checks", "Can run data checks"),
+                    ("solve_data_problem", "Can solve data check problems"),
+                ),
+                "verbose_name": "Data check result",
+                "verbose_name_plural": "Data check results",
+            },
+            managers=[("objects", django.contrib.sites.managers.CurrentSiteManager()),],
+        ),
+    ]
diff --git a/aleksis/core/migrations/0009_default_dashboard.py b/aleksis/core/migrations/0009_default_dashboard.py
new file mode 100644
index 0000000000000000000000000000000000000000..401396bb064139d5c9bdda37f1c9a5dece65dc22
--- /dev/null
+++ b/aleksis/core/migrations/0009_default_dashboard.py
@@ -0,0 +1,30 @@
+# Generated by Django 3.1.4 on 2021-01-04 13:39
+
+from django.db import migrations, models
+import django.db.models.deletion
+import django.utils.timezone
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('core', '0008_data_check_result'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='dashboardwidgetorder',
+            name='default',
+            field=models.BooleanField(default=False, verbose_name='Part of the default dashboard'),
+        ),
+        migrations.AlterField(
+            model_name='dashboardwidgetorder',
+            name='person',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='core.person', verbose_name='Person'),
+        ),
+        migrations.AlterModelOptions(
+            name='dashboardwidget',
+            options={'permissions': (('edit_default_dashboard', 'Can edit default dashboard'),),
+                     'verbose_name': 'Dashboard Widget', 'verbose_name_plural': 'Dashboard Widgets'},
+        ),
+    ]
diff --git a/aleksis/core/mixins.py b/aleksis/core/mixins.py
index e44caa020bdb6fb1814a3b7e10de95d72915b26b..3cad91f2c80301d8d73268e32f58d7773c5a45c8 100644
--- a/aleksis/core/mixins.py
+++ b/aleksis/core/mixins.py
@@ -47,6 +47,28 @@ class _ExtensibleModelBase(models.base.ModelBase):
         return mcls
 
 
+def _generate_one_to_one_proxy_property(field, subfield):
+    def getter(self):
+        if hasattr(self, field.name):
+            related = getattr(self, field.name)
+            return getattr(related, subfield.name)
+        # Related instane does not exist
+        return None
+
+    def setter(self, val):
+        if hasattr(self, field.name):
+            related = getattr(self, field.name)
+        else:
+            # Auto-create related instance (but do not save)
+            related = field.related_model()
+            setattr(related, field.remote_field.name, self)
+            # Ensure the related model is saved later
+            self._save_reverse = getattr(self, "_save_reverse", []) + [related]
+        setattr(related, subfield.name, val)
+
+    return property(getter, setter)
+
+
 class ExtensibleModel(models.Model, metaclass=_ExtensibleModelBase):
     """Base model for all objects in AlekSIS apps.
 
@@ -248,13 +270,51 @@ class ExtensibleModel(models.Model, metaclass=_ExtensibleModelBase):
             to.property_(_virtual_related, related_name)
 
     @classmethod
-    def syncable_fields(cls) -> List[models.Field]:
-        """Collect all fields that can be synced on a model."""
-        return [
-            field
-            for field in cls._meta.fields
-            if (field.editable and not field.auto_created and not field.is_relation)
-        ]
+    def syncable_fields(
+        cls, recursive: bool = True, exclude_remotes: List = []
+    ) -> List[models.Field]:
+        """Collect all fields that can be synced on a model.
+
+        If recursive is True, it recurses into related models and generates virtual
+        proxy fields to access fields in related models."""
+        fields = []
+        for field in cls._meta.get_fields():
+            if field.is_relation and field.one_to_one and recursive:
+                if ExtensibleModel not in field.related_model.__mro__:
+                    # Related model is not extensible and thus has no syncable fields
+                    continue
+                if field.related_model in exclude_remotes:
+                    # Remote is excluded, probably to avoid recursion
+                    continue
+
+                # Recurse into related model to get its fields as well
+                for subfield in field.related_model.syncable_fields(
+                    recursive, exclude_remotes + [cls]
+                ):
+                    # generate virtual field names for proxy access
+                    name = f"_{field.name}__{subfield.name}"
+                    verbose_name = f"{field.name} ({field.related_model._meta.verbose_name}) → {subfield.verbose_name}"
+
+                    if not hasattr(cls, name):
+                        # Add proxy properties to handle access to related model
+                        setattr(cls, name, _generate_one_to_one_proxy_property(field, subfield))
+
+                    # Generate a fake field class with enough API to detect attribute names
+                    fields.append(
+                        type(
+                            "FakeRelatedProxyField",
+                            (),
+                            {
+                                "name": name,
+                                "verbose_name": verbose_name,
+                                "to_python": lambda v: subfield.to_python(v),
+                            },
+                        )
+                    )
+            elif field.editable and not field.auto_created:
+                fields.append(field)
+
+        return fields
 
     @classmethod
     def syncable_fields_choices(cls) -> Tuple[Tuple[str, str]]:
@@ -273,6 +333,16 @@ class ExtensibleModel(models.Model, metaclass=_ExtensibleModelBase):
         """Dynamically add a new permission to a model."""
         cls.extra_permissions.append((name, verbose_name))
 
+    def save(self, *args, **kwargs):
+        """Ensure all functionality of our extensions that needs saving gets it."""
+        # For auto-created remote syncable fields
+        if hasattr(self, "_save_reverse"):
+            for related in self._save_reverse:
+                related.save()
+            del self._save_reverse
+
+        super().save(*args, **kwargs)
+
     class Meta:
         abstract = True
 
diff --git a/aleksis/core/models.py b/aleksis/core/models.py
index 0f7a80d416cfe1dec30b57f2bf1e070e664a8966..8927844a47da2f30e030a9b0815e82539940d8ba 100644
--- a/aleksis/core/models.py
+++ b/aleksis/core/models.py
@@ -26,6 +26,8 @@ from model_utils.models import TimeStampedModel
 from phonenumber_field.modelfields import PhoneNumberField
 from polymorphic.models import PolymorphicModel
 
+from aleksis.core.data_checks import DataCheck, DataCheckRegistry
+
 from .managers import (
     CurrentSiteManagerWithoutMigrations,
     GroupManager,
@@ -237,7 +239,10 @@ class Person(ExtensibleModel):
     @property
     def dashboard_widgets(self):
         return [
-            w.widget for w in DashboardWidgetOrder.objects.filter(person=self).order_by("order")
+            w.widget
+            for w in DashboardWidgetOrder.objects.filter(person=self, widget__active=True).order_by(
+                "order"
+            )
         ]
 
     def save(self, *args, **kwargs):
@@ -492,7 +497,7 @@ class Notification(ExtensibleModel, TimeStampedModel):
     def save(self, **kwargs):
         super().save(**kwargs)
         if not self.sent:
-            transaction.on_commit(lambda: send_notification(self.pk, resend=True))
+            send_notification(self.pk, resend=True)
         self.sent = True
         super().save(**kwargs)
 
@@ -729,6 +734,7 @@ class DashboardWidget(PolymorphicModel, PureDjangoModel):
         return self.title
 
     class Meta:
+        permissions = (("edit_default_dashboard", _("Can edit default dashboard")),)
         verbose_name = _("Dashboard Widget")
         verbose_name_plural = _("Dashboard Widgets")
 
@@ -737,8 +743,21 @@ class DashboardWidgetOrder(ExtensibleModel):
     widget = models.ForeignKey(
         DashboardWidget, on_delete=models.CASCADE, verbose_name=_("Dashboard widget")
     )
-    person = models.ForeignKey(Person, on_delete=models.CASCADE, verbose_name=_("Person"))
+    person = models.ForeignKey(
+        Person, on_delete=models.CASCADE, verbose_name=_("Person"), null=True, blank=True
+    )
     order = models.PositiveIntegerField(verbose_name=_("Order"))
+    default = models.BooleanField(default=False, verbose_name=_("Part of the default dashboard"))
+
+    @classproperty
+    def default_dashboard_widgets(cls):
+        """Get default order for dashboard widgets."""
+        return [
+            w.widget
+            for w in cls.objects.filter(person=None, default=True, widget__active=True).order_by(
+                "order"
+            )
+        ]
 
     class Meta:
         verbose_name = _("Dashboard widget order")
@@ -843,3 +862,38 @@ class GroupPreferenceModel(PerInstancePreferenceModel, PureDjangoModel):
 
     class Meta:
         app_label = "core"
+
+
+class DataCheckResult(ExtensibleModel):
+    """Save the result of a data check for a specific object."""
+
+    check = models.CharField(
+        max_length=255,
+        verbose_name=_("Related data check task"),
+        choices=DataCheckRegistry.data_checks_choices,
+    )
+
+    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
+    object_id = models.CharField(max_length=255)
+    related_object = GenericForeignKey("content_type", "object_id")
+
+    solved = models.BooleanField(default=False, verbose_name=_("Issue solved"))
+    sent = models.BooleanField(default=False, verbose_name=_("Notification sent"))
+
+    @property
+    def related_check(self) -> DataCheck:
+        return DataCheckRegistry.data_checks_by_name[self.check]
+
+    def solve(self, solve_option: str = "default"):
+        self.related_check.solve(self, solve_option)
+
+    def __str__(self):
+        return f"{self.related_object}: {self.related_check.problem_name}"
+
+    class Meta:
+        verbose_name = _("Data check result")
+        verbose_name_plural = _("Data check results")
+        permissions = (
+            ("run_data_checks", _("Can run data checks")),
+            ("solve_data_problem", _("Can solve data check problems")),
+        )
diff --git a/aleksis/core/preferences.py b/aleksis/core/preferences.py
index b962f27bba83374a2f331af43a913362cd6d71ad..6594e3b1ddf8c48e038de228c0b9e22c13a70ec0 100644
--- a/aleksis/core/preferences.py
+++ b/aleksis/core/preferences.py
@@ -8,11 +8,12 @@ from dynamic_preferences.types import (
     BooleanPreference,
     ChoicePreference,
     FilePreference,
+    ModelMultipleChoicePreference,
     MultipleChoicePreference,
     StringPreference,
 )
 
-from .models import Person
+from .models import Group, Person
 from .registries import person_preferences_registry, site_preferences_registry
 from .util.notifications import get_notification_choices_lazy
 
@@ -228,3 +229,35 @@ class AvailableLanguages(MultipleChoicePreference):
     verbose_name = _("Available languages")
     field_attribute = {"initial": []}
     choices = settings.LANGUAGES
+
+
+@site_preferences_registry.register
+class DataChecksSendEmails(BooleanPreference):
+    """Enable email sending if data checks detect problems."""
+
+    section = general
+    name = "data_checks_send_emails"
+    default = False
+    verbose_name = _("Send emails if data checks detect problems")
+
+
+@site_preferences_registry.register
+class DataChecksEmailsRecipients(ModelMultipleChoicePreference):
+    """Email recipients for data check problem emails."""
+
+    section = general
+    name = "data_checks_recipients"
+    default = []
+    model = Person
+    verbose_name = _("Email recipients for data checks problem emails")
+
+
+@site_preferences_registry.register
+class DataChecksEmailsRecipientGroups(ModelMultipleChoicePreference):
+    """Email recipient groups for data check problem emails."""
+
+    section = general
+    name = "data_checks_recipient_groups"
+    default = []
+    model = Group
+    verbose_name = _("Email recipient groups for data checks problem emails")
diff --git a/aleksis/core/rules.py b/aleksis/core/rules.py
index 2e36bc08bf3a307c0b8a116a5731f0f4793f2475..ac713bbe54a937d529da6c4e0266209dae593fd5 100644
--- a/aleksis/core/rules.py
+++ b/aleksis/core/rules.py
@@ -279,6 +279,21 @@ view_group_stats_predicate = has_person & (
 )
 rules.add_perm("core.view_group_stats", view_group_stats_predicate)
 
+# View data check results
+view_data_check_results_predicate = has_person & has_global_perm("core.view_datacheckresult")
+rules.add_perm("core.view_datacheckresults", view_data_check_results_predicate)
+
+# Run data checks
+run_data_checks_predicate = (
+    has_person & view_data_check_results_predicate & has_global_perm("core.run_data_checks")
+)
+rules.add_perm("core.run_data_checks", run_data_checks_predicate)
+
+# Solve data problems
+solve_data_problem_predicate = (
+    has_person & view_data_check_results_predicate & has_global_perm("core.solve_data_problem")
+)
+rules.add_perm("core.solve_data_problem", solve_data_problem_predicate)
 
 view_dashboard_widget_predicate = has_person & has_global_perm("core.view_dashboardwidget")
 rules.add_perm("core.view_dashboardwidget", view_dashboard_widget_predicate)
@@ -291,3 +306,6 @@ rules.add_perm("core.edit_dashboardwidget", edit_dashboard_widget_predicate)
 
 delete_dashboard_widget_predicate = has_person & has_global_perm("core.delete_dashboardwidget")
 rules.add_perm("core.delete_dashboardwidget", delete_dashboard_widget_predicate)
+
+edit_default_dashboard_predicate = has_person & has_global_perm("core.edit_default_dashboard")
+rules.add_perm("core.edit_default_dashboard", edit_default_dashboard_predicate)
diff --git a/aleksis/core/settings.py b/aleksis/core/settings.py
index e8870dc656e05c566ab1e83131d7fc4c70e0b9d5..f6f8f538345f76bbfd3a340ae748c9bbc77e3f09 100644
--- a/aleksis/core/settings.py
+++ b/aleksis/core/settings.py
@@ -377,7 +377,7 @@ ANY_JS = {
         "css_url": JS_URL + "/select2-materialize/select2-materialize.css",
         "js_url": JS_URL + "/select2-materialize/index.js",
     },
-    "sortablejs": {"js_url": JS_URL + "/sortablejs/dist/sortable.umd.js"},
+    "sortablejs": {"js_url": JS_URL + "/sortablejs/Sortable.min.js"},
     "jquery-sortablejs": {"js_url": JS_URL + "/jquery-sortablejs/jquery-sortable.js"},
 }
 
diff --git a/aleksis/core/static/js/main.js b/aleksis/core/static/js/main.js
index 615f8b287df18ed38c57d1f44358073bb74bcf61..45fee5c5bde0eb54655b2fe556c05f9aee573c4f 100644
--- a/aleksis/core/static/js/main.js
+++ b/aleksis/core/static/js/main.js
@@ -58,6 +58,9 @@ $(document).ready(function () {
     // Initialize select [MAT]
     $('select').formSelect();
 
+    // Initialize dropdown [MAT]
+    $('.dropdown-trigger').dropdown();
+
     // If JS is activated, the language form will be auto-submitted
     $('.language-field select').change(function () {
 
@@ -110,3 +113,11 @@ $(document).ready(function () {
         el.addClass("closed").removeClass("opened");
     });
 });
+
+// Show notice if serviceworker broadcasts that the current page comes from its cache
+const channel = new BroadcastChannel("cache-or-not");
+channel.addEventListener("message", event => {
+    if ((event.data) && !($("#cache-alert").length)) {
+        $("main").prepend('<div id="cache-alert" class="alert warning"><p><i class="material-icons left">warning</i>' + gettext("This page may contain outdated information since there is no internet connection.") + '</p> </div>')
+    }
+});
diff --git a/aleksis/core/static/js/serviceworker.js b/aleksis/core/static/js/serviceworker.js
index 818e27cb7d28e820431a4ac28ba6fdf0c422deb7..16382ec00c5dadb22c63060a227451377202d363 100644
--- a/aleksis/core/static/js/serviceworker.js
+++ b/aleksis/core/static/js/serviceworker.js
@@ -5,6 +5,10 @@ const CACHE = 'aleksis-cache';
 
 const offlineFallbackPage = 'offline/';
 
+const channel = new BroadcastChannel('cache-or-not');
+
+var comesFromCache = false;
+
 self.addEventListener("install", function (event) {
     console.log("[AlekSIS PWA] Install Event processing.");
 
@@ -29,6 +33,7 @@ self.addEventListener("activate", function (event) {
 self.addEventListener("fetch", function (event) {
     if (event.request.method !== "GET") return;
     networkFirstFetch(event);
+    if (comesFromCache) channel.postMessage(true);
 });
 
 function networkFirstFetch(event) {
@@ -38,6 +43,7 @@ function networkFirstFetch(event) {
                 // If request was successful, add or update it in the cache
                 console.log("[AlekSIS PWA] Network request successful.");
                 event.waitUntil(updateCache(event.request, response.clone()));
+                comesFromCache = false;
                 return response;
             })
             .catch(function (error) {
@@ -56,10 +62,11 @@ function fromCache(event) {
             .then(function (matching) {
                 if (!matching || matching.status === 404) {
                     console.log("[AlekSIS PWA] Cache request failed. Serving offline fallback page.");
+                    comesFromCache = false;
                     // Use the precached offline page as fallback
-                    return caches.match(offlineFallbackPage)
+                    return caches.match(offlineFallbackPage);
                 }
-
+                comesFromCache = true;
                 return matching;
             });
     });
diff --git a/aleksis/core/static/style.scss b/aleksis/core/static/style.scss
index 81f443f75ab79c34121390bf03da9ab1e611dd5b..a7b29299653c8e40d7b98304dcf2ea6f68ee4de2 100644
--- a/aleksis/core/static/style.scss
+++ b/aleksis/core/static/style.scss
@@ -543,6 +543,10 @@ main .alert p:first-child, main .alert div:first-child {
   height: 100%;
 }
 
+.btn-margin {
+  margin-bottom: 5px;
+}
+
 
 /* Dashboard */
 
diff --git a/aleksis/core/templates/components/materialize-chips.html b/aleksis/core/templates/components/materialize-chips.html
new file mode 100644
index 0000000000000000000000000000000000000000..e8a37bbb456dd47eb1231ecbc7ec541a7944be74
--- /dev/null
+++ b/aleksis/core/templates/components/materialize-chips.html
@@ -0,0 +1,9 @@
+<div class="chip {{ classes }}">
+  {% if img %}
+    <img class="{{ img_classes }}" src="{{ img }}" alt="{{ alt }}">
+  {% endif %}
+  {{ content }}
+  {% if close %}
+    <i class="close material-icons"></i>
+  {% endif %}
+</div>
diff --git a/aleksis/core/templates/core/dashboard_widget/list.html b/aleksis/core/templates/core/dashboard_widget/list.html
index ab384e8620f7c6499adb3e663fdb98e4eb598b2c..6715e3df96e2faed4a1afc78333529039000de32 100644
--- a/aleksis/core/templates/core/dashboard_widget/list.html
+++ b/aleksis/core/templates/core/dashboard_widget/list.html
@@ -2,7 +2,7 @@
 
 {% extends "core/base.html" %}
 
-{% load i18n data_helpers %}
+{% load i18n data_helpers rules %}
 {% load render_table from django_tables2 %}
 
 {% block browser_title %}{% blocktrans %}Dashboard widgets{% endblocktrans %}{% endblock %}
@@ -10,13 +10,28 @@
 
 {% block content %}
 
-  {% for ct, model in widget_types %}
-    <a class="btn green waves-effect waves-light" href="{% url 'create_dashboard_widget' ct.app_label ct.model  %}">
-      <i class="material-icons left">add</i>
-      {% verbose_name_object model as widget_name %}
-      {% blocktrans with name=widget_name %}Create {{ name }}{% endblocktrans %}
+  <a class="btn green waves-effect waves-light dropdown-trigger" href="#" data-target="widget-dropdown">
+    <i class="material-icons left">add</i>
+    {% trans "Create dashboard widget" %}
+  </a>
+  <ul id="widget-dropdown" class="dropdown-content">
+    {% for ct, model in widget_types %}
+      <li>
+        <a href="{% url 'create_dashboard_widget' ct.app_label ct.model %}">
+          {% verbose_name_object model as widget_name %}
+          {% blocktrans with name=widget_name %}Create {{ name }}{% endblocktrans %}
+        </a>
+      </li>
+    {% endfor %}
+  </ul>
+
+  {% has_perm "core.edit_default_dashboard" user as can_edit_default_dashboard %}
+  {% if can_edit_default_dashboard %}
+    <a class="btn orange waves-effect waves-light" href="{% url "edit_default_dashboard" %}">
+      <i class="material-icons left">edit</i>
+      {% trans "Edit default dashboard" %}
     </a>
-  {% endfor %}
+  {% endif %}
 
   {% render_table table %}
 {% endblock %}
diff --git a/aleksis/core/templates/core/data_check/list.html b/aleksis/core/templates/core/data_check/list.html
new file mode 100644
index 0000000000000000000000000000000000000000..5a510fdd92f550ad1b7ff6b0b81983ea225420ba
--- /dev/null
+++ b/aleksis/core/templates/core/data_check/list.html
@@ -0,0 +1,103 @@
+{# -*- engine:django -*- #}
+
+{% extends "core/base.html" %}
+{% load data_helpers %}
+
+{% load i18n %}
+{% load render_table from django_tables2 %}
+
+{% block browser_title %}{% blocktrans %}Data checks{% endblocktrans %}{% endblock %}
+{% block page_title %}{% blocktrans %}Data checks{% endblocktrans %}{% endblock %}
+
+{% block content %}
+  <a class="btn green waves-effect waves-light" href="{% url "data_check_run" %}">
+    <i class="material-icons left">refresh</i>
+    {% trans "Check data again" %}
+  </a>
+
+  {% if results %}
+    <div class="card">
+      <div class="card-content">
+        <i class="material-icons left medium red-text">warning</i>
+        <span class="card-title">{% trans "The system detected some problems with your data." %}</span>
+        <p>{% blocktrans %}Please go through all data and check whether some extra action is
+          needed.{% endblocktrans %}</p>
+      </div>
+    </div>
+  {% else %}
+    <div class="card">
+      <div class="card-content">
+        <i class="material-icons left medium green-text">check_circle</i>
+        <span class="card-title">{% trans "Everything is fine." %}</span>
+        <p>{% blocktrans %}The system hasn't detected any problems with your data.{% endblocktrans %}</p>
+      </div>
+    </div>
+  {% endif %}
+
+  {% if results %}
+    <div class="card">
+      <div class="card-content">
+        <div class="card-title">{% trans "Detected problems" %}</div>
+        <table>
+          <thead>
+          <tr>
+            <th></th>
+            <th colspan="2">{% trans "Affected object" %}</th>
+            <th>{% trans "Detected problem" %}</th>
+            <th>{% trans "Show details" %}</th>
+            <th>{% trans "Options to solve the problem" %}</th>
+          </tr>
+          </thead>
+          <tbody>
+          {% for result in results %}
+            <tr>
+              <td>
+                <code>{{ result.id }}</code>
+              </td>
+              <td>{% verbose_name_object result.related_object %}</td>
+              <td>{{ result.related_object }}</td>
+              <td>{{ result.related_check.problem_name }}</td>
+              <td>
+                <a class="btn-flat waves-effect waves-light" href="{{ result.related_object.get_absolute_url }}">
+                  {% trans "Show object" %}
+                </a>
+              </td>
+              <td>
+                {% for option_name, option in result.related_check.solve_options.items %}
+                  <a class="btn btn-margin waves-effect waves-light"
+                     href="{% url "data_check_solve" result.pk option_name %}">
+                    {{ option.verbose_name }}
+                  </a>
+                {% endfor %}
+              </td>
+            </tr>
+          {% endfor %}
+          </tbody>
+        </table>
+      </div>
+    </div>
+  {% endif %}
+  </div>
+
+  <div class="card hundred-percent">
+    <div class="card-content">
+      <div class="card-title">{% trans "Registered checks" %}</div>
+      <div class="alert primary">
+        <div>
+          <i class="material-icons left">info</i>
+          {% blocktrans %}
+            The system will check for the following problems:
+          {% endblocktrans %}
+        </div>
+      </div>
+      <ul class="collection">
+        {% for check in registered_checks %}
+          <li class="collection-item">
+            <i class="material-icons left">check</i>
+            {{ check.verbose_name }}
+          </li>
+        {% endfor %}
+      </ul>
+    </div>
+  </div>
+{% endblock %}
diff --git a/aleksis/core/templates/core/edit_dashboard.html b/aleksis/core/templates/core/edit_dashboard.html
index a15f24bff8ebcca6a7f9b4ea081d9d8c008f3b0a..09d9afd97ee8b983ed4577267641eae77fd2f14e 100644
--- a/aleksis/core/templates/core/edit_dashboard.html
+++ b/aleksis/core/templates/core/edit_dashboard.html
@@ -1,16 +1,38 @@
 {% extends 'core/base.html' %}
 {% load i18n static dashboard any_js %}
 
-{% block browser_title %}{% blocktrans %}Edit dashboard{% endblocktrans %}{% endblock %}
-{% block page_title %}{% blocktrans %}Edit dashboard{% endblocktrans %}{% endblock %}
+{% block browser_title %}
+  {% if not default_dashboard %}
+    {% trans "Edit dashboard" %}
+  {% else %}
+    {% trans "Edit default dashboard" %}
+  {% endif %}
+{% endblock %}
+{% block page_title %}
+  {% if not default_dashboard %}
+    {% trans "Edit dashboard" %}
+  {% else %}
+    {% trans "Edit default dashboard" %}
+  {% endif %}
+{% endblock %}
 
 {% block content %}
   <div class="alert primary">
     <p>
       <i class="material-icons left">info</i>
-      On this page you can arrange your personal dashboard. You can drag any items from "Available widgets" to "Your
-      Dashboard" or change the order by moving the widgets. After you have finished, please don't forget to click on
-      "Save".
+      {% if not default_dashboard %}
+        {% blocktrans %}
+          On this page you can arrange your personal dashboard. You can drag any items from "Available widgets" to "Your
+          Dashboard" or change the order by moving the widgets. After you have finished, please don't forget to click on
+          "Save".
+        {% endblocktrans %}
+      {% else %}
+        {% blocktrans %}
+          On this page you can arrange the default dashboard which is shown when a user doesn't arrange his own
+          dashboard. You can drag any items from "Available widgets" to "Default Dashboard" or change the order
+          by moving the widgets. After you have finished, please don't forget to click on "Save".
+        {% endblocktrans %}
+      {% endif %}
     </p>
   </div>
 
@@ -30,7 +52,14 @@
     {% endfor %}
   </div>
 
-  <h5>{% trans "Your dashboard" %}</h5>
+  <h5>
+    {% if not default_dashboard %}
+      {% trans "Your dashboard" %}
+    {% else %}
+      {% trans "Default dashboard" %}
+    {% endif %}
+  </h5>
+
   <div class="row card-panel grey lighten-3" id="widgets">
     {% for widget in widgets %}
       {% include "core/partials/edit_dashboard_widget.html" %}
diff --git a/aleksis/core/templates/core/index.html b/aleksis/core/templates/core/index.html
index 93b80ddefffaa8cf72db56a7ef503a694f0514f5..419bb59f11b5084eee7ac379605c3cefe00d530b 100644
--- a/aleksis/core/templates/core/index.html
+++ b/aleksis/core/templates/core/index.html
@@ -42,19 +42,18 @@
         <div class="col s{{ widget.size_s }} m{{ widget.size_m }} l{{ widget.size_l }} xl{{ widget.size_xl }}">
           {% include_widget widget %}
         </div>
-        {% empty %}
-        <div class="col s12 grey-text center">
-          <i class="material-icons medium ">widgets</i>
-          <p class="flow-text">
-            {% blocktrans %}
-              You haven't selected any dashboard widgets. Please click on "Edit dashboard" to add widgets to your
-              personal dashboard.
-            {% endblocktrans %}
-          </p>
-        </div>
       {% endfor %}
     </div>
 
+    {% if default_dashboard and widgets %}
+      <div class="grey-text right">
+        {% blocktrans %}
+          You didn't customise your dashboard so that you see the system default. Please click on "Edit dashboard" to
+          customise your personal dashboard.
+        {% endblocktrans %}
+      </div>
+    {% endif %}
+
     <div class="row">
       <div class="col s12 m6">
         <h5>{% blocktrans %}Last activities{% endblocktrans %}</h5>
diff --git a/aleksis/core/templates/dynamic_preferences/sections.html b/aleksis/core/templates/dynamic_preferences/sections.html
index 39b97496fd4542cfbad440f3571eb2b6f8df86d2..344962dfdfd6ed21ff25aef9056a823904260234 100644
--- a/aleksis/core/templates/dynamic_preferences/sections.html
+++ b/aleksis/core/templates/dynamic_preferences/sections.html
@@ -1,11 +1,6 @@
 {% load i18n %}
 <ul class="tabs">
   <li class="tab ">
-    <a href="{% url registry_url %}"
-       class="{% if not active_section %}active{% endif %}"
-       target="_self">
-      {% trans "All" %}
-    </a>
     {% for section in registry.section_objects.values %}
       <li class="tab">
         <a class="{% if active_section == section.name %}active{% endif %}"
diff --git a/aleksis/core/templates/templated_email/data_checks.css b/aleksis/core/templates/templated_email/data_checks.css
new file mode 100644
index 0000000000000000000000000000000000000000..b385b185ecfe66dcca070e8eb024bbb091917f04
--- /dev/null
+++ b/aleksis/core/templates/templated_email/data_checks.css
@@ -0,0 +1,16 @@
+body {
+    line-height: 1.5;
+    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
+    font-weight: normal;
+    color: rgba(0, 0, 0, 0.87);
+}
+
+.count {
+    text-align: right;
+    font-family: monospace;
+    font-size: 14pt;
+}
+
+td, th {
+    padding: 10px;
+}
diff --git a/aleksis/core/templates/templated_email/data_checks.email b/aleksis/core/templates/templated_email/data_checks.email
new file mode 100644
index 0000000000000000000000000000000000000000..0f9b5a5307fba9152683d4e03b0c41a2105629c7
--- /dev/null
+++ b/aleksis/core/templates/templated_email/data_checks.email
@@ -0,0 +1,44 @@
+{% load i18n %}
+
+{% block subject %}
+ {% trans "The system detected some new problems with your data." %}
+{% endblock %}
+
+{% block plain %}
+ {% trans "Hello," %}
+
+ {% blocktrans %}
+  the system detected some new problems with your data.
+  Please take some time to inspect them and solve the issues or mark them as ignored.
+ {% endblocktrans %}
+
+ {% for result in results %}
+  {{ result.0.problem_name }}: {{ result.1 }}
+ {% endfor %}
+{% endblock %}
+
+{% block html %}
+ <style>
+  {% include "templated_email/data_checks.css" %}
+ </style>
+ <p>{% trans "Hello," %}</p>
+ <p>
+  {% blocktrans %}
+   the system detected some new problems with your data.
+   Please take some time to inspect them and solve the issues or mark them as ignored.
+  {% endblocktrans %}
+ </p>
+
+ <table>
+  <tr>
+   <th>{% trans "Problem description" %}</th>
+   <th>{% trans "Count of objects with new problems" %}</th>
+  </tr>
+  {% for result in results %}
+   <tr>
+    <td>{{ result.0.problem_name }}</td>
+    <td class="count">{{ result.1 }}</td>
+   </tr>
+  {% endfor %}
+ </table>
+{% endblock %}
diff --git a/aleksis/core/urls.py b/aleksis/core/urls.py
index 7f0f81b0960174c8df67fb862a38e4d2bdd38164..30c38b11c9c1e884f62f88a0f62b369f55fe2969 100644
--- a/aleksis/core/urls.py
+++ b/aleksis/core/urls.py
@@ -154,6 +154,13 @@ urlpatterns = [
         name="preferences_group",
     ),
     path("health/", include(health_urls)),
+    path("data_check/", views.DataCheckView.as_view(), name="check_data",),
+    path("data_check/run/", views.RunDataChecks.as_view(), name="data_check_run",),
+    path(
+        "data_check/<int:pk>/<str:solve_option>/",
+        views.SolveDataCheckView.as_view(),
+        name="data_check_solve",
+    ),
     path("dashboard_widgets/", views.DashboardWidgetListView.as_view(), name="dashboard_widgets"),
     path(
         "dashboard_widgets/<int:pk>/edit/",
@@ -170,6 +177,12 @@ urlpatterns = [
         views.DashboardWidgetCreateView.as_view(),
         name="create_dashboard_widget",
     ),
+    path(
+        "dashboard_widgets/default/",
+        views.EditDashboardView.as_view(),
+        {"default": True},
+        name="edit_default_dashboard",
+    ),
 ]
 
 # Serve static files from STATIC_ROOT to make it work with runserver
diff --git a/aleksis/core/util/core_helpers.py b/aleksis/core/util/core_helpers.py
index bef457feee2b0dd53f72591523387d912c4038b1..18fcfc241ea76d96312e1339fbde6fd526218307 100644
--- a/aleksis/core/util/core_helpers.py
+++ b/aleksis/core/util/core_helpers.py
@@ -14,6 +14,7 @@ else:
     import importlib_metadata as metadata
 
 from django.conf import settings
+from django.db import transaction
 from django.db.models import Model, QuerySet
 from django.http import HttpRequest
 from django.shortcuts import get_object_or_404
@@ -195,6 +196,12 @@ def celery_optional(orig: Callable) -> Callable:
     If Celery is configured and available, it wraps the function in a Task
     and calls its delay method when invoked; if not, it leaves it untouched
     and it is executed synchronously.
+
+    The wrapped function returns a tuple with either
+    the return value of the task's delay method and False
+    if the method has been executed asynchronously
+    or the return value of the executed method and True
+    if the method has been executed synchronously.
     """
     if is_celery_enabled():
         from ..celery import app  # noqa
@@ -203,9 +210,9 @@ def celery_optional(orig: Callable) -> Callable:
 
     def wrapped(*args, **kwargs):
         if is_celery_enabled():
-            task.delay(*args, **kwargs)
+            return transaction.on_commit(lambda: task.delay(*args, **kwargs)), False
         else:
-            orig(*args, **kwargs)
+            return orig(*args, **kwargs), True
 
     return wrapped
 
diff --git a/aleksis/core/util/forms.py b/aleksis/core/util/forms.py
new file mode 100644
index 0000000000000000000000000000000000000000..9d7279892f89f47bccebef95786df79ce1f737f1
--- /dev/null
+++ b/aleksis/core/util/forms.py
@@ -0,0 +1,34 @@
+from collections import OrderedDict
+
+from material import Layout, Row
+
+
+class PreferenceLayout(Layout):
+    """django-material Layout object for managing preferences."""
+
+    def __init__(self, form_base_class, section=None):
+        """
+        Create Layout object for the given form_base_class.
+
+        :param form_base_class: A Form class used as the base. Must have a ``registry` attribute
+        :param section: A section where the layout builder will load preferences
+        """
+        registry = form_base_class.registry
+        if section:
+            # Try to use section param
+            preferences_obj = registry.preferences(section=section)
+        else:
+            # display all preferences in the form
+            preferences_obj = registry.preferences()
+
+        rows = OrderedDict()
+
+        for preference in preferences_obj:
+            row_name = preference.get("row", preference.identifier())
+            rows.setdefault(row_name, [])
+            rows[row_name].append(preference.identifier())
+
+        rows_material = []
+        for fields in rows.values():
+            rows_material.append(Row(*fields))
+        super().__init__(*rows_material)
diff --git a/aleksis/core/views.py b/aleksis/core/views.py
index 14cbf2dbeafc7dd84edfadcd5375e97560159011..41b36acfbcff7573366a2328d2d0f9f2a92fe1df 100644
--- a/aleksis/core/views.py
+++ b/aleksis/core/views.py
@@ -5,6 +5,7 @@ from django.conf import settings
 from django.contrib.contenttypes.models import ContentType
 from django.core.exceptions import PermissionDenied
 from django.core.paginator import Paginator
+from django.db.models import QuerySet
 from django.forms.models import BaseModelForm, modelform_factory
 from django.http import HttpRequest, HttpResponse, HttpResponseNotFound
 from django.shortcuts import get_object_or_404, redirect, render
@@ -13,6 +14,8 @@ from django.utils.decorators import method_decorator
 from django.utils.translation import gettext_lazy as _
 from django.views.decorators.cache import never_cache
 from django.views.generic.base import View
+from django.views.generic.detail import DetailView
+from django.views.generic.list import ListView
 
 import reversion
 from django_tables2 import RequestConfig, SingleTableView
@@ -23,8 +26,11 @@ from haystack.query import SearchQuerySet
 from haystack.views import SearchView
 from health_check.views import MainView
 from reversion import set_user
+from reversion.views import RevisionMixin
 from rules.contrib.views import PermissionRequiredMixin, permission_required
 
+from aleksis.core.data_checks import DataCheckRegistry, check_data
+
 from .filters import GroupFilter, PersonFilter
 from .forms import (
     AnnouncementForm,
@@ -46,6 +52,7 @@ from .models import (
     Announcement,
     DashboardWidget,
     DashboardWidgetOrder,
+    DataCheckResult,
     Group,
     GroupType,
     Notification,
@@ -68,6 +75,7 @@ from .tables import (
 from .util import messages
 from .util.apps import AppConfig
 from .util.core_helpers import objectgetter_optional
+from .util.forms import PreferenceLayout
 
 
 @permission_required("core.view_dashboard")
@@ -87,6 +95,12 @@ def index(request: HttpRequest) -> HttpResponse:
     context["announcements"] = announcements
 
     widgets = request.user.person.dashboard_widgets
+
+    if len(widgets) == 0:
+        # Use default dashboard if there are no widgets
+        widgets = DashboardWidgetOrder.default_dashboard_widgets
+        context["default_dashboard"] = True
+
     media = DashboardWidget.get_media(widgets)
 
     context["widgets"] = widgets
@@ -106,7 +120,7 @@ def about(request: HttpRequest) -> HttpResponse:
     return render(request, "core/pages/about.html", context)
 
 
-class SchoolTermListView(SingleTableView, PermissionRequiredMixin):
+class SchoolTermListView(PermissionRequiredMixin, SingleTableView):
     """Table of all school terms."""
 
     model = SchoolTerm
@@ -116,7 +130,7 @@ class SchoolTermListView(SingleTableView, PermissionRequiredMixin):
 
 
 @method_decorator(never_cache, name="dispatch")
-class SchoolTermCreateView(AdvancedCreateView, PermissionRequiredMixin):
+class SchoolTermCreateView(PermissionRequiredMixin, AdvancedCreateView):
     """Create view for school terms."""
 
     model = SchoolTerm
@@ -128,7 +142,7 @@ class SchoolTermCreateView(AdvancedCreateView, PermissionRequiredMixin):
 
 
 @method_decorator(never_cache, name="dispatch")
-class SchoolTermEditView(AdvancedEditView, PermissionRequiredMixin):
+class SchoolTermEditView(PermissionRequiredMixin, AdvancedEditView):
     """Edit view for school terms."""
 
     model = SchoolTerm
@@ -374,7 +388,7 @@ def data_management(request: HttpRequest) -> HttpResponse:
     return render(request, "core/management/data_management.html", context)
 
 
-class SystemStatus(MainView, PermissionRequiredMixin):
+class SystemStatus(PermissionRequiredMixin, MainView):
     """View giving information about the system status."""
 
     template_name = "core/pages/system_status.html"
@@ -531,9 +545,16 @@ def preferences(
         # Invalid registry name passed from URL
         return HttpResponseNotFound()
 
+    if not section and len(registry.sections()) > 0:
+        default_section = list(registry.sections())[0]
+        return redirect(f"preferences_{registry_name}", default_section)
+
     # Build final form from dynamic-preferences
     form_class = preference_form_builder(form_class, instance=instance, section=section)
 
+    # Get layout
+    form_class.layout = PreferenceLayout(form_class, section=section)
+
     if request.method == "POST":
         form = form_class(request.POST, request.FILES or None)
         if form.is_valid():
@@ -702,7 +723,63 @@ def delete_group_type(request: HttpRequest, id_: int) -> HttpResponse:
     return redirect("group_types")
 
 
-class DashboardWidgetListView(SingleTableView, PermissionRequiredMixin):
+class DataCheckView(PermissionRequiredMixin, ListView):
+    permission_required = "core.view_datacheckresults"
+    model = DataCheckResult
+    template_name = "core/data_check/list.html"
+    context_object_name = "results"
+
+    def get_queryset(self) -> QuerySet:
+        return DataCheckResult.objects.filter(solved=False).order_by("check")
+
+    def get_context_data(self, **kwargs: Any) -> Dict[str, Any]:
+        context = super().get_context_data(**kwargs)
+        context["registered_checks"] = DataCheckRegistry.data_checks
+        return context
+
+
+class RunDataChecks(PermissionRequiredMixin, View):
+    permission_required = "core.run_data_checks"
+
+    def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
+        if not check_data()[1]:
+            messages.success(
+                request,
+                _(
+                    "The data check has been started. Please note that it may take "
+                    "a while before you are able to fetch the data on this page."
+                ),
+            )
+        else:
+            messages.success(request, _("The data check has finished."))
+        return redirect("check_data")
+
+
+class SolveDataCheckView(PermissionRequiredMixin, RevisionMixin, DetailView):
+    queryset = DataCheckResult.objects.all()
+    permission_required = "core.solve_data_problem"
+
+    def get(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
+        solve_option = self.kwargs["solve_option"]
+        result = self.get_object()
+        if solve_option in result.related_check.solve_options:
+            solve_option_obj = result.related_check.solve_options[solve_option]
+
+            msg = _(
+                f"The solve option '{solve_option_obj.verbose_name}' "
+                f"has been executed on the object '{result.related_object}' "
+                f"(type: {result.related_object._meta.verbose_name})."
+            )
+
+            result.solve(solve_option)
+
+            messages.success(request, msg)
+            return redirect("check_data")
+        else:
+            return HttpResponseNotFound()
+
+
+class DashboardWidgetListView(PermissionRequiredMixin, SingleTableView):
     """Table of all dashboard widgets."""
 
     model = DashboardWidget
@@ -720,7 +797,7 @@ class DashboardWidgetListView(SingleTableView, PermissionRequiredMixin):
 
 
 @method_decorator(never_cache, name="dispatch")
-class DashboardWidgetEditView(AdvancedEditView, PermissionRequiredMixin):
+class DashboardWidgetEditView(PermissionRequiredMixin, AdvancedEditView):
     """Edit view for dashboard widgets."""
 
     def get_form_class(self) -> Type[BaseModelForm]:
@@ -735,7 +812,7 @@ class DashboardWidgetEditView(AdvancedEditView, PermissionRequiredMixin):
 
 
 @method_decorator(never_cache, name="dispatch")
-class DashboardWidgetCreateView(AdvancedCreateView, PermissionRequiredMixin):
+class DashboardWidgetCreateView(PermissionRequiredMixin, AdvancedCreateView):
     """Create view for dashboard widgets."""
 
     def get_model(self, request, *args, **kwargs):
@@ -777,11 +854,23 @@ class DashboardWidgetDeleteView(PermissionRequiredMixin, AdvancedDeleteView):
 class EditDashboardView(View):
     """View for editing dashboard widget order."""
 
-    def get_context_data(self, request):
+    def get_context_data(self, request, **kwargs):
         context = {}
+        self.default_dashboard = kwargs.get("default", False)
+
+        if self.default_dashboard and not request.user.has_perm("core.edit_default_dashboard"):
+            raise PermissionDenied()
+
+        context["default_dashboard"] = self.default_dashboard
 
-        widgets = request.user.person.dashboard_widgets
-        not_used_widgets = DashboardWidget.objects.exclude(pk__in=[w.pk for w in widgets])
+        widgets = (
+            request.user.person.dashboard_widgets
+            if not self.default_dashboard
+            else DashboardWidgetOrder.default_dashboard_widgets
+        )
+        not_used_widgets = DashboardWidget.objects.exclude(pk__in=[w.pk for w in widgets]).filter(
+            active=True
+        )
         context["widgets"] = widgets
         context["not_used_widgets"] = not_used_widgets
 
@@ -800,8 +889,8 @@ class EditDashboardView(View):
 
         return context
 
-    def post(self, request):
-        context = self.get_context_data(request)
+    def post(self, request, **kwargs):
+        context = self.get_context_data(request, **kwargs)
 
         if context["formset"].is_valid():
             added_objects = []
@@ -811,22 +900,26 @@ class EditDashboardView(View):
 
                 obj, created = DashboardWidgetOrder.objects.update_or_create(
                     widget=form.cleaned_data["pk"],
-                    person=request.user.person,
+                    person=request.user.person if not self.default_dashboard else None,
+                    default=self.default_dashboard,
                     defaults={"order": form.cleaned_data["order"]},
                 )
 
                 added_objects.append(obj.pk)
 
-            DashboardWidgetOrder.objects.filter(person=request.user.person).exclude(
-                pk__in=added_objects
-            ).delete()
+            DashboardWidgetOrder.objects.filter(
+                person=request.user.person if not self.default_dashboard else None,
+                default=self.default_dashboard,
+            ).exclude(pk__in=added_objects).delete()
 
-            messages.success(
-                request, _("Your dashboard configuration has been saved successfully.")
-            )
-            return redirect("index")
+            if not self.default_dashboard:
+                msg = _("Your dashboard configuration has been saved successfully.")
+            else:
+                msg = _("The configuration of the default dashboard has been saved successfully.")
+            messages.success(request, msg)
+            return redirect("index" if not self.default_dashboard else "dashboard_widgets")
 
-    def get(self, request):
-        context = self.get_context_data(request)
+    def get(self, request, **kwargs):
+        context = self.get_context_data(request, **kwargs)
 
         return render(request, "core/edit_dashboard.html", context=context)
diff --git a/poetry.lock b/poetry.lock
index be0e61cd822675c59e9c9fc318fd2f104c7f900a..050abe9881f5ea2dd89b14b83932f3954791bf80 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -46,7 +46,7 @@ reference = "gitlab"
 
 [[package]]
 name = "amqp"
-version = "5.0.2"
+version = "5.0.3"
 description = "Low-level AMQP client for Python (fork of amqplib)."
 category = "main"
 optional = true
@@ -122,6 +122,21 @@ PyYAML = ">=5.3.1"
 six = ">=1.10.0"
 stevedore = ">=1.20.0"
 
+[[package]]
+name = "beautifulsoup4"
+version = "4.9.3"
+description = "Screen-scraping library"
+category = "main"
+optional = false
+python-versions = "*"
+
+[package.dependencies]
+soupsieve = {version = ">1.2", markers = "python_version >= \"3.0\""}
+
+[package.extras]
+html5lib = ["html5lib"]
+lxml = ["lxml"]
+
 [[package]]
 name = "billiard"
 version = "3.6.3.0"
@@ -152,7 +167,7 @@ d = ["aiohttp (>=3.3.2)", "aiohttp-cors"]
 
 [[package]]
 name = "bleach"
-version = "3.2.1"
+version = "3.2.2"
 description = "An easy safelist-based HTML-sanitizing tool."
 category = "main"
 optional = false
@@ -171,6 +186,17 @@ category = "main"
 optional = false
 python-versions = "*"
 
+[[package]]
+name = "bs4"
+version = "0.0.1"
+description = "Dummy package for Beautiful Soup"
+category = "main"
+optional = false
+python-versions = "*"
+
+[package.dependencies]
+beautifulsoup4 = "*"
+
 [[package]]
 name = "calendarweek"
 version = "0.4.7"
@@ -354,7 +380,7 @@ six = "*"
 
 [[package]]
 name = "coverage"
-version = "5.3"
+version = "5.3.1"
 description = "Code coverage measurement for Python"
 category = "dev"
 optional = false
@@ -373,7 +399,7 @@ python-versions = "*"
 
 [[package]]
 name = "django"
-version = "3.1.4"
+version = "3.1.5"
 description = "A high-level Python Web framework that encourages rapid development and clean, pragmatic design."
 category = "main"
 optional = false
@@ -469,7 +495,7 @@ dev = ["flake8", "tox", "twine", "therapist", "black"]
 
 [[package]]
 name = "django-celery-beat"
-version = "2.1.0"
+version = "2.2.0"
 description = "Database-backed Periodic Tasks."
 category = "main"
 optional = true
@@ -477,8 +503,8 @@ python-versions = "*"
 
 [package.dependencies]
 celery = ">=4.4,<6.0"
-Django = ">=2.2"
-django-timezone-field = ">=4.0,<5.0"
+Django = ">=2.2,<4.0"
+django-timezone-field = ">=4.1.0,<5.0"
 python-crontab = ">=2.3.4"
 
 [[package]]
@@ -496,7 +522,7 @@ django-appconf = "*"
 
 [[package]]
 name = "django-celery-results"
-version = "2.0.0"
+version = "2.0.1"
 description = "Celery result backends for Django."
 category = "main"
 optional = true
@@ -635,7 +661,7 @@ Django = ">=2.2"
 
 [[package]]
 name = "django-health-check"
-version = "3.16.1"
+version = "3.16.2"
 description = "Run checks on services like databases, queue servers, celery processes, etc."
 category = "main"
 optional = false
@@ -646,7 +672,7 @@ django = ">=1.11"
 
 [[package]]
 name = "django-impersonate"
-version = "1.7"
+version = "1.7.2"
 description = "Django app to allow superusers to impersonate other users."
 category = "main"
 optional = false
@@ -681,7 +707,7 @@ Django = ">=1.5"
 
 [[package]]
 name = "django-jsonstore"
-version = "0.4.1"
+version = "0.5.0"
 description = "Expose JSONField data as a virtual django model fields."
 category = "main"
 optional = false
@@ -701,7 +727,7 @@ python-versions = "*"
 
 [[package]]
 name = "django-material"
-version = "1.7.3"
+version = "1.7.4"
 description = "Material design for django forms and admin"
 category = "main"
 optional = false
@@ -711,8 +737,8 @@ python-versions = "*"
 six = "*"
 
 [[package]]
-name = "django-menu-generator"
-version = "1.1.0"
+name = "django-menu-generator-ng"
+version = "1.2.0"
 description = "A straightforward menu generator for Django"
 category = "main"
 optional = false
@@ -852,7 +878,7 @@ management-command = ["django-compressor (>=2.4)"]
 
 [[package]]
 name = "django-select2"
-version = "7.5.0"
+version = "7.6.1"
 description = "Select2 option fields for Django"
 category = "main"
 optional = false
@@ -888,7 +914,7 @@ typing-extensions = "*"
 
 [[package]]
 name = "django-tables2"
-version = "2.3.3"
+version = "2.3.4"
 description = "Table/data-grid framework for Django"
 category = "main"
 optional = false
@@ -1020,7 +1046,7 @@ yaml = ["ruamel.yaml"]
 
 [[package]]
 name = "faker"
-version = "5.0.2"
+version = "5.6.5"
 description = "Faker is a Python package that generates fake data for you."
 category = "main"
 optional = false
@@ -1180,7 +1206,7 @@ smmap = ">=3.0.1,<4"
 
 [[package]]
 name = "gitpython"
-version = "3.1.11"
+version = "3.1.12"
 description = "Python Git Library"
 category = "dev"
 optional = false
@@ -1215,7 +1241,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
 
 [[package]]
 name = "importlib-metadata"
-version = "3.3.0"
+version = "3.4.0"
 description = "Read metadata from Python packages"
 category = "main"
 optional = false
@@ -1226,8 +1252,8 @@ typing-extensions = {version = ">=3.6.4", markers = "python_version < \"3.8\""}
 zipp = ">=0.5"
 
 [package.extras]
-docs = ["sphinx", "jaraco.packaging (>=3.2)", "rst.linker (>=1.9)"]
-testing = ["pytest (>=3.5,!=3.7.3)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pytest-cov", "jaraco.test (>=3.2.0)", "packaging", "pep517", "pyfakefs", "flufl.flake8", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"]
+docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"]
+testing = ["pytest (>=3.5,!=3.7.3)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pytest-cov", "pytest-enabler", "packaging", "pep517", "pyfakefs", "flufl.flake8", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"]
 
 [[package]]
 name = "iniconfig"
@@ -1239,7 +1265,7 @@ python-versions = "*"
 
 [[package]]
 name = "isort"
-version = "5.6.4"
+version = "5.7.0"
 description = "A Python utility / library to sort Python imports."
 category = "dev"
 optional = false
@@ -1402,7 +1428,7 @@ scramp = "1.2.0"
 
 [[package]]
 name = "phonenumbers"
-version = "8.12.15"
+version = "8.12.16"
 description = "Python version of Google's common library for parsing, formatting, storing and validating international phone numbers."
 category = "main"
 optional = false
@@ -1410,7 +1436,7 @@ python-versions = "*"
 
 [[package]]
 name = "pillow"
-version = "8.0.1"
+version = "8.1.0"
 description = "Python Imaging Library (Fork)"
 category = "main"
 optional = false
@@ -1443,7 +1469,7 @@ twisted = ["twisted"]
 
 [[package]]
 name = "prompt-toolkit"
-version = "3.0.8"
+version = "3.0.11"
 description = "Library for building powerful interactive command lines in Python"
 category = "main"
 optional = true
@@ -1535,7 +1561,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
 
 [[package]]
 name = "pygments"
-version = "2.7.3"
+version = "2.7.4"
 description = "Pygments is a syntax highlighting package written in Python."
 category = "dev"
 optional = false
@@ -1586,14 +1612,14 @@ testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "requests", "xm
 
 [[package]]
 name = "pytest-cov"
-version = "2.10.1"
+version = "2.11.1"
 description = "Pytest plugin for measuring coverage."
 category = "dev"
 optional = false
 python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
 
 [package.dependencies]
-coverage = ">=4.4"
+coverage = ">=5.2.1"
 pytest = ">=4.6"
 
 [package.extras]
@@ -1690,7 +1716,7 @@ six = ">=1.4.0"
 
 [[package]]
 name = "pytz"
-version = "2020.4"
+version = "2020.5"
 description = "World timezone definitions, modern and historical"
 category = "main"
 optional = false
@@ -1698,11 +1724,11 @@ python-versions = "*"
 
 [[package]]
 name = "pyyaml"
-version = "5.3.1"
+version = "5.4.1"
 description = "YAML parser and emitter for Python"
 category = "dev"
 optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*"
 
 [[package]]
 name = "qrcode"
@@ -1803,7 +1829,7 @@ python-versions = "*"
 
 [[package]]
 name = "safety"
-version = "1.9.0"
+version = "1.10.3"
 description = "Checks installed dependencies for known vulnerabilities."
 category = "dev"
 optional = false
@@ -1858,6 +1884,14 @@ category = "dev"
 optional = false
 python-versions = "*"
 
+[[package]]
+name = "soupsieve"
+version = "2.1"
+description = "A modern CSS selector implementation for Beautiful Soup."
+category = "main"
+optional = false
+python-versions = ">=3.5"
+
 [[package]]
 name = "spdx-license-list"
 version = "0.5.2"
@@ -1868,7 +1902,7 @@ python-versions = "*"
 
 [[package]]
 name = "sphinx"
-version = "3.3.1"
+version = "3.4.3"
 description = "Python documentation generator"
 category = "dev"
 optional = false
@@ -1894,8 +1928,8 @@ sphinxcontrib-serializinghtml = "*"
 
 [package.extras]
 docs = ["sphinxcontrib-websupport"]
-lint = ["flake8 (>=3.5.0)", "flake8-import-order", "mypy (>=0.790)", "docutils-stubs"]
-test = ["pytest", "pytest-cov", "html5lib", "typed-ast", "cython"]
+lint = ["flake8 (>=3.5.0)", "isort", "mypy (>=0.790)", "docutils-stubs"]
+test = ["pytest", "pytest-cov", "html5lib", "cython", "typed-ast"]
 
 [[package]]
 name = "sphinx-autodoc-typehints"
@@ -2021,7 +2055,7 @@ python-versions = "*"
 
 [[package]]
 name = "testfixtures"
-version = "6.17.0"
+version = "6.17.1"
 description = "A collection of helpers and mock objects for unit tests and doc tests."
 category = "dev"
 optional = false
@@ -2076,32 +2110,33 @@ python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
 
 [[package]]
 name = "tqdm"
-version = "4.54.1"
+version = "4.56.0"
 description = "Fast, Extensible Progress Meter"
 category = "main"
 optional = false
 python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7"
 
 [package.extras]
-dev = ["py-make (>=0.1.0)", "twine", "argopt", "pydoc-markdown", "wheel"]
+dev = ["py-make (>=0.1.0)", "twine", "wheel"]
+telegram = ["requests"]
 
 [[package]]
 name = "twilio"
-version = "6.50.1"
+version = "6.51.0"
 description = "Twilio API client and TwiML generator"
 category = "main"
 optional = false
 python-versions = "*"
 
 [package.dependencies]
-PyJWT = ">=1.4.2"
+PyJWT = "1.7.1"
 pytz = "*"
 requests = {version = ">=2.0.0", markers = "python_version >= \"3.0\""}
 six = "*"
 
 [[package]]
 name = "typed-ast"
-version = "1.4.1"
+version = "1.4.2"
 description = "a fork of Python 2 and 3 ast modules with type comment support"
 category = "dev"
 optional = false
@@ -2182,7 +2217,7 @@ ldap = ["django-auth-ldap"]
 [metadata]
 lock-version = "1.1"
 python-versions = "^3.7"
-content-hash = "65a4b7b891965a330e7fec9ed64213579550aac1ac8295aa8c3022a4978d488c"
+content-hash = "b8b44ac64723c99f10cbeaa085976eb30a503e29379801c21495d362933e4aa0"
 
 [metadata.files]
 alabaster = [
@@ -2193,8 +2228,8 @@ aleksis-builddeps = [
     {file = "AlekSIS-Builddeps-1.tar.gz", hash = "sha256:97a19597f422593cbdc438aabf17f95748126c8951df6ac7db7991fc99c108c4"},
 ]
 amqp = [
-    {file = "amqp-5.0.2-py3-none-any.whl", hash = "sha256:5b9062d5c0812335c75434bf17ce33d7a20ecfedaa0733faec7379868eb4068a"},
-    {file = "amqp-5.0.2.tar.gz", hash = "sha256:fcd5b3baeeb7fc19b3486ff6d10543099d40ae1f5c9196eae695d1cde1b2f784"},
+    {file = "amqp-5.0.3-py3-none-any.whl", hash = "sha256:2c58528a05dcbf2ae080f3141b6a5bf467949fad9234edd8b9085b8db2e325fe"},
+    {file = "amqp-5.0.3.tar.gz", hash = "sha256:1733ebf713050504fd9d2ebc661f1fc95b3588f99ee87d2e39c84c27bfd815dc"},
 ]
 appdirs = [
     {file = "appdirs-1.4.4-py2.py3-none-any.whl", hash = "sha256:a841dacd6b99318a741b166adb07e19ee71a274450e68237b4650ca1055ab128"},
@@ -2220,6 +2255,11 @@ bandit = [
     {file = "bandit-1.7.0-py3-none-any.whl", hash = "sha256:216be4d044209fa06cf2a3e51b319769a51be8318140659719aa7a115c35ed07"},
     {file = "bandit-1.7.0.tar.gz", hash = "sha256:8a4c7415254d75df8ff3c3b15cfe9042ecee628a1e40b44c15a98890fbfc2608"},
 ]
+beautifulsoup4 = [
+    {file = "beautifulsoup4-4.9.3-py2-none-any.whl", hash = "sha256:4c98143716ef1cb40bf7f39a8e3eec8f8b009509e74904ba3a7b315431577e35"},
+    {file = "beautifulsoup4-4.9.3-py3-none-any.whl", hash = "sha256:fff47e031e34ec82bf17e00da8f592fe7de69aeea38be00523c04623c04fb666"},
+    {file = "beautifulsoup4-4.9.3.tar.gz", hash = "sha256:84729e322ad1d5b4d25f805bfa05b902dd96450f43842c4e99067d5e1369eb25"},
+]
 billiard = [
     {file = "billiard-3.6.3.0-py3-none-any.whl", hash = "sha256:bff575450859a6e0fbc2f9877d9b715b0bbc07c3565bb7ed2280526a0cdf5ede"},
     {file = "billiard-3.6.3.0.tar.gz", hash = "sha256:d91725ce6425f33a97dfa72fb6bfef0e47d4652acd98a032bd1a7fbf06d5fa6a"},
@@ -2229,13 +2269,16 @@ black = [
     {file = "black-19.10b0.tar.gz", hash = "sha256:c2edb73a08e9e0e6f65a0e6af18b059b8b1cdd5bef997d7a0b181df93dc81539"},
 ]
 bleach = [
-    {file = "bleach-3.2.1-py2.py3-none-any.whl", hash = "sha256:9f8ccbeb6183c6e6cddea37592dfb0167485c1e3b13b3363bc325aa8bda3adbd"},
-    {file = "bleach-3.2.1.tar.gz", hash = "sha256:52b5919b81842b1854196eaae5ca29679a2f2e378905c346d3ca8227c2c66080"},
+    {file = "bleach-3.2.2-py2.py3-none-any.whl", hash = "sha256:a690ccc41a10d806a7c0a9130767750925e4863e332f7e4ea93da1bc12a24300"},
+    {file = "bleach-3.2.2.tar.gz", hash = "sha256:ce6270dd0ae56cd810495b8d994551ae16b41f2b4043cf50064f298985afdb3c"},
 ]
 "boolean.py" = [
     {file = "boolean.py-3.8-py2.py3-none-any.whl", hash = "sha256:d75da0fd0354425fa64f6bbc6cec6ae1485d0eec3447b73187ff8cbf9b572e26"},
     {file = "boolean.py-3.8.tar.gz", hash = "sha256:cc24e20f985d60cd4a3a5a1c0956dd12611159d32a75081dabd0c9ab981acaa4"},
 ]
+bs4 = [
+    {file = "bs4-0.0.1.tar.gz", hash = "sha256:36ecea1fd7cc5c0c6e4a1ff075df26d50da647b75376626cc186e2212886dd3a"},
+]
 calendarweek = [
     {file = "calendarweek-0.4.7-py3-none-any.whl", hash = "sha256:ee65caea113503dcdb33d96bca9f79f88b3ab4f66279d4cb568d89f1f662608a"},
     {file = "calendarweek-0.4.7.tar.gz", hash = "sha256:7655d6a4c3b4f6a4e01aa7d23b49cd121db0399050e9c08cd8d1210155be25dd"},
@@ -2277,6 +2320,7 @@ click-repl = [
 ]
 colorama = [
     {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"},
+    {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"},
 ]
 colour = [
     {file = "colour-0.1.5-py2.py3-none-any.whl", hash = "sha256:33f6db9d564fadc16e59921a56999b79571160ce09916303d35346dddc17978c"},
@@ -2286,48 +2330,63 @@ configobj = [
     {file = "configobj-5.0.6.tar.gz", hash = "sha256:a2f5650770e1c87fb335af19a9b7eb73fc05ccf22144eb68db7d00cd2bcb0902"},
 ]
 coverage = [
-    {file = "coverage-5.3-cp27-cp27m-macosx_10_13_intel.whl", hash = "sha256:bd3166bb3b111e76a4f8e2980fa1addf2920a4ca9b2b8ca36a3bc3dedc618270"},
-    {file = "coverage-5.3-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:9342dd70a1e151684727c9c91ea003b2fb33523bf19385d4554f7897ca0141d4"},
-    {file = "coverage-5.3-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:63808c30b41f3bbf65e29f7280bf793c79f54fb807057de7e5238ffc7cc4d7b9"},
-    {file = "coverage-5.3-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:4d6a42744139a7fa5b46a264874a781e8694bb32f1d76d8137b68138686f1729"},
-    {file = "coverage-5.3-cp27-cp27m-win32.whl", hash = "sha256:86e9f8cd4b0cdd57b4ae71a9c186717daa4c5a99f3238a8723f416256e0b064d"},
-    {file = "coverage-5.3-cp27-cp27m-win_amd64.whl", hash = "sha256:7858847f2d84bf6e64c7f66498e851c54de8ea06a6f96a32a1d192d846734418"},
-    {file = "coverage-5.3-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:530cc8aaf11cc2ac7430f3614b04645662ef20c348dce4167c22d99bec3480e9"},
-    {file = "coverage-5.3-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:381ead10b9b9af5f64646cd27107fb27b614ee7040bb1226f9c07ba96625cbb5"},
-    {file = "coverage-5.3-cp35-cp35m-macosx_10_13_x86_64.whl", hash = "sha256:71b69bd716698fa62cd97137d6f2fdf49f534decb23a2c6fc80813e8b7be6822"},
-    {file = "coverage-5.3-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:1d44bb3a652fed01f1f2c10d5477956116e9b391320c94d36c6bf13b088a1097"},
-    {file = "coverage-5.3-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:1c6703094c81fa55b816f5ae542c6ffc625fec769f22b053adb42ad712d086c9"},
-    {file = "coverage-5.3-cp35-cp35m-win32.whl", hash = "sha256:cedb2f9e1f990918ea061f28a0f0077a07702e3819602d3507e2ff98c8d20636"},
-    {file = "coverage-5.3-cp35-cp35m-win_amd64.whl", hash = "sha256:7f43286f13d91a34fadf61ae252a51a130223c52bfefb50310d5b2deb062cf0f"},
-    {file = "coverage-5.3-cp36-cp36m-macosx_10_13_x86_64.whl", hash = "sha256:c851b35fc078389bc16b915a0a7c1d5923e12e2c5aeec58c52f4aa8085ac8237"},
-    {file = "coverage-5.3-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:aac1ba0a253e17889550ddb1b60a2063f7474155465577caa2a3b131224cfd54"},
-    {file = "coverage-5.3-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:2b31f46bf7b31e6aa690d4c7a3d51bb262438c6dcb0d528adde446531d0d3bb7"},
-    {file = "coverage-5.3-cp36-cp36m-win32.whl", hash = "sha256:c5f17ad25d2c1286436761b462e22b5020d83316f8e8fcb5deb2b3151f8f1d3a"},
-    {file = "coverage-5.3-cp36-cp36m-win_amd64.whl", hash = "sha256:aef72eae10b5e3116bac6957de1df4d75909fc76d1499a53fb6387434b6bcd8d"},
-    {file = "coverage-5.3-cp37-cp37m-macosx_10_13_x86_64.whl", hash = "sha256:e8caf961e1b1a945db76f1b5fa9c91498d15f545ac0ababbe575cfab185d3bd8"},
-    {file = "coverage-5.3-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:29a6272fec10623fcbe158fdf9abc7a5fa032048ac1d8631f14b50fbfc10d17f"},
-    {file = "coverage-5.3-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:2d43af2be93ffbad25dd959899b5b809618a496926146ce98ee0b23683f8c51c"},
-    {file = "coverage-5.3-cp37-cp37m-win32.whl", hash = "sha256:c3888a051226e676e383de03bf49eb633cd39fc829516e5334e69b8d81aae751"},
-    {file = "coverage-5.3-cp37-cp37m-win_amd64.whl", hash = "sha256:9669179786254a2e7e57f0ecf224e978471491d660aaca833f845b72a2df3709"},
-    {file = "coverage-5.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0203acd33d2298e19b57451ebb0bed0ab0c602e5cf5a818591b4918b1f97d516"},
-    {file = "coverage-5.3-cp38-cp38-manylinux1_i686.whl", hash = "sha256:582ddfbe712025448206a5bc45855d16c2e491c2dd102ee9a2841418ac1c629f"},
-    {file = "coverage-5.3-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:0f313707cdecd5cd3e217fc68c78a960b616604b559e9ea60cc16795c4304259"},
-    {file = "coverage-5.3-cp38-cp38-win32.whl", hash = "sha256:78e93cc3571fd928a39c0b26767c986188a4118edc67bc0695bc7a284da22e82"},
-    {file = "coverage-5.3-cp38-cp38-win_amd64.whl", hash = "sha256:8f264ba2701b8c9f815b272ad568d555ef98dfe1576802ab3149c3629a9f2221"},
-    {file = "coverage-5.3-cp39-cp39-macosx_10_13_x86_64.whl", hash = "sha256:50691e744714856f03a86df3e2bff847c2acede4c191f9a1da38f088df342978"},
-    {file = "coverage-5.3-cp39-cp39-manylinux1_i686.whl", hash = "sha256:9361de40701666b034c59ad9e317bae95c973b9ff92513dd0eced11c6adf2e21"},
-    {file = "coverage-5.3-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:c1b78fb9700fc961f53386ad2fd86d87091e06ede5d118b8a50dea285a071c24"},
-    {file = "coverage-5.3-cp39-cp39-win32.whl", hash = "sha256:cb7df71de0af56000115eafd000b867d1261f786b5eebd88a0ca6360cccfaca7"},
-    {file = "coverage-5.3-cp39-cp39-win_amd64.whl", hash = "sha256:47a11bdbd8ada9b7ee628596f9d97fbd3851bd9999d398e9436bd67376dbece7"},
-    {file = "coverage-5.3.tar.gz", hash = "sha256:280baa8ec489c4f542f8940f9c4c2181f0306a8ee1a54eceba071a449fb870a0"},
+    {file = "coverage-5.3.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:fabeeb121735d47d8eab8671b6b031ce08514c86b7ad8f7d5490a7b6dcd6267d"},
+    {file = "coverage-5.3.1-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:7e4d159021c2029b958b2363abec4a11db0ce8cd43abb0d9ce44284cb97217e7"},
+    {file = "coverage-5.3.1-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:378ac77af41350a8c6b8801a66021b52da8a05fd77e578b7380e876c0ce4f528"},
+    {file = "coverage-5.3.1-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:e448f56cfeae7b1b3b5bcd99bb377cde7c4eb1970a525c770720a352bc4c8044"},
+    {file = "coverage-5.3.1-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:cc44e3545d908ecf3e5773266c487ad1877be718d9dc65fc7eb6e7d14960985b"},
+    {file = "coverage-5.3.1-cp27-cp27m-win32.whl", hash = "sha256:08b3ba72bd981531fd557f67beee376d6700fba183b167857038997ba30dd297"},
+    {file = "coverage-5.3.1-cp27-cp27m-win_amd64.whl", hash = "sha256:8dacc4073c359f40fcf73aede8428c35f84639baad7e1b46fce5ab7a8a7be4bb"},
+    {file = "coverage-5.3.1-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:ee2f1d1c223c3d2c24e3afbb2dd38be3f03b1a8d6a83ee3d9eb8c36a52bee899"},
+    {file = "coverage-5.3.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:9a9d4ff06804920388aab69c5ea8a77525cf165356db70131616acd269e19b36"},
+    {file = "coverage-5.3.1-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:782a5c7df9f91979a7a21792e09b34a658058896628217ae6362088b123c8500"},
+    {file = "coverage-5.3.1-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:fda29412a66099af6d6de0baa6bd7c52674de177ec2ad2630ca264142d69c6c7"},
+    {file = "coverage-5.3.1-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:f2c6888eada180814b8583c3e793f3f343a692fc802546eed45f40a001b1169f"},
+    {file = "coverage-5.3.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:8f33d1156241c43755137288dea619105477961cfa7e47f48dbf96bc2c30720b"},
+    {file = "coverage-5.3.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:b239711e774c8eb910e9b1ac719f02f5ae4bf35fa0420f438cdc3a7e4e7dd6ec"},
+    {file = "coverage-5.3.1-cp35-cp35m-manylinux2010_i686.whl", hash = "sha256:f54de00baf200b4539a5a092a759f000b5f45fd226d6d25a76b0dff71177a714"},
+    {file = "coverage-5.3.1-cp35-cp35m-manylinux2010_x86_64.whl", hash = "sha256:be0416074d7f253865bb67630cf7210cbc14eb05f4099cc0f82430135aaa7a3b"},
+    {file = "coverage-5.3.1-cp35-cp35m-win32.whl", hash = "sha256:c46643970dff9f5c976c6512fd35768c4a3819f01f61169d8cdac3f9290903b7"},
+    {file = "coverage-5.3.1-cp35-cp35m-win_amd64.whl", hash = "sha256:9a4f66259bdd6964d8cf26142733c81fb562252db74ea367d9beb4f815478e72"},
+    {file = "coverage-5.3.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:c6e5174f8ca585755988bc278c8bb5d02d9dc2e971591ef4a1baabdf2d99589b"},
+    {file = "coverage-5.3.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:3911c2ef96e5ddc748a3c8b4702c61986628bb719b8378bf1e4a6184bbd48fe4"},
+    {file = "coverage-5.3.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:c5ec71fd4a43b6d84ddb88c1df94572479d9a26ef3f150cef3dacefecf888105"},
+    {file = "coverage-5.3.1-cp36-cp36m-manylinux2010_i686.whl", hash = "sha256:f51dbba78d68a44e99d484ca8c8f604f17e957c1ca09c3ebc2c7e3bbd9ba0448"},
+    {file = "coverage-5.3.1-cp36-cp36m-manylinux2010_x86_64.whl", hash = "sha256:a2070c5affdb3a5e751f24208c5c4f3d5f008fa04d28731416e023c93b275277"},
+    {file = "coverage-5.3.1-cp36-cp36m-win32.whl", hash = "sha256:535dc1e6e68fad5355f9984d5637c33badbdc987b0c0d303ee95a6c979c9516f"},
+    {file = "coverage-5.3.1-cp36-cp36m-win_amd64.whl", hash = "sha256:a4857f7e2bc6921dbd487c5c88b84f5633de3e7d416c4dc0bb70256775551a6c"},
+    {file = "coverage-5.3.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:fac3c432851038b3e6afe086f777732bcf7f6ebbfd90951fa04ee53db6d0bcdd"},
+    {file = "coverage-5.3.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:cd556c79ad665faeae28020a0ab3bda6cd47d94bec48e36970719b0b86e4dcf4"},
+    {file = "coverage-5.3.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:a66ca3bdf21c653e47f726ca57f46ba7fc1f260ad99ba783acc3e58e3ebdb9ff"},
+    {file = "coverage-5.3.1-cp37-cp37m-manylinux2010_i686.whl", hash = "sha256:ab110c48bc3d97b4d19af41865e14531f300b482da21783fdaacd159251890e8"},
+    {file = "coverage-5.3.1-cp37-cp37m-manylinux2010_x86_64.whl", hash = "sha256:e52d3d95df81c8f6b2a1685aabffadf2d2d9ad97203a40f8d61e51b70f191e4e"},
+    {file = "coverage-5.3.1-cp37-cp37m-win32.whl", hash = "sha256:fa10fee7e32213f5c7b0d6428ea92e3a3fdd6d725590238a3f92c0de1c78b9d2"},
+    {file = "coverage-5.3.1-cp37-cp37m-win_amd64.whl", hash = "sha256:ce6f3a147b4b1a8b09aae48517ae91139b1b010c5f36423fa2b866a8b23df879"},
+    {file = "coverage-5.3.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:93a280c9eb736a0dcca19296f3c30c720cb41a71b1f9e617f341f0a8e791a69b"},
+    {file = "coverage-5.3.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:3102bb2c206700a7d28181dbe04d66b30780cde1d1c02c5f3c165cf3d2489497"},
+    {file = "coverage-5.3.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:8ffd4b204d7de77b5dd558cdff986a8274796a1e57813ed005b33fd97e29f059"},
+    {file = "coverage-5.3.1-cp38-cp38-manylinux2010_i686.whl", hash = "sha256:a607ae05b6c96057ba86c811d9c43423f35e03874ffb03fbdcd45e0637e8b631"},
+    {file = "coverage-5.3.1-cp38-cp38-manylinux2010_x86_64.whl", hash = "sha256:3a3c3f8863255f3c31db3889f8055989527173ef6192a283eb6f4db3c579d830"},
+    {file = "coverage-5.3.1-cp38-cp38-win32.whl", hash = "sha256:ff1330e8bc996570221b450e2d539134baa9465f5cb98aff0e0f73f34172e0ae"},
+    {file = "coverage-5.3.1-cp38-cp38-win_amd64.whl", hash = "sha256:3498b27d8236057def41de3585f317abae235dd3a11d33e01736ffedb2ef8606"},
+    {file = "coverage-5.3.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ceb499d2b3d1d7b7ba23abe8bf26df5f06ba8c71127f188333dddcf356b4b63f"},
+    {file = "coverage-5.3.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:3b14b1da110ea50c8bcbadc3b82c3933974dbeea1832e814aab93ca1163cd4c1"},
+    {file = "coverage-5.3.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:76b2775dda7e78680d688daabcb485dc87cf5e3184a0b3e012e1d40e38527cc8"},
+    {file = "coverage-5.3.1-cp39-cp39-manylinux2010_i686.whl", hash = "sha256:cef06fb382557f66d81d804230c11ab292d94b840b3cb7bf4450778377b592f4"},
+    {file = "coverage-5.3.1-cp39-cp39-manylinux2010_x86_64.whl", hash = "sha256:6f61319e33222591f885c598e3e24f6a4be3533c1d70c19e0dc59e83a71ce27d"},
+    {file = "coverage-5.3.1-cp39-cp39-win32.whl", hash = "sha256:cc6f8246e74dd210d7e2b56c76ceaba1cc52b025cd75dbe96eb48791e0250e98"},
+    {file = "coverage-5.3.1-cp39-cp39-win_amd64.whl", hash = "sha256:2757fa64e11ec12220968f65d086b7a29b6583d16e9a544c889b22ba98555ef1"},
+    {file = "coverage-5.3.1-pp36-none-any.whl", hash = "sha256:723d22d324e7997a651478e9c5a3120a0ecbc9a7e94071f7e1954562a8806cf3"},
+    {file = "coverage-5.3.1-pp37-none-any.whl", hash = "sha256:c89b558f8a9a5a6f2cfc923c304d49f0ce629c3bd85cb442ca258ec20366394c"},
+    {file = "coverage-5.3.1.tar.gz", hash = "sha256:38f16b1317b8dd82df67ed5daa5f5e7c959e46579840d77a67a4ceb9cef0a50b"},
 ]
 dj-database-url = [
     {file = "dj-database-url-0.5.0.tar.gz", hash = "sha256:4aeaeb1f573c74835b0686a2b46b85990571159ffc21aa57ecd4d1e1cb334163"},
     {file = "dj_database_url-0.5.0-py2.py3-none-any.whl", hash = "sha256:851785365761ebe4994a921b433062309eb882fedd318e1b0fcecc607ed02da9"},
 ]
 django = [
-    {file = "Django-3.1.4-py3-none-any.whl", hash = "sha256:5c866205f15e7a7123f1eec6ab939d22d5bde1416635cab259684af66d8e48a2"},
-    {file = "Django-3.1.4.tar.gz", hash = "sha256:edb10b5c45e7e9c0fb1dc00b76ec7449aca258a39ffd613dbd078c51d19c9f03"},
+    {file = "Django-3.1.5-py3-none-any.whl", hash = "sha256:efa2ab96b33b20c2182db93147a0c3cd7769d418926f9e9f140a60dca7c64ca9"},
+    {file = "Django-3.1.5.tar.gz", hash = "sha256:2d78425ba74c7a1a74b196058b261b9733a8570782f4e2828974777ccca7edf7"},
 ]
 django-any-js = [
     {file = "django-any-js-1.0.3.post0.tar.gz", hash = "sha256:1da88b44b861b0f54f6b8ea0eb4c7c4fa1a5772e9a4320532cd4e0871a4e23f7"},
@@ -2357,16 +2416,16 @@ django-cache-memoize = [
     {file = "django_cache_memoize-0.1.7-py2.py3-none-any.whl", hash = "sha256:bc7f53725558244af62197d0125732d7ec88ecc1281a3a2f37d77ae1a8c269d3"},
 ]
 django-celery-beat = [
-    {file = "django-celery-beat-2.1.0.tar.gz", hash = "sha256:4eb0e8412e2e05ba0029912a6f80d1054731001eecbcb4d59688c4e07cf4d9d3"},
-    {file = "django_celery_beat-2.1.0-py2.py3-none-any.whl", hash = "sha256:8a169e11d96faed8b72d505ddbc70e7fe0b16cdc854df43cb209c153ed08d651"},
+    {file = "django-celery-beat-2.2.0.tar.gz", hash = "sha256:b8a13afb15e7c53fc04f4f847ac71a6d32088959aba701eb7c4a59f0c28ba543"},
+    {file = "django_celery_beat-2.2.0-py2.py3-none-any.whl", hash = "sha256:c4c72a9579f20eff4c4ccf1b58ebdca5ef940f4210065057db1754ea5f8dffdc"},
 ]
 django-celery-email = [
     {file = "django-celery-email-3.0.0.tar.gz", hash = "sha256:5546cbba80952cc3b8a0ffa4206ce90a4a996a7ffd1c385a2bdb65903ca18ece"},
     {file = "django_celery_email-3.0.0-py2.py3-none-any.whl", hash = "sha256:0f72da39cb2ea83c69440566e87f27cd72f68f247f98ce99fb29889fcf329406"},
 ]
 django-celery-results = [
-    {file = "django_celery_results-2.0.0-py2.py3-none-any.whl", hash = "sha256:f82280a9a25c44048b9e64ae4d47ade7d522c8221304b0e25388080021b95468"},
-    {file = "django_celery_results-2.0.0.tar.gz", hash = "sha256:754e01f22f70fddee5f2ca95c18f183fccee42ad98f9803577bffa717d45ac5d"},
+    {file = "django_celery_results-2.0.1-py2.py3-none-any.whl", hash = "sha256:a2f7d172f7f57dd972538acc6e80a5bf50c673fb4d82fe027189c8659c60dfce"},
+    {file = "django_celery_results-2.0.1.tar.gz", hash = "sha256:d625e324138e5b2ef46ffa9e89fa353c16d619420066ac8b240ef9247b293a84"},
 ]
 django-ckeditor = [
     {file = "django-ckeditor-6.0.0.tar.gz", hash = "sha256:29fd1a333cb9741ac2c3fd4e427a5c00115ed33a2389716a09af7656022dcdde"},
@@ -2412,11 +2471,11 @@ django-haystack = [
     {file = "django_haystack-3.0b1-py3-none-any.whl", hash = "sha256:b83705e1cf8141cd1755fc6683ac65fea4e1281f4b4306bc9224af96495b0df3"},
 ]
 django-health-check = [
-    {file = "django-health-check-3.16.1.tar.gz", hash = "sha256:2cb3944e313e435bdf299288e109f398b6c08b610e09cc90d7f5f6a2bcf469fc"},
-    {file = "django_health_check-3.16.1-py2.py3-none-any.whl", hash = "sha256:8b0835f04ebaeb0d12498a5ef47dd22196237c3987ff28bcce9ed28b5a169d5e"},
+    {file = "django-health-check-3.16.2.tar.gz", hash = "sha256:d5edf773b59e4091ac6bd65280091dbb13d92e70eba5cf8573faa738a9cb481c"},
+    {file = "django_health_check-3.16.2-py2.py3-none-any.whl", hash = "sha256:aec4dd5cfb8333071f535c3611ef805ec2012af9568cf984be351ff1bd4020be"},
 ]
 django-impersonate = [
-    {file = "django-impersonate-1.7.tar.gz", hash = "sha256:1dadb5239a5cb79d4327ef3000cd989f9d4e76428a5e2a080496a53b41fa785f"},
+    {file = "django-impersonate-1.7.2.tar.gz", hash = "sha256:ef1f9fa3180f4d95db0abbca3403f389e901e0beb781afd0db0edface72d148d"},
 ]
 django-ipware = [
     {file = "django-ipware-3.0.2.tar.gz", hash = "sha256:c7df8e1410a8e5d6b1fbae58728402ea59950f043c3582e033e866f0f0cf5e94"},
@@ -2430,18 +2489,20 @@ django-js-reverse = [
     {file = "django_js_reverse-0.9.1-py2.py3-none-any.whl", hash = "sha256:8134c2ab6307c945edfa90671ca65e85d6c1754d48566bdd6464be259cc80c30"},
 ]
 django-jsonstore = [
-    {file = "django-jsonstore-0.4.1.tar.gz", hash = "sha256:d6e42152af3f924e4657c99e80144ba9a6410799256f6134b5a4e9fa4282ec10"},
+    {file = "django-jsonstore-0.5.0.tar.gz", hash = "sha256:896dc10b08f59807eda1c6cebf43cd26e50d0db29d13495c027dc31e464be3c3"},
+    {file = "django_jsonstore-0.5.0-py2-none-any.whl", hash = "sha256:9630c1fb43ae9f8e32733c5cf7d4c3775ba6f08532f517c64025053352d72844"},
 ]
 django-maintenance-mode = [
     {file = "django-maintenance-mode-0.15.1.tar.gz", hash = "sha256:d07102cab88dd707a82232f0c552c287e62aa53af582a0ca4f2aa31f14f5ed27"},
     {file = "django_maintenance_mode-0.15.1-py3-none-any.whl", hash = "sha256:8c45b400253076655562c99a2ffb88f8353fc1c84496c1b9de812cc8132aea6f"},
 ]
 django-material = [
-    {file = "django-material-1.7.3.tar.gz", hash = "sha256:00599cd87f19f3a66be065865b223801afa9da680744a5eac10c489a10d98eba"},
-    {file = "django_material-1.7.3-py2.py3-none-any.whl", hash = "sha256:6c010aa47618ceae2617f8a476b55aaed0884b1a4a6f5bdf969448a1ba72e352"},
+    {file = "django-material-1.7.4.tar.gz", hash = "sha256:93af86e740b6db15a3b9df913c343217b198d7342a083db694acb319b49cb2dd"},
+    {file = "django_material-1.7.4-py2.py3-none-any.whl", hash = "sha256:70dcaa34b35dbc31fbdb7454c7a376358586d0f166abe15870e07e468d729425"},
 ]
-django-menu-generator = [
-    {file = "django-menu-generator-1.1.0.tar.gz", hash = "sha256:e8f9b808080c4b281f9c5962f39078c76c2007a5ef8ab1f7a81c81dbbe6a9848"},
+django-menu-generator-ng = [
+    {file = "django-menu-generator-ng-1.2.0.tar.gz", hash = "sha256:ed3666ffe7d669045958ff45254a8d5afcedfc1824ed27df5c63823f624bf521"},
+    {file = "django_menu_generator_ng-1.2.0-py3-none-any.whl", hash = "sha256:aea14db10b81899c022074dfb0dce058effef1c899b0bd1d2b3491bea1e86ee2"},
 ]
 django-middleware-global-request = [
     {file = "django-middleware-global-request-0.1.2.tar.gz", hash = "sha256:f6490759bc9f7dbde4001709554e29ca715daf847f2222914b4e47117dca9313"},
@@ -2486,8 +2547,8 @@ django-sass-processor = [
     {file = "django-sass-processor-0.8.2.tar.gz", hash = "sha256:9b46a12ca8bdcb397d46fbcc49e6a926ff9f76a93c5efeb23b495419fd01fc7a"},
 ]
 django-select2 = [
-    {file = "django-select2-7.5.0.tar.gz", hash = "sha256:df71dedba9a362041b65e3cd692cb8b4f9e1e17a19681c7b4e61f331868bae0c"},
-    {file = "django_select2-7.5.0-py2.py3-none-any.whl", hash = "sha256:6662aa1c21d4839b8fff38e4c9d402ed3da81f7c5ef7f7e703c862255ba3b9ed"},
+    {file = "django-select2-7.6.1.tar.gz", hash = "sha256:25362c5bafe082a19add598fb0a69e3239b94759691a0ac8e01ab7fba8e650ad"},
+    {file = "django_select2-7.6.1-py2.py3-none-any.whl", hash = "sha256:dc6b6fa737b6ea0b673e27c218955dd51a3fb81b2b28af93ce87703b24f4faf8"},
 ]
 django-settings-context-processor = [
     {file = "django-settings-context-processor-0.2.tar.gz", hash = "sha256:d37c853d69a3069f5abbf94c7f4f6fc0fac38bbd0524190cd5a250ba800e496a"},
@@ -2497,8 +2558,8 @@ django-stubs = [
     {file = "django_stubs-1.7.0-py3-none-any.whl", hash = "sha256:30a7d99c694acf79c5d93d69a5a8e4b54d2a8c11dd672aa869006789e2189fa6"},
 ]
 django-tables2 = [
-    {file = "django-tables2-2.3.3.tar.gz", hash = "sha256:ad38ece83157b8b9c1fb72b0316fcffc4b32d7fec53eec3f2847b83c4c0a2cb2"},
-    {file = "django_tables2-2.3.3-py2.py3-none-any.whl", hash = "sha256:9c175834130ebb2b3a5644431391e09128405e4538637804d5e74a8b96fc9f68"},
+    {file = "django-tables2-2.3.4.tar.gz", hash = "sha256:50ccadbd13740a996d8a4d4f144ef80134745cd0b5ec278061537e341f5ef7a2"},
+    {file = "django_tables2-2.3.4-py2.py3-none-any.whl", hash = "sha256:af5f70a9845fd8690c6b44120b065e55b9771cae99c1dcd0eb4f1cfa3f0a71e4"},
 ]
 django-templated-email = [
     {file = "django-templated-email-2.3.0.tar.gz", hash = "sha256:536c4e5ae099eabfb9aab36087d4d7799948c654e73da55a744213d086d5bb33"},
@@ -2531,8 +2592,8 @@ dynaconf = [
     {file = "dynaconf-3.1.2.tar.gz", hash = "sha256:9b34ab2f811a81755f5eb4beac77a69e1e0887528c7e37fc4bc83fed52dcf502"},
 ]
 faker = [
-    {file = "Faker-5.0.2-py3-none-any.whl", hash = "sha256:5b17c95cfb013a22b062b8df18286f08ce4ea880f9948ec74295e5a42dbb2e44"},
-    {file = "Faker-5.0.2.tar.gz", hash = "sha256:00ce4342c221b1931b2f35d46f5027d35bc62a4ca3a34628b2c5b514b4ca958a"},
+    {file = "Faker-5.6.5-py3-none-any.whl", hash = "sha256:8fe22be90c0db35d830464918f84beb50f970f4caacae4d88e92692857b78aa7"},
+    {file = "Faker-5.6.5.tar.gz", hash = "sha256:0f8198d876bc65edd3699e2542c6ae13cc93fbc4a478c17db190d5d9b6ce790e"},
 ]
 flake8 = [
     {file = "flake8-3.8.4-py2.py3-none-any.whl", hash = "sha256:749dbbd6bfd0cf1318af27bf97a14e28e5ff548ef8e5b1566ccfb25a11e7c839"},
@@ -2580,8 +2641,8 @@ gitdb = [
     {file = "gitdb-4.0.5.tar.gz", hash = "sha256:c9e1f2d0db7ddb9a704c2a0217be31214e91a4fe1dea1efad19ae42ba0c285c9"},
 ]
 gitpython = [
-    {file = "GitPython-3.1.11-py3-none-any.whl", hash = "sha256:6eea89b655917b500437e9668e4a12eabdcf00229a0df1762aabd692ef9b746b"},
-    {file = "GitPython-3.1.11.tar.gz", hash = "sha256:befa4d101f91bad1b632df4308ec64555db684c360bd7d2130b4807d49ce86b8"},
+    {file = "GitPython-3.1.12-py3-none-any.whl", hash = "sha256:867ec3dfb126aac0f8296b19fb63b8c4a399f32b4b6fafe84c4b10af5fa9f7b5"},
+    {file = "GitPython-3.1.12.tar.gz", hash = "sha256:42dbefd8d9e2576c496ed0059f3103dcef7125b9ce16f9d5f9c834aed44a1dac"},
 ]
 html2text = [
     {file = "html2text-2020.1.16-py3-none-any.whl", hash = "sha256:c7c629882da0cf377d66f073329ccf34a12ed2adf0169b9285ae4e63ef54c82b"},
@@ -2596,15 +2657,16 @@ imagesize = [
     {file = "imagesize-1.2.0.tar.gz", hash = "sha256:b1f6b5a4eab1f73479a50fb79fcf729514a900c341d8503d62a62dbc4127a2b1"},
 ]
 importlib-metadata = [
-    {file = "importlib_metadata-3.3.0-py3-none-any.whl", hash = "sha256:bf792d480abbd5eda85794e4afb09dd538393f7d6e6ffef6e9f03d2014cf9450"},
-    {file = "importlib_metadata-3.3.0.tar.gz", hash = "sha256:5c5a2720817414a6c41f0a49993908068243ae02c1635a228126519b509c8aed"},
+    {file = "importlib_metadata-3.4.0-py3-none-any.whl", hash = "sha256:ace61d5fc652dc280e7b6b4ff732a9c2d40db2c0f92bc6cb74e07b73d53a1771"},
+    {file = "importlib_metadata-3.4.0.tar.gz", hash = "sha256:fa5daa4477a7414ae34e95942e4dd07f62adf589143c875c133c1e53c4eff38d"},
 ]
 iniconfig = [
+    {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"},
     {file = "iniconfig-1.1.1.tar.gz", hash = "sha256:bc3af051d7d14b2ee5ef9969666def0cd1a000e121eaea580d4a313df4b37f32"},
 ]
 isort = [
-    {file = "isort-5.6.4-py3-none-any.whl", hash = "sha256:dcab1d98b469a12a1a624ead220584391648790275560e1a43e54c5dceae65e7"},
-    {file = "isort-5.6.4.tar.gz", hash = "sha256:dcaeec1b5f0eca77faea2a35ab790b4f3680ff75590bfcb7145986905aab2f58"},
+    {file = "isort-5.7.0-py3-none-any.whl", hash = "sha256:fff4f0c04e1825522ce6949973e83110a6e907750cd92d128b0d14aaaadbffdc"},
+    {file = "isort-5.7.0.tar.gz", hash = "sha256:c729845434366216d320e936b8ad6f9d681aab72dc7cbc2d51bedc3582f3ad1e"},
 ]
 jinja2 = [
     {file = "Jinja2-2.11.2-py2.py3-none-any.whl", hash = "sha256:f0a4641d3cf955324a89c04f3d94663aa4d638abe8f733ecd3582848e1c37035"},
@@ -2712,38 +2774,42 @@ pg8000 = [
     {file = "pg8000-1.16.6.tar.gz", hash = "sha256:8fc1e6a62ccb7c9830f1e7e9288e2d20eaf373cc8875b5c55b7d5d9b7717be91"},
 ]
 phonenumbers = [
-    {file = "phonenumbers-8.12.15-py2.py3-none-any.whl", hash = "sha256:13d499f7114c4b37c54ee844b188d5e7441951a7da41de5fc1a25ff8fdceef80"},
-    {file = "phonenumbers-8.12.15.tar.gz", hash = "sha256:b734bfcf33e87ddae72196a40b3d1af35abd0beb263816ae18e1bff612926406"},
+    {file = "phonenumbers-8.12.16-py2.py3-none-any.whl", hash = "sha256:56ad29025b8f885945506350b06d77afbc506c5463141d77a5df767280a7ee0b"},
+    {file = "phonenumbers-8.12.16.tar.gz", hash = "sha256:a820ab08c980ef24a2d2a1ead4f8d7016fdf008e484d1aecf7ff0b32cc475e16"},
 ]
 pillow = [
-    {file = "Pillow-8.0.1-cp36-cp36m-macosx_10_10_x86_64.whl", hash = "sha256:b63d4ff734263ae4ce6593798bcfee6dbfb00523c82753a3a03cbc05555a9cc3"},
-    {file = "Pillow-8.0.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:5f9403af9c790cc18411ea398a6950ee2def2a830ad0cfe6dc9122e6d528b302"},
-    {file = "Pillow-8.0.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:6b4a8fd632b4ebee28282a9fef4c341835a1aa8671e2770b6f89adc8e8c2703c"},
-    {file = "Pillow-8.0.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:cc3ea6b23954da84dbee8025c616040d9aa5eaf34ea6895a0a762ee9d3e12e11"},
-    {file = "Pillow-8.0.1-cp36-cp36m-win32.whl", hash = "sha256:d8a96747df78cda35980905bf26e72960cba6d355ace4780d4bdde3b217cdf1e"},
-    {file = "Pillow-8.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:7ba0ba61252ab23052e642abdb17fd08fdcfdbbf3b74c969a30c58ac1ade7cd3"},
-    {file = "Pillow-8.0.1-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:795e91a60f291e75de2e20e6bdd67770f793c8605b553cb6e4387ce0cb302e09"},
-    {file = "Pillow-8.0.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:0a2e8d03787ec7ad71dc18aec9367c946ef8ef50e1e78c71f743bc3a770f9fae"},
-    {file = "Pillow-8.0.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:006de60d7580d81f4a1a7e9f0173dc90a932e3905cc4d47ea909bc946302311a"},
-    {file = "Pillow-8.0.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:bd7bf289e05470b1bc74889d1466d9ad4a56d201f24397557b6f65c24a6844b8"},
-    {file = "Pillow-8.0.1-cp37-cp37m-win32.whl", hash = "sha256:95edb1ed513e68bddc2aee3de66ceaf743590bf16c023fb9977adc4be15bd3f0"},
-    {file = "Pillow-8.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:e38d58d9138ef972fceb7aeec4be02e3f01d383723965bfcef14d174c8ccd039"},
-    {file = "Pillow-8.0.1-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:d3d07c86d4efa1facdf32aa878bd508c0dc4f87c48125cc16b937baa4e5b5e11"},
-    {file = "Pillow-8.0.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:fbd922f702582cb0d71ef94442bfca57624352622d75e3be7a1e7e9360b07e72"},
-    {file = "Pillow-8.0.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:92c882b70a40c79de9f5294dc99390671e07fc0b0113d472cbea3fde15db1792"},
-    {file = "Pillow-8.0.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:7c9401e68730d6c4245b8e361d3d13e1035cbc94db86b49dc7da8bec235d0015"},
-    {file = "Pillow-8.0.1-cp38-cp38-win32.whl", hash = "sha256:6c1aca8231625115104a06e4389fcd9ec88f0c9befbabd80dc206c35561be271"},
-    {file = "Pillow-8.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:cc9ec588c6ef3a1325fa032ec14d97b7309db493782ea8c304666fb10c3bd9a7"},
-    {file = "Pillow-8.0.1-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:eb472586374dc66b31e36e14720747595c2b265ae962987261f044e5cce644b5"},
-    {file = "Pillow-8.0.1-cp39-cp39-manylinux1_i686.whl", hash = "sha256:0eeeae397e5a79dc088d8297a4c2c6f901f8fb30db47795113a4a605d0f1e5ce"},
-    {file = "Pillow-8.0.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:81f812d8f5e8a09b246515fac141e9d10113229bc33ea073fec11403b016bcf3"},
-    {file = "Pillow-8.0.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:895d54c0ddc78a478c80f9c438579ac15f3e27bf442c2a9aa74d41d0e4d12544"},
-    {file = "Pillow-8.0.1-cp39-cp39-win32.whl", hash = "sha256:2fb113757a369a6cdb189f8df3226e995acfed0a8919a72416626af1a0a71140"},
-    {file = "Pillow-8.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:59e903ca800c8cfd1ebe482349ec7c35687b95e98cefae213e271c8c7fffa021"},
-    {file = "Pillow-8.0.1-pp36-pypy36_pp73-macosx_10_10_x86_64.whl", hash = "sha256:5abd653a23c35d980b332bc0431d39663b1709d64142e3652890df4c9b6970f6"},
-    {file = "Pillow-8.0.1-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:4b0ef2470c4979e345e4e0cc1bbac65fda11d0d7b789dbac035e4c6ce3f98adb"},
-    {file = "Pillow-8.0.1-pp37-pypy37_pp73-win32.whl", hash = "sha256:8de332053707c80963b589b22f8e0229f1be1f3ca862a932c1bcd48dafb18dd8"},
-    {file = "Pillow-8.0.1.tar.gz", hash = "sha256:11c5c6e9b02c9dac08af04f093eb5a2f84857df70a7d4a6a6ad461aca803fb9e"},
+    {file = "Pillow-8.1.0-cp36-cp36m-macosx_10_10_x86_64.whl", hash = "sha256:d355502dce85ade85a2511b40b4c61a128902f246504f7de29bbeec1ae27933a"},
+    {file = "Pillow-8.1.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:93a473b53cc6e0b3ce6bf51b1b95b7b1e7e6084be3a07e40f79b42e83503fbf2"},
+    {file = "Pillow-8.1.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:2353834b2c49b95e1313fb34edf18fca4d57446675d05298bb694bca4b194174"},
+    {file = "Pillow-8.1.0-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:1d208e670abfeb41b6143537a681299ef86e92d2a3dac299d3cd6830d5c7bded"},
+    {file = "Pillow-8.1.0-cp36-cp36m-win32.whl", hash = "sha256:dd9eef866c70d2cbbea1ae58134eaffda0d4bfea403025f4db6859724b18ab3d"},
+    {file = "Pillow-8.1.0-cp36-cp36m-win_amd64.whl", hash = "sha256:b09e10ec453de97f9a23a5aa5e30b334195e8d2ddd1ce76cc32e52ba63c8b31d"},
+    {file = "Pillow-8.1.0-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:b02a0b9f332086657852b1f7cb380f6a42403a6d9c42a4c34a561aa4530d5234"},
+    {file = "Pillow-8.1.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:ca20739e303254287138234485579b28cb0d524401f83d5129b5ff9d606cb0a8"},
+    {file = "Pillow-8.1.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:604815c55fd92e735f9738f65dabf4edc3e79f88541c221d292faec1904a4b17"},
+    {file = "Pillow-8.1.0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:cf6e33d92b1526190a1de904df21663c46a456758c0424e4f947ae9aa6088bf7"},
+    {file = "Pillow-8.1.0-cp37-cp37m-win32.whl", hash = "sha256:47c0d93ee9c8b181f353dbead6530b26980fe4f5485aa18be8f1fd3c3cbc685e"},
+    {file = "Pillow-8.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:96d4dc103d1a0fa6d47c6c55a47de5f5dafd5ef0114fa10c85a1fd8e0216284b"},
+    {file = "Pillow-8.1.0-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:7916cbc94f1c6b1301ac04510d0881b9e9feb20ae34094d3615a8a7c3db0dcc0"},
+    {file = "Pillow-8.1.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:3de6b2ee4f78c6b3d89d184ade5d8fa68af0848f9b6b6da2b9ab7943ec46971a"},
+    {file = "Pillow-8.1.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:cdbbe7dff4a677fb555a54f9bc0450f2a21a93c5ba2b44e09e54fcb72d2bd13d"},
+    {file = "Pillow-8.1.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:f50e7a98b0453f39000619d845be8b06e611e56ee6e8186f7f60c3b1e2f0feae"},
+    {file = "Pillow-8.1.0-cp38-cp38-win32.whl", hash = "sha256:cb192176b477d49b0a327b2a5a4979552b7a58cd42037034316b8018ac3ebb59"},
+    {file = "Pillow-8.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:6c5275bd82711cd3dcd0af8ce0bb99113ae8911fc2952805f1d012de7d600a4c"},
+    {file = "Pillow-8.1.0-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:165c88bc9d8dba670110c689e3cc5c71dbe4bfb984ffa7cbebf1fac9554071d6"},
+    {file = "Pillow-8.1.0-cp39-cp39-manylinux1_i686.whl", hash = "sha256:5e2fe3bb2363b862671eba632537cd3a823847db4d98be95690b7e382f3d6378"},
+    {file = "Pillow-8.1.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:7612520e5e1a371d77e1d1ca3a3ee6227eef00d0a9cddb4ef7ecb0b7396eddf7"},
+    {file = "Pillow-8.1.0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:d673c4990acd016229a5c1c4ee8a9e6d8f481b27ade5fc3d95938697fa443ce0"},
+    {file = "Pillow-8.1.0-cp39-cp39-win32.whl", hash = "sha256:dc577f4cfdda354db3ae37a572428a90ffdbe4e51eda7849bf442fb803f09c9b"},
+    {file = "Pillow-8.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:22d070ca2e60c99929ef274cfced04294d2368193e935c5d6febfd8b601bf865"},
+    {file = "Pillow-8.1.0-pp36-pypy36_pp73-macosx_10_10_x86_64.whl", hash = "sha256:a3d3e086474ef12ef13d42e5f9b7bbf09d39cf6bd4940f982263d6954b13f6a9"},
+    {file = "Pillow-8.1.0-pp36-pypy36_pp73-manylinux2010_i686.whl", hash = "sha256:731ca5aabe9085160cf68b2dbef95fc1991015bc0a3a6ea46a371ab88f3d0913"},
+    {file = "Pillow-8.1.0-pp36-pypy36_pp73-manylinux2010_x86_64.whl", hash = "sha256:bba80df38cfc17f490ec651c73bb37cd896bc2400cfba27d078c2135223c1206"},
+    {file = "Pillow-8.1.0-pp37-pypy37_pp73-macosx_10_10_x86_64.whl", hash = "sha256:c3d911614b008e8a576b8e5303e3db29224b455d3d66d1b2848ba6ca83f9ece9"},
+    {file = "Pillow-8.1.0-pp37-pypy37_pp73-manylinux2010_i686.whl", hash = "sha256:39725acf2d2e9c17356e6835dccebe7a697db55f25a09207e38b835d5e1bc032"},
+    {file = "Pillow-8.1.0-pp37-pypy37_pp73-manylinux2010_x86_64.whl", hash = "sha256:81c3fa9a75d9f1afafdb916d5995633f319db09bd773cb56b8e39f1e98d90820"},
+    {file = "Pillow-8.1.0-pp37-pypy37_pp73-win32.whl", hash = "sha256:b6f00ad5ebe846cc91763b1d0c6d30a8042e02b2316e27b05de04fa6ec831ec5"},
+    {file = "Pillow-8.1.0.tar.gz", hash = "sha256:887668e792b7edbfb1d3c9d8b5d8c859269a0f0eba4dda562adb95500f60dbba"},
 ]
 pluggy = [
     {file = "pluggy-0.13.1-py2.py3-none-any.whl", hash = "sha256:966c145cd83c96502c3c3868f50408687b38434af77734af1e9ca461a4081d2d"},
@@ -2754,8 +2820,8 @@ prometheus-client = [
     {file = "prometheus_client-0.9.0.tar.gz", hash = "sha256:9da7b32f02439d8c04f7777021c304ed51d9ec180604700c1ba72a4d44dceb03"},
 ]
 prompt-toolkit = [
-    {file = "prompt_toolkit-3.0.8-py3-none-any.whl", hash = "sha256:7debb9a521e0b1ee7d2fe96ee4bd60ef03c6492784de0547337ca4433e46aa63"},
-    {file = "prompt_toolkit-3.0.8.tar.gz", hash = "sha256:25c95d2ac813909f813c93fde734b6e44406d1477a9faef7c915ff37d39c0a8c"},
+    {file = "prompt_toolkit-3.0.11-py3-none-any.whl", hash = "sha256:0bdd2585e5afd00c5f91dd28eb2090ea67e94c385878921939bb4ccfa3904723"},
+    {file = "prompt_toolkit-3.0.11.tar.gz", hash = "sha256:dc83e6368b0edd9ceabe17a055f2e22f6ed95b9aa39dbd59d0b4f3585bdfe9ed"},
 ]
 psutil = [
     {file = "psutil-5.8.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:0066a82f7b1b37d334e68697faba68e5ad5e858279fd6351c8ca6024e8d6ba64"},
@@ -2800,6 +2866,8 @@ psycopg2 = [
     {file = "psycopg2-2.8.6-cp37-cp37m-win_amd64.whl", hash = "sha256:56fee7f818d032f802b8eed81ef0c1232b8b42390df189cab9cfa87573fe52c5"},
     {file = "psycopg2-2.8.6-cp38-cp38-win32.whl", hash = "sha256:ad2fe8a37be669082e61fb001c185ffb58867fdbb3e7a6b0b0d2ffe232353a3e"},
     {file = "psycopg2-2.8.6-cp38-cp38-win_amd64.whl", hash = "sha256:56007a226b8e95aa980ada7abdea6b40b75ce62a433bd27cec7a8178d57f4051"},
+    {file = "psycopg2-2.8.6-cp39-cp39-win32.whl", hash = "sha256:2c93d4d16933fea5bbacbe1aaf8fa8c1348740b2e50b3735d1b0bf8154cbf0f3"},
+    {file = "psycopg2-2.8.6-cp39-cp39-win_amd64.whl", hash = "sha256:d5062ae50b222da28253059880a871dc87e099c25cb68acf613d9d227413d6f7"},
     {file = "psycopg2-2.8.6.tar.gz", hash = "sha256:fb23f6c71107c37fd667cb4ea363ddeb936b348bbd6449278eb92c189699f543"},
 ]
 py = [
@@ -2844,6 +2912,8 @@ pycryptodome = [
     {file = "pycryptodome-3.9.9-cp27-cp27m-macosx_10_6_intel.whl", hash = "sha256:5598dc6c9dbfe882904e54584322893eff185b98960bbe2cdaaa20e8a437b6e5"},
     {file = "pycryptodome-3.9.9-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:1cfdb92dca388e27e732caa72a1cc624520fe93752a665c3b6cd8f1a91b34916"},
     {file = "pycryptodome-3.9.9-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:5f19e6ef750f677d924d9c7141f54bade3cd56695bbfd8a9ef15d0378557dfe4"},
+    {file = "pycryptodome-3.9.9-cp27-cp27m-win32.whl", hash = "sha256:a3d8a9efa213be8232c59cdc6b65600276508e375e0a119d710826248fd18d37"},
+    {file = "pycryptodome-3.9.9-cp27-cp27m-win_amd64.whl", hash = "sha256:50826b49fbca348a61529693b0031cdb782c39060fb9dca5ac5dff858159dc5a"},
     {file = "pycryptodome-3.9.9-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:19cb674df6c74a14b8b408aa30ba8a89bd1c01e23505100fb45f930fbf0ed0d9"},
     {file = "pycryptodome-3.9.9-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:28f75e58d02019a7edc7d4135203d2501dfc47256d175c72c9798f9a129a49a7"},
     {file = "pycryptodome-3.9.9-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:6d3baaf82681cfb1a842f1c8f77beac791ceedd99af911e4f5fabec32bae2259"},
@@ -2854,17 +2924,26 @@ pycryptodome = [
     {file = "pycryptodome-3.9.9-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:7798e73225a699651888489fbb1dbc565e03a509942a8ce6194bbe6fb582a41f"},
     {file = "pycryptodome-3.9.9-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:46e96aeb8a9ca8b1edf9b1fd0af4bf6afcf3f1ca7fa35529f5d60b98f3e4e959"},
     {file = "pycryptodome-3.9.9-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:843e5f10ecdf9d307032b8b91afe9da1d6ed5bb89d0bbec5c8dcb4ba44008e11"},
+    {file = "pycryptodome-3.9.9-cp36-cp36m-win32.whl", hash = "sha256:b68794fba45bdb367eeb71249c26d23e61167510a1d0c3d6cf0f2f14636e62ee"},
+    {file = "pycryptodome-3.9.9-cp36-cp36m-win_amd64.whl", hash = "sha256:60febcf5baf70c566d9d9351c47fbd8321da9a4edf2eff45c4c31c86164ca794"},
     {file = "pycryptodome-3.9.9-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:4ed27951b0a17afd287299e2206a339b5b6d12de9321e1a1575261ef9c4a851b"},
     {file = "pycryptodome-3.9.9-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:9000877383e2189dafd1b2fc68c6c726eca9a3cfb6d68148fbb72ccf651959b6"},
     {file = "pycryptodome-3.9.9-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:faa682c404c218e8788c3126c9a4b8fbcc54dc245b5b6e8ea5b46f3b63bd0c84"},
     {file = "pycryptodome-3.9.9-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:62c488a21c253dadc9f731a32f0ac61e4e436d81a1ea6f7d1d9146ed4d20d6bd"},
+    {file = "pycryptodome-3.9.9-cp37-cp37m-win32.whl", hash = "sha256:834b790bbb6bd18956f625af4004d9c15eed12d5186d8e57851454ae76d52215"},
+    {file = "pycryptodome-3.9.9-cp37-cp37m-win_amd64.whl", hash = "sha256:70d807d11d508433daf96244ec1c64e55039e8a35931fc5ea9eee94dbe3cb6b5"},
     {file = "pycryptodome-3.9.9-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:27397aee992af69d07502126561d851ba3845aa808f0e55c71ad0efa264dd7d4"},
     {file = "pycryptodome-3.9.9-cp38-cp38-manylinux1_i686.whl", hash = "sha256:d7ec2bd8f57c559dd24e71891c51c25266a8deb66fc5f02cc97c7fb593d1780a"},
     {file = "pycryptodome-3.9.9-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:e15bde67ccb7d4417f627dd16ffe2f5a4c2941ce5278444e884cb26d73ecbc61"},
     {file = "pycryptodome-3.9.9-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:5c3c4865730dfb0263f822b966d6d58429d8b1e560d1ddae37685fd9e7c63161"},
+    {file = "pycryptodome-3.9.9-cp38-cp38-win32.whl", hash = "sha256:76b1a34d74bb2c91bce460cdc74d1347592045627a955e9a252554481c17c52f"},
+    {file = "pycryptodome-3.9.9-cp38-cp38-win_amd64.whl", hash = "sha256:6e4227849e4231a3f5b35ea5bdedf9a82b3883500e5624f00a19156e9a9ef861"},
     {file = "pycryptodome-3.9.9-cp39-cp39-manylinux1_i686.whl", hash = "sha256:2a68df525b387201a43b27b879ce8c08948a430e883a756d6c9e3acdaa7d7bd8"},
     {file = "pycryptodome-3.9.9-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:a4599c0ca0fc027c780c1c45ed996d5bef03e571470b7b1c7171ec1e1a90914c"},
     {file = "pycryptodome-3.9.9-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:b4e6b269a8ddaede774e5c3adbef6bf452ee144e6db8a716d23694953348cd86"},
+    {file = "pycryptodome-3.9.9-cp39-cp39-win32.whl", hash = "sha256:a199e9ca46fc6e999e5f47fce342af4b56c7de85fae893c69ab6aa17531fb1e1"},
+    {file = "pycryptodome-3.9.9-cp39-cp39-win_amd64.whl", hash = "sha256:6e89bb3826e6f84501e8e3b205c22595d0c5492c2f271cbb9ee1c48eb1866645"},
+    {file = "pycryptodome-3.9.9.tar.gz", hash = "sha256:910e202a557e1131b1c1b3f17a63914d57aac55cf9fb9b51644962841c3995c4"},
 ]
 pydocstyle = [
     {file = "pydocstyle-5.1.1-py3-none-any.whl", hash = "sha256:aca749e190a01726a4fb472dd4ef23b5c9da7b9205c0a7857c06533de13fd678"},
@@ -2875,8 +2954,8 @@ pyflakes = [
     {file = "pyflakes-2.2.0.tar.gz", hash = "sha256:35b2d75ee967ea93b55750aa9edbbf72813e06a66ba54438df2cfac9e3c27fc8"},
 ]
 pygments = [
-    {file = "Pygments-2.7.3-py3-none-any.whl", hash = "sha256:f275b6c0909e5dafd2d6269a656aa90fa58ebf4a74f8fcf9053195d226b24a08"},
-    {file = "Pygments-2.7.3.tar.gz", hash = "sha256:ccf3acacf3782cbed4a989426012f1c535c9a90d3a7fc3f16d231b9372d2b716"},
+    {file = "Pygments-2.7.4-py3-none-any.whl", hash = "sha256:bc9591213a8f0e0ca1a5e68a479b4887fdc3e75d0774e5c71c31920c427de435"},
+    {file = "Pygments-2.7.4.tar.gz", hash = "sha256:df49d09b498e83c1a73128295860250b0b7edd4c723a32e9bc0d295c7c2ec337"},
 ]
 pyjwt = [
     {file = "PyJWT-1.7.1-py2.py3-none-any.whl", hash = "sha256:5c6eca3c2940464d106b99ba83b00c6add741c9becaec087fb7ccdefea71350e"},
@@ -2891,8 +2970,8 @@ pytest = [
     {file = "pytest-6.2.1.tar.gz", hash = "sha256:66e419b1899bc27346cb2c993e12c5e5e8daba9073c1fbce33b9807abc95c306"},
 ]
 pytest-cov = [
-    {file = "pytest-cov-2.10.1.tar.gz", hash = "sha256:47bd0ce14056fdd79f93e1713f88fad7bdcc583dcd7783da86ef2f085a0bb88e"},
-    {file = "pytest_cov-2.10.1-py2.py3-none-any.whl", hash = "sha256:45ec2d5182f89a81fc3eb29e3d1ed3113b9e9a873bcddb2a71faaab066110191"},
+    {file = "pytest-cov-2.11.1.tar.gz", hash = "sha256:359952d9d39b9f822d9d29324483e7ba04a3a17dd7d05aa6beb7ea01e359e5f7"},
+    {file = "pytest_cov-2.11.1-py2.py3-none-any.whl", hash = "sha256:bdb9fdb0b85a7cc825269a4c56b48ccaa5c7e365054b6038772c32ddcdc969da"},
 ]
 pytest-django = [
     {file = "pytest-django-3.10.0.tar.gz", hash = "sha256:4de6dbd077ed8606616958f77655fed0d5e3ee45159475671c7fa67596c6dba6"},
@@ -2920,21 +2999,31 @@ python-memcached = [
     {file = "python_memcached-1.59-py2.py3-none-any.whl", hash = "sha256:4dac64916871bd3550263323fc2ce18e1e439080a2d5670c594cf3118d99b594"},
 ]
 pytz = [
-    {file = "pytz-2020.4-py2.py3-none-any.whl", hash = "sha256:5c55e189b682d420be27c6995ba6edce0c0a77dd67bfbe2ae6607134d5851ffd"},
-    {file = "pytz-2020.4.tar.gz", hash = "sha256:3e6b7dd2d1e0a59084bcee14a17af60c5c562cdc16d828e8eba2e683d3a7e268"},
+    {file = "pytz-2020.5-py2.py3-none-any.whl", hash = "sha256:16962c5fb8db4a8f63a26646d8886e9d769b6c511543557bc84e9569fb9a9cb4"},
+    {file = "pytz-2020.5.tar.gz", hash = "sha256:180befebb1927b16f6b57101720075a984c019ac16b1b7575673bea42c6c3da5"},
 ]
 pyyaml = [
-    {file = "PyYAML-5.3.1-cp27-cp27m-win32.whl", hash = "sha256:74809a57b329d6cc0fdccee6318f44b9b8649961fa73144a98735b0aaf029f1f"},
-    {file = "PyYAML-5.3.1-cp27-cp27m-win_amd64.whl", hash = "sha256:240097ff019d7c70a4922b6869d8a86407758333f02203e0fc6ff79c5dcede76"},
-    {file = "PyYAML-5.3.1-cp35-cp35m-win32.whl", hash = "sha256:4f4b913ca1a7319b33cfb1369e91e50354d6f07a135f3b901aca02aa95940bd2"},
-    {file = "PyYAML-5.3.1-cp35-cp35m-win_amd64.whl", hash = "sha256:cc8955cfbfc7a115fa81d85284ee61147059a753344bc51098f3ccd69b0d7e0c"},
-    {file = "PyYAML-5.3.1-cp36-cp36m-win32.whl", hash = "sha256:7739fc0fa8205b3ee8808aea45e968bc90082c10aef6ea95e855e10abf4a37b2"},
-    {file = "PyYAML-5.3.1-cp36-cp36m-win_amd64.whl", hash = "sha256:69f00dca373f240f842b2931fb2c7e14ddbacd1397d57157a9b005a6a9942648"},
-    {file = "PyYAML-5.3.1-cp37-cp37m-win32.whl", hash = "sha256:d13155f591e6fcc1ec3b30685d50bf0711574e2c0dfffd7644babf8b5102ca1a"},
-    {file = "PyYAML-5.3.1-cp37-cp37m-win_amd64.whl", hash = "sha256:73f099454b799e05e5ab51423c7bcf361c58d3206fa7b0d555426b1f4d9a3eaf"},
-    {file = "PyYAML-5.3.1-cp38-cp38-win32.whl", hash = "sha256:06a0d7ba600ce0b2d2fe2e78453a470b5a6e000a985dd4a4e54e436cc36b0e97"},
-    {file = "PyYAML-5.3.1-cp38-cp38-win_amd64.whl", hash = "sha256:95f71d2af0ff4227885f7a6605c37fd53d3a106fcab511b8860ecca9fcf400ee"},
-    {file = "PyYAML-5.3.1.tar.gz", hash = "sha256:b8eac752c5e14d3eca0e6dd9199cd627518cb5ec06add0de9d32baeee6fe645d"},
+    {file = "PyYAML-5.4.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922"},
+    {file = "PyYAML-5.4.1-cp27-cp27m-win32.whl", hash = "sha256:129def1b7c1bf22faffd67b8f3724645203b79d8f4cc81f674654d9902cb4393"},
+    {file = "PyYAML-5.4.1-cp27-cp27m-win_amd64.whl", hash = "sha256:4465124ef1b18d9ace298060f4eccc64b0850899ac4ac53294547536533800c8"},
+    {file = "PyYAML-5.4.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185"},
+    {file = "PyYAML-5.4.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253"},
+    {file = "PyYAML-5.4.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc"},
+    {file = "PyYAML-5.4.1-cp36-cp36m-win32.whl", hash = "sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5"},
+    {file = "PyYAML-5.4.1-cp36-cp36m-win_amd64.whl", hash = "sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df"},
+    {file = "PyYAML-5.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018"},
+    {file = "PyYAML-5.4.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63"},
+    {file = "PyYAML-5.4.1-cp37-cp37m-win32.whl", hash = "sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b"},
+    {file = "PyYAML-5.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf"},
+    {file = "PyYAML-5.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46"},
+    {file = "PyYAML-5.4.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb"},
+    {file = "PyYAML-5.4.1-cp38-cp38-win32.whl", hash = "sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc"},
+    {file = "PyYAML-5.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696"},
+    {file = "PyYAML-5.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77"},
+    {file = "PyYAML-5.4.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183"},
+    {file = "PyYAML-5.4.1-cp39-cp39-win32.whl", hash = "sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10"},
+    {file = "PyYAML-5.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db"},
+    {file = "PyYAML-5.4.1.tar.gz", hash = "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e"},
 ]
 qrcode = [
     {file = "qrcode-6.1-py2.py3-none-any.whl", hash = "sha256:3996ee560fc39532910603704c82980ff6d4d5d629f9c3f25f34174ce8606cf5"},
@@ -3006,28 +3095,37 @@ restructuredtext-lint = [
     {file = "ruamel.yaml.clib-0.2.2-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:73b3d43e04cc4b228fa6fa5d796409ece6fcb53a6c270eb2048109cbcbc3b9c2"},
     {file = "ruamel.yaml.clib-0.2.2-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:53b9dd1abd70e257a6e32f934ebc482dac5edb8c93e23deb663eac724c30b026"},
     {file = "ruamel.yaml.clib-0.2.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:839dd72545ef7ba78fd2aa1a5dd07b33696adf3e68fae7f31327161c1093001b"},
+    {file = "ruamel.yaml.clib-0.2.2-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:1236df55e0f73cd138c0eca074ee086136c3f16a97c2ac719032c050f7e0622f"},
     {file = "ruamel.yaml.clib-0.2.2-cp35-cp35m-win32.whl", hash = "sha256:b1e981fe1aff1fd11627f531524826a4dcc1f26c726235a52fcb62ded27d150f"},
     {file = "ruamel.yaml.clib-0.2.2-cp35-cp35m-win_amd64.whl", hash = "sha256:4e52c96ca66de04be42ea2278012a2342d89f5e82b4512fb6fb7134e377e2e62"},
     {file = "ruamel.yaml.clib-0.2.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:a873e4d4954f865dcb60bdc4914af7eaae48fb56b60ed6daa1d6251c72f5337c"},
     {file = "ruamel.yaml.clib-0.2.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:ab845f1f51f7eb750a78937be9f79baea4a42c7960f5a94dde34e69f3cce1988"},
+    {file = "ruamel.yaml.clib-0.2.2-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:2fd336a5c6415c82e2deb40d08c222087febe0aebe520f4d21910629018ab0f3"},
     {file = "ruamel.yaml.clib-0.2.2-cp36-cp36m-win32.whl", hash = "sha256:e9f7d1d8c26a6a12c23421061f9022bb62704e38211fe375c645485f38df34a2"},
     {file = "ruamel.yaml.clib-0.2.2-cp36-cp36m-win_amd64.whl", hash = "sha256:2602e91bd5c1b874d6f93d3086f9830f3e907c543c7672cf293a97c3fabdcd91"},
     {file = "ruamel.yaml.clib-0.2.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:44c7b0498c39f27795224438f1a6be6c5352f82cb887bc33d962c3a3acc00df6"},
     {file = "ruamel.yaml.clib-0.2.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:8e8fd0a22c9d92af3a34f91e8a2594eeb35cba90ab643c5e0e643567dc8be43e"},
+    {file = "ruamel.yaml.clib-0.2.2-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:75f0ee6839532e52a3a53f80ce64925ed4aed697dd3fa890c4c918f3304bd4f4"},
     {file = "ruamel.yaml.clib-0.2.2-cp37-cp37m-win32.whl", hash = "sha256:464e66a04e740d754170be5e740657a3b3b6d2bcc567f0c3437879a6e6087ff6"},
     {file = "ruamel.yaml.clib-0.2.2-cp37-cp37m-win_amd64.whl", hash = "sha256:52ae5739e4b5d6317b52f5b040b1b6639e8af68a5b8fd606a8b08658fbd0cab5"},
     {file = "ruamel.yaml.clib-0.2.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:4df5019e7783d14b79217ad9c56edf1ba7485d614ad5a385d1b3c768635c81c0"},
     {file = "ruamel.yaml.clib-0.2.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:5254af7d8bdf4d5484c089f929cb7f5bafa59b4f01d4f48adda4be41e6d29f99"},
+    {file = "ruamel.yaml.clib-0.2.2-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:8be05be57dc5c7b4a0b24edcaa2f7275866d9c907725226cdde46da09367d923"},
     {file = "ruamel.yaml.clib-0.2.2-cp38-cp38-win32.whl", hash = "sha256:74161d827407f4db9072011adcfb825b5258a5ccb3d2cd518dd6c9edea9e30f1"},
     {file = "ruamel.yaml.clib-0.2.2-cp38-cp38-win_amd64.whl", hash = "sha256:058a1cc3df2a8aecc12f983a48bda99315cebf55a3b3a5463e37bb599b05727b"},
+    {file = "ruamel.yaml.clib-0.2.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c6ac7e45367b1317e56f1461719c853fd6825226f45b835df7436bb04031fd8a"},
+    {file = "ruamel.yaml.clib-0.2.2-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:b4b0d31f2052b3f9f9b5327024dc629a253a83d8649d4734ca7f35b60ec3e9e5"},
+    {file = "ruamel.yaml.clib-0.2.2-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:1f8c0a4577c0e6c99d208de5c4d3fd8aceed9574bb154d7a2b21c16bb924154c"},
+    {file = "ruamel.yaml.clib-0.2.2-cp39-cp39-win32.whl", hash = "sha256:46d6d20815064e8bb023ea8628cfb7402c0f0e83de2c2227a88097e239a7dffd"},
+    {file = "ruamel.yaml.clib-0.2.2-cp39-cp39-win_amd64.whl", hash = "sha256:6c0a5dc52fc74eb87c67374a4e554d4761fd42a4d01390b7e868b30d21f4b8bb"},
     {file = "ruamel.yaml.clib-0.2.2.tar.gz", hash = "sha256:2d24bd98af676f4990c4d715bcdc2a60b19c56a3fb3a763164d2d8ca0e806ba7"},
 ]
 rules = [
     {file = "rules-2.2.tar.gz", hash = "sha256:9bae429f9d4f91a375402990da1541f9e093b0ac077221d57124d06eeeca4405"},
 ]
 safety = [
-    {file = "safety-1.9.0-py2.py3-none-any.whl", hash = "sha256:86c1c4a031fe35bd624fce143fbe642a0234d29f7cbf7a9aa269f244a955b087"},
-    {file = "safety-1.9.0.tar.gz", hash = "sha256:23bf20690d4400edc795836b0c983c2b4cbbb922233108ff925b7dd7750f00c9"},
+    {file = "safety-1.10.3-py2.py3-none-any.whl", hash = "sha256:5f802ad5df5614f9622d8d71fedec2757099705c2356f862847c58c6dfe13e84"},
+    {file = "safety-1.10.3.tar.gz", hash = "sha256:30e394d02a20ac49b7f65292d19d38fa927a8f9582cdfd3ad1adbbc66c641ad5"},
 ]
 scramp = [
     {file = "scramp-1.2.0-py3-none-any.whl", hash = "sha256:74815c25aad1fe0b5fb994e96c3de63e8695164358a80138352aaadfa4760350"},
@@ -3049,13 +3147,17 @@ snowballstemmer = [
     {file = "snowballstemmer-2.0.0-py2.py3-none-any.whl", hash = "sha256:209f257d7533fdb3cb73bdbd24f436239ca3b2fa67d56f6ff88e86be08cc5ef0"},
     {file = "snowballstemmer-2.0.0.tar.gz", hash = "sha256:df3bac3df4c2c01363f3dd2cfa78cce2840a79b9f1c2d2de9ce8d31683992f52"},
 ]
+soupsieve = [
+    {file = "soupsieve-2.1-py3-none-any.whl", hash = "sha256:4bb21a6ee4707bf43b61230e80740e71bfe56e55d1f1f50924b087bb2975c851"},
+    {file = "soupsieve-2.1.tar.gz", hash = "sha256:6dc52924dc0bc710a5d16794e6b3480b2c7c08b07729505feab2b2c16661ff6e"},
+]
 spdx-license-list = [
     {file = "spdx_license_list-0.5.2-py3-none-any.whl", hash = "sha256:1b338470c7b403dbecceca563a316382c7977516128ca6c1e8f7078e3ed6e7b0"},
     {file = "spdx_license_list-0.5.2.tar.gz", hash = "sha256:952996f72ab807972dc2278bb9b91e5294767211e51f09aad9c0e2ff5b82a31b"},
 ]
 sphinx = [
-    {file = "Sphinx-3.3.1-py3-none-any.whl", hash = "sha256:d4e59ad4ea55efbb3c05cde3bfc83bfc14f0c95aa95c3d75346fcce186a47960"},
-    {file = "Sphinx-3.3.1.tar.gz", hash = "sha256:1e8d592225447104d1172be415bc2972bd1357e3e12fdc76edf2261105db4300"},
+    {file = "Sphinx-3.4.3-py3-none-any.whl", hash = "sha256:c314c857e7cd47c856d2c5adff514ac2e6495f8b8e0f886a8a37e9305dfea0d8"},
+    {file = "Sphinx-3.4.3.tar.gz", hash = "sha256:41cad293f954f7d37f803d97eb184158cfd90f51195131e94875bc07cd08b93c"},
 ]
 sphinx-autodoc-typehints = [
     {file = "sphinx-autodoc-typehints-1.11.1.tar.gz", hash = "sha256:244ba6d3e2fdb854622f643c7763d6f95b6886eba24bec28e86edf205e4ddb20"},
@@ -3101,8 +3203,8 @@ termcolor = [
     {file = "termcolor-1.1.0.tar.gz", hash = "sha256:1d6d69ce66211143803fbc56652b41d73b4a400a2891d7bf7a1cdf4c02de613b"},
 ]
 testfixtures = [
-    {file = "testfixtures-6.17.0-py2.py3-none-any.whl", hash = "sha256:ebcc3e024d47bb58a60cdc678604151baa0c920ae2814004c89ac9066de31b2c"},
-    {file = "testfixtures-6.17.0.tar.gz", hash = "sha256:fa7c170df68ca6367eda061e9ec339ae3e6d3679c31e04033f83ef97a7d7d0ce"},
+    {file = "testfixtures-6.17.1-py2.py3-none-any.whl", hash = "sha256:9ed31e83f59619e2fa17df053b241e16e0608f4580f7b5a9333a0c9bdcc99137"},
+    {file = "testfixtures-6.17.1.tar.gz", hash = "sha256:5ec3a0dd6f71cc4c304fbc024a10cc293d3e0b852c868014b9f233203e149bda"},
 ]
 "testing.common.database" = [
     {file = "testing.common.database-2.0.3-py2.py3-none-any.whl", hash = "sha256:e3ed492bf480a87f271f74c53b262caf5d85c8bc09989a8f534fa2283ec52492"},
@@ -3121,34 +3223,43 @@ toml = [
     {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
 ]
 tqdm = [
-    {file = "tqdm-4.54.1-py2.py3-none-any.whl", hash = "sha256:d4f413aecb61c9779888c64ddf0c62910ad56dcbe857d8922bb505d4dbff0df1"},
-    {file = "tqdm-4.54.1.tar.gz", hash = "sha256:38b658a3e4ecf9b4f6f8ff75ca16221ae3378b2e175d846b6b33ea3a20852cf5"},
+    {file = "tqdm-4.56.0-py2.py3-none-any.whl", hash = "sha256:4621f6823bab46a9cc33d48105753ccbea671b68bab2c50a9f0be23d4065cb5a"},
+    {file = "tqdm-4.56.0.tar.gz", hash = "sha256:fe3d08dd00a526850568d542ff9de9bbc2a09a791da3c334f3213d8d0bbbca65"},
 ]
 twilio = [
-    {file = "twilio-6.50.1.tar.gz", hash = "sha256:dd8371c9b4ea422d6de7526b63b587da82e8488f2b3f6b1258d2cad6e4006a65"},
+    {file = "twilio-6.51.0.tar.gz", hash = "sha256:de98a05858e6efdf87bfa4c8f7e773adf1885cfcbb6531356840bcd17dc4c444"},
 ]
 typed-ast = [
-    {file = "typed_ast-1.4.1-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:73d785a950fc82dd2a25897d525d003f6378d1cb23ab305578394694202a58c3"},
-    {file = "typed_ast-1.4.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:aaee9905aee35ba5905cfb3c62f3e83b3bec7b39413f0a7f19be4e547ea01ebb"},
-    {file = "typed_ast-1.4.1-cp35-cp35m-win32.whl", hash = "sha256:0c2c07682d61a629b68433afb159376e24e5b2fd4641d35424e462169c0a7919"},
-    {file = "typed_ast-1.4.1-cp35-cp35m-win_amd64.whl", hash = "sha256:4083861b0aa07990b619bd7ddc365eb7fa4b817e99cf5f8d9cf21a42780f6e01"},
-    {file = "typed_ast-1.4.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:269151951236b0f9a6f04015a9004084a5ab0d5f19b57de779f908621e7d8b75"},
-    {file = "typed_ast-1.4.1-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:24995c843eb0ad11a4527b026b4dde3da70e1f2d8806c99b7b4a7cf491612652"},
-    {file = "typed_ast-1.4.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:fe460b922ec15dd205595c9b5b99e2f056fd98ae8f9f56b888e7a17dc2b757e7"},
-    {file = "typed_ast-1.4.1-cp36-cp36m-win32.whl", hash = "sha256:4e3e5da80ccbebfff202a67bf900d081906c358ccc3d5e3c8aea42fdfdfd51c1"},
-    {file = "typed_ast-1.4.1-cp36-cp36m-win_amd64.whl", hash = "sha256:249862707802d40f7f29f6e1aad8d84b5aa9e44552d2cc17384b209f091276aa"},
-    {file = "typed_ast-1.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8ce678dbaf790dbdb3eba24056d5364fb45944f33553dd5869b7580cdbb83614"},
-    {file = "typed_ast-1.4.1-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:c9e348e02e4d2b4a8b2eedb48210430658df6951fa484e59de33ff773fbd4b41"},
-    {file = "typed_ast-1.4.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:bcd3b13b56ea479b3650b82cabd6b5343a625b0ced5429e4ccad28a8973f301b"},
-    {file = "typed_ast-1.4.1-cp37-cp37m-win32.whl", hash = "sha256:d5d33e9e7af3b34a40dc05f498939f0ebf187f07c385fd58d591c533ad8562fe"},
-    {file = "typed_ast-1.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:0666aa36131496aed8f7be0410ff974562ab7eeac11ef351def9ea6fa28f6355"},
-    {file = "typed_ast-1.4.1-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:d205b1b46085271b4e15f670058ce182bd1199e56b317bf2ec004b6a44f911f6"},
-    {file = "typed_ast-1.4.1-cp38-cp38-manylinux1_i686.whl", hash = "sha256:6daac9731f172c2a22ade6ed0c00197ee7cc1221aa84cfdf9c31defeb059a907"},
-    {file = "typed_ast-1.4.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:498b0f36cc7054c1fead3d7fc59d2150f4d5c6c56ba7fb150c013fbc683a8d2d"},
-    {file = "typed_ast-1.4.1-cp38-cp38-win32.whl", hash = "sha256:715ff2f2df46121071622063fc7543d9b1fd19ebfc4f5c8895af64a77a8c852c"},
-    {file = "typed_ast-1.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:fc0fea399acb12edbf8a628ba8d2312f583bdbdb3335635db062fa98cf71fca4"},
-    {file = "typed_ast-1.4.1-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:d43943ef777f9a1c42bf4e552ba23ac77a6351de620aa9acf64ad54933ad4d34"},
-    {file = "typed_ast-1.4.1.tar.gz", hash = "sha256:8c8aaad94455178e3187ab22c8b01a3837f8ee50e09cf31f1ba129eb293ec30b"},
+    {file = "typed_ast-1.4.2-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:7703620125e4fb79b64aa52427ec192822e9f45d37d4b6625ab37ef403e1df70"},
+    {file = "typed_ast-1.4.2-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:c9aadc4924d4b5799112837b226160428524a9a45f830e0d0f184b19e4090487"},
+    {file = "typed_ast-1.4.2-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:9ec45db0c766f196ae629e509f059ff05fc3148f9ffd28f3cfe75d4afb485412"},
+    {file = "typed_ast-1.4.2-cp35-cp35m-win32.whl", hash = "sha256:85f95aa97a35bdb2f2f7d10ec5bbdac0aeb9dafdaf88e17492da0504de2e6400"},
+    {file = "typed_ast-1.4.2-cp35-cp35m-win_amd64.whl", hash = "sha256:9044ef2df88d7f33692ae3f18d3be63dec69c4fb1b5a4a9ac950f9b4ba571606"},
+    {file = "typed_ast-1.4.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:c1c876fd795b36126f773db9cbb393f19808edd2637e00fd6caba0e25f2c7b64"},
+    {file = "typed_ast-1.4.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:5dcfc2e264bd8a1db8b11a892bd1647154ce03eeba94b461effe68790d8b8e07"},
+    {file = "typed_ast-1.4.2-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:8db0e856712f79c45956da0c9a40ca4246abc3485ae0d7ecc86a20f5e4c09abc"},
+    {file = "typed_ast-1.4.2-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:d003156bb6a59cda9050e983441b7fa2487f7800d76bdc065566b7d728b4581a"},
+    {file = "typed_ast-1.4.2-cp36-cp36m-win32.whl", hash = "sha256:4c790331247081ea7c632a76d5b2a265e6d325ecd3179d06e9cf8d46d90dd151"},
+    {file = "typed_ast-1.4.2-cp36-cp36m-win_amd64.whl", hash = "sha256:d175297e9533d8d37437abc14e8a83cbc68af93cc9c1c59c2c292ec59a0697a3"},
+    {file = "typed_ast-1.4.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:cf54cfa843f297991b7388c281cb3855d911137223c6b6d2dd82a47ae5125a41"},
+    {file = "typed_ast-1.4.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:b4fcdcfa302538f70929eb7b392f536a237cbe2ed9cba88e3bf5027b39f5f77f"},
+    {file = "typed_ast-1.4.2-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:987f15737aba2ab5f3928c617ccf1ce412e2e321c77ab16ca5a293e7bbffd581"},
+    {file = "typed_ast-1.4.2-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:37f48d46d733d57cc70fd5f30572d11ab8ed92da6e6b28e024e4a3edfb456e37"},
+    {file = "typed_ast-1.4.2-cp37-cp37m-win32.whl", hash = "sha256:36d829b31ab67d6fcb30e185ec996e1f72b892255a745d3a82138c97d21ed1cd"},
+    {file = "typed_ast-1.4.2-cp37-cp37m-win_amd64.whl", hash = "sha256:8368f83e93c7156ccd40e49a783a6a6850ca25b556c0fa0240ed0f659d2fe496"},
+    {file = "typed_ast-1.4.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:963c80b583b0661918718b095e02303d8078950b26cc00b5e5ea9ababe0de1fc"},
+    {file = "typed_ast-1.4.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:e683e409e5c45d5c9082dc1daf13f6374300806240719f95dc783d1fc942af10"},
+    {file = "typed_ast-1.4.2-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:84aa6223d71012c68d577c83f4e7db50d11d6b1399a9c779046d75e24bed74ea"},
+    {file = "typed_ast-1.4.2-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:a38878a223bdd37c9709d07cd357bb79f4c760b29210e14ad0fb395294583787"},
+    {file = "typed_ast-1.4.2-cp38-cp38-win32.whl", hash = "sha256:a2c927c49f2029291fbabd673d51a2180038f8cd5a5b2f290f78c4516be48be2"},
+    {file = "typed_ast-1.4.2-cp38-cp38-win_amd64.whl", hash = "sha256:c0c74e5579af4b977c8b932f40a5464764b2f86681327410aa028a22d2f54937"},
+    {file = "typed_ast-1.4.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:07d49388d5bf7e863f7fa2f124b1b1d89d8aa0e2f7812faff0a5658c01c59aa1"},
+    {file = "typed_ast-1.4.2-cp39-cp39-manylinux1_i686.whl", hash = "sha256:240296b27397e4e37874abb1df2a608a92df85cf3e2a04d0d4d61055c8305ba6"},
+    {file = "typed_ast-1.4.2-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:d746a437cdbca200622385305aedd9aef68e8a645e385cc483bdc5e488f07166"},
+    {file = "typed_ast-1.4.2-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:14bf1522cdee369e8f5581238edac09150c765ec1cb33615855889cf33dcb92d"},
+    {file = "typed_ast-1.4.2-cp39-cp39-win32.whl", hash = "sha256:cc7b98bf58167b7f2db91a4327da24fb93368838eb84a44c472283778fc2446b"},
+    {file = "typed_ast-1.4.2-cp39-cp39-win_amd64.whl", hash = "sha256:7147e2a76c75f0f64c4319886e7639e490fee87c9d25cb1d4faef1d8cf83a440"},
+    {file = "typed_ast-1.4.2.tar.gz", hash = "sha256:9fc0b3cb5d1720e7141d103cf4819aea239f7d136acf9ee4a69b047b7986175a"},
 ]
 typing-extensions = [
     {file = "typing_extensions-3.7.4.3-py2-none-any.whl", hash = "sha256:dafc7639cde7f1b6e1acc0f457842a83e722ccca8eef5270af2d74792619a89f"},
diff --git a/pyproject.toml b/pyproject.toml
index cfb02aa3649f591f00fac32004c0a397e43a09ab..9a388a12d9da6e4e195a175072832dc8ce7a59fc 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
 [tool.poetry]
 name = "AlekSIS-Core"
-version = "2.0a3.dev0"
+version = "2.0a4.dev0"
 packages = [
     { include = "aleksis" }
 ]
@@ -38,7 +38,7 @@ Django = "^3.0"
 django-any-js = "^1.0"
 django-debug-toolbar = "^2.0"
 django-middleware-global-request = "^0.1.2"
-django-menu-generator = "^1.0.4"
+django-menu-generator-ng = "^1.2.0"
 django-tables2 = "^2.1"
 Pillow = "^8.0"
 django-phonenumber-field = {version = "<5.1", extras = ["phonenumbers"]}
@@ -72,7 +72,7 @@ Celery = {version="^5.0.0", optional=true, extras=["django", "redis"]}
 django-celery-results = {version="^2.0.0", optional=true}
 django-celery-beat = {version="^2.0.0", optional=true}
 django-celery-email = {version="^3.0.0", optional=true}
-django-jsonstore = "^0.4.1"
+django-jsonstore = "^0.5.0"
 django-polymorphic = "^3.0.0"
 django-colorfield = "^0.3.0"
 django-bleach = "^0.6.1"
@@ -93,6 +93,7 @@ django-cachalot = "^2.3.2"
 django-prometheus = "^2.1.0"
 importlib-metadata = {version = "^3.0.0", python = "<3.9"}
 django-model-utils = "^4.0.0"
+bs4 = "^0.0.1"
 
 [tool.poetry.extras]
 ldap = ["django-auth-ldap"]
diff --git a/tox.ini b/tox.ini
index 98fce3af53aa48d1eac2e28454c26e7b74c23f72..e1283a1b72150383c5c2c9b7fbf43abb6cdf6ea2 100644
--- a/tox.ini
+++ b/tox.ini
@@ -9,9 +9,11 @@ whitelist_externals = poetry
 skip_install = true
 envdir = {toxworkdir}/globalenv
 commands_pre =
-     - poetry install
+     poetry install
+     poetry run aleksis-admin yarn install
+     poetry run aleksis-admin collectstatic --no-input
 commands =
-    - poetry run pytest --cov=. {posargs} aleksis/
+    poetry run pytest --cov=. {posargs} aleksis/
 
 [testenv:selenium]
 setenv =