Skip to content

Commit 1ac2f7f

Browse files
committed
feat(accounts): add default notification configuration to settings
1 parent 623aed1 commit 1ac2f7f

10 files changed

Lines changed: 282 additions & 76 deletions

File tree

docs/admin/config.rst

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -809,6 +809,106 @@ DEFAULT_MERGE_STYLE
809809
* :ref:`component`
810810
* :ref:`component-merge_style`
811811

812+
.. setting:: DEFAULT_NOTIFICATIONS
813+
814+
DEFAULT_NOTIFICATIONS
815+
---------------------
816+
817+
Default notification settings for every created user.
818+
819+
A list of 3-tuples consisting of notification scope, notification frequency and notification handler.
820+
821+
Scopes:
822+
823+
``0``
824+
:guilabel:`All`
825+
``10``
826+
:guilabel:`Watched`
827+
``20``
828+
:guilabel:`Administered`
829+
``30``
830+
:guilabel:`Project`
831+
``40``
832+
:guilabel:`Component`
833+
834+
Frequencies:
835+
836+
``0``
837+
:guilabel:`No notification`
838+
``1``
839+
:guilabel:`Instant notification`
840+
``2``
841+
:guilabel:`Daily digest`
842+
``3``
843+
:guilabel:`Weekly digest`
844+
``4``
845+
:guilabel:`Monthly digest`
846+
847+
Handlers:
848+
849+
``RepositoryNotification``
850+
:guilabel:`Operation was performed in the repository`
851+
``LockNotification``
852+
:guilabel:`Component was locked or unlocked`
853+
``LicenseNotification``
854+
:guilabel:`License was changed`
855+
``ParseErrorNotification``
856+
:guilabel:`Parse error occurred`
857+
``NewStringNotificaton``
858+
:guilabel:`String is available for translation`
859+
``NewContributorNotificaton``
860+
:guilabel:`Contributor made their first translation`
861+
``NewSuggestionNotificaton``
862+
:guilabel:`Suggestion was added`
863+
``LanguageTranslatedNotificaton``
864+
:guilabel:`Language was translated`
865+
``ComponentTranslatedNotificaton``
866+
:guilabel:`Component was translated`
867+
``NewCommentNotificaton``
868+
:guilabel:`Comment was added`
869+
``MentionCommentNotificaton``
870+
:guilabel:`You were mentioned in a comment`
871+
``LastAuthorCommentNotificaton``
872+
:guilabel:`Your translation received a comment`
873+
``TranslatedStringNotificaton``
874+
:guilabel:`String was edited by user`
875+
``ApprovedStringNotificaton``
876+
:guilabel:`String was approved`
877+
``ChangedStringNotificaton``
878+
:guilabel:`String was changed`
879+
``NewTranslationNotificaton``
880+
:guilabel:`New language was added or requested`
881+
``NewComponentNotificaton``
882+
:guilabel:`New translation component was created`
883+
``NewAnnouncementNotificaton``
884+
:guilabel:`Announcement was published`
885+
``NewAlertNotificaton``
886+
:guilabel:`New alert emerged in a component`
887+
``MergeFailureNotification``
888+
:guilabel:`Repository operation failed`
889+
``PendingSuggestionsNotification``
890+
:guilabel:`Pending suggestions exist`
891+
``ToDoStringsNotification``
892+
:guilabel:`Unfinished strings exist`
893+
894+
.. note::
895+
896+
This setting affects only newly created users.
897+
898+
Example:
899+
900+
.. code-block:: python
901+
902+
DEFAULT_NOTIFICATIONS = [
903+
(0, 1, "MentionCommentNotificaton"),
904+
(10, 1, "LastAuthorCommentNotificaton"),
905+
]
906+
907+
.. seealso::
908+
909+
* :ref:`notifications`
910+
911+
812912
.. setting:: DEFAULT_SHARED_TM
813913

814914
DEFAULT_SHARED_TM

docs/admin/install/docker.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1090,6 +1090,17 @@ Generic settings
10901090

10911091
Configures :setting:`DEFAULT_AUTO_WATCH`.
10921092

1093+
.. envvar:: WEBLATE_DEFAULT_NOTIFICATIONS
1094+
1095+
Configures :setting:`DEFAULT_NOTIFICATIONS`.
1096+
1097+
**Example:**
1098+
1099+
.. code-block:: yaml
1100+
1101+
environment:
1102+
WEBLATE_DEFAULT_NOTIFICATIONS: 0:1:MentionCommentNotificaton,10:1:LastAuthorCommentNotificaton
1103+
10931104
.. envvar:: WEBLATE_RATELIMIT_ATTEMPTS
10941105
.. envvar:: WEBLATE_RATELIMIT_LOCKOUT
10951106
.. envvar:: WEBLATE_RATELIMIT_WINDOW

docs/changes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ Weblate 2026.7
55

66
.. rubric:: New features
77

8+
* Added :setting:`DEFAULT_NOTIFICATIONS` to configure :ref:`notifications` settings for new users.
9+
810
.. rubric:: Improvements
911

1012
* Management interface access control is now more fine-grained with dedicated site-wide permissions.

weblate/accounts/data.py

Lines changed: 0 additions & 71 deletions
This file was deleted.

weblate/accounts/defaults.py

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44

55
from __future__ import annotations
66

7+
from weblate.accounts.notifications import (
8+
NotificationFrequency,
9+
NotificationScope,
10+
)
11+
712
DEFAULT_ENABLE_AVATARS = True
813
DEFAULT_AVATAR_URL_PREFIX = "https://www.gravatar.com/"
914
DEFAULT_AVATAR_DEFAULT_IMAGE = "identicon"
@@ -43,3 +48,56 @@
4348
(10, 3_600),
4449
(50, 86_400),
4550
)
51+
52+
DEFAULT_NOTIFICATIONS: list[tuple[NotificationScope, NotificationFrequency, str]] = [
53+
(
54+
NotificationScope.SCOPE_ALL,
55+
NotificationFrequency.FREQ_INSTANT,
56+
"MentionCommentNotificaton",
57+
),
58+
(
59+
NotificationScope.SCOPE_WATCHED,
60+
NotificationFrequency.FREQ_INSTANT,
61+
"LastAuthorCommentNotificaton",
62+
),
63+
(
64+
NotificationScope.SCOPE_WATCHED,
65+
NotificationFrequency.FREQ_INSTANT,
66+
"MentionCommentNotificaton",
67+
),
68+
(
69+
NotificationScope.SCOPE_WATCHED,
70+
NotificationFrequency.FREQ_INSTANT,
71+
"NewAnnouncementNotificaton",
72+
),
73+
(
74+
NotificationScope.SCOPE_WATCHED,
75+
NotificationFrequency.FREQ_WEEKLY,
76+
"TranslationActivitySummaryNotification",
77+
),
78+
(
79+
NotificationScope.SCOPE_ADMIN,
80+
NotificationFrequency.FREQ_INSTANT,
81+
"MergeFailureNotification",
82+
),
83+
(
84+
NotificationScope.SCOPE_ADMIN,
85+
NotificationFrequency.FREQ_INSTANT,
86+
"ParseErrorNotification",
87+
),
88+
(
89+
NotificationScope.SCOPE_ADMIN,
90+
NotificationFrequency.FREQ_INSTANT,
91+
"NewTranslationNotificaton",
92+
),
93+
(
94+
NotificationScope.SCOPE_ADMIN,
95+
NotificationFrequency.FREQ_INSTANT,
96+
"NewAlertNotificaton",
97+
),
98+
(
99+
NotificationScope.SCOPE_ADMIN,
100+
NotificationFrequency.FREQ_INSTANT,
101+
"NewAnnouncementNotificaton",
102+
),
103+
]

weblate/accounts/models.py

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@
4141
from unidecode import unidecode
4242

4343
from weblate.accounts.avatar import get_user_display
44-
from weblate.accounts.data import create_default_notifications
4544
from weblate.accounts.notifications import (
4645
NOTIFICATIONS,
4746
NotificationFrequency,
@@ -160,6 +159,8 @@ class WeblateAccountsConf(AppConf):
160159

161160
MAXIMAL_PASSWORD_LENGTH = defaults.DEFAULT_MAXIMAL_PASSWORD_LENGTH
162161

162+
DEFAULT_NOTIFICATIONS = defaults.DEFAULT_NOTIFICATIONS
163+
163164
# Multi-level rate limiting for email notifications
164165
# Each tuple contains (max_emails, time_window_seconds)
165166
RATELIMIT_NOTIFICATION_LIMITS: ClassVar[list[tuple[int, int]]] = list(
@@ -1416,3 +1417,13 @@ def create_profile_callback(sender, instance, created=False, **kwargs) -> None:
14161417
# Create subscriptions
14171418
if not instance.is_anonymous and not instance.is_bot:
14181419
create_default_notifications(instance)
1420+
1421+
1422+
def create_default_notifications(user: User) -> None:
1423+
if WeblateAccountsConf.DEFAULT_NOTIFICATIONS:
1424+
for scope, frequency, notification in WeblateAccountsConf.DEFAULT_NOTIFICATIONS:
1425+
user.subscription_set.get_or_create(
1426+
scope=scope,
1427+
notification=notification,
1428+
defaults={"frequency": frequency},
1429+
)

weblate/accounts/tests/test_notifications.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@
1515
from django.test import SimpleTestCase
1616
from django.test.utils import override_settings
1717

18-
from weblate.accounts.data import DEFAULT_NOTIFICATIONS
19-
from weblate.accounts.models import AuditLog, Profile, Subscription
18+
from weblate.accounts.models import AuditLog, Profile, Subscription, WeblateAccountsConf
2019
from weblate.accounts.notifications import (
2120
RECIPIENT_USERNAME_HEADER,
2221
MergeFailureNotification,
@@ -146,15 +145,15 @@ def test_activity_summary_default_notification(self) -> None:
146145
NotificationFrequency.FREQ_WEEKLY,
147146
"TranslationActivitySummaryNotification",
148147
),
149-
DEFAULT_NOTIFICATIONS,
148+
WeblateAccountsConf.DEFAULT_NOTIFICATIONS,
150149
)
151150
self.assertNotIn(
152151
(
153152
NotificationScope.SCOPE_WATCHED,
154153
NotificationFrequency.FREQ_WEEKLY,
155154
"NewStringNotificaton",
156155
),
157-
DEFAULT_NOTIFICATIONS,
156+
WeblateAccountsConf.DEFAULT_NOTIFICATIONS,
158157
)
159158

160159

weblate/settings_docker.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
get_env_ratelimit,
4141
get_env_redis_url,
4242
get_env_str,
43+
get_notification_config,
4344
get_saml_idp,
4445
modify_env_list,
4546
)
@@ -1494,6 +1495,8 @@
14941495
"WEBLATE_DEFAULT_AUTO_WATCH", accounts_defaults.DEFAULT_AUTO_WATCH
14951496
)
14961497

1498+
DEFAULT_NOTIFICATIONS = get_notification_config(accounts_defaults.DEFAULT_NOTIFICATIONS)
1499+
14971500
DEFAULT_SHARED_TM = get_env_bool(
14981501
"WEBLATE_DEFAULT_SHARED_TM", trans_defaults.DEFAULT_SHARED_TM
14991502
)

0 commit comments

Comments
 (0)